blob: 1981f753bbf2948474d2f98ab13bd8c5702c722c [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
78#ifdef WLAN_FEATURE_LINK_LAYER_STATS
79#include "wlan_hdd_stats.h"
80#endif
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080081#include "cds_api.h"
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080082#include "wlan_policy_mgr_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080083#include "qwlan_version.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080084
85#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070086#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080087
Ravi Joshideb5a8d2015-11-09 19:11:43 -080088#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +053089#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070090#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070091#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053092#include "wlan_hdd_disa.h"
Jeff Johnsoncd113fc2017-01-26 14:42:44 -080093#include "wlan_hdd_request_manager.h"
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080094#include "wlan_hdd_he.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -080095
Leo Changfdb45c32016-10-28 11:09:23 -070096#include <cdp_txrx_cmn.h>
97#include <cdp_txrx_misc.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -080098#include <qca_vendor.h>
Mukul Sharma3d36c392017-01-18 18:39:12 +053099#include "wlan_pmo_ucfg_api.h"
Naveen Rawat5f040ba2017-03-06 12:20:25 -0800100#include "os_if_wifi_pos.h"
Ajit Pal Singh90a45a42017-04-18 18:53:46 +0530101#include "wlan_utility.h"
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -0700102#include "wlan_reg_ucfg_api.h"
Naveen Rawatd2657be2017-10-10 14:31:23 -0700103#include "wifi_pos_api.h"
Sandeep Puligilla063a4342018-01-10 02:50:14 -0800104#include "wlan_hdd_spectralscan.h"
Sravan Kumar Kairam858073b2018-03-13 09:03:32 +0530105#include "wlan_ipa_ucfg_api.h"
Naveen Rawate8b1b822018-01-30 09:46:16 -0800106#include <wlan_cfg80211_mc_cp_stats.h>
Yu Wang157d1472018-03-09 16:05:01 +0800107#include <wlan_cp_stats_mc_ucfg_api.h>
Sravan Kumar Kairam858073b2018-03-13 09:03:32 +0530108
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800109#define g_mode_rates_size (12)
110#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800111
112/*
113 * Android CTS verifier needs atleast this much wait time (in msec)
114 */
115#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
116
117/*
118 * Refer @tCfgProtection structure for definition of the bit map.
119 * below value is obtained by setting the following bit-fields.
120 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
121 */
122#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
123
124#define HDD2GHZCHAN(freq, chan, flag) { \
Srinivas Girigowda11c28e02017-06-27 20:06:21 -0700125 .band = HDD_NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800126 .center_freq = (freq), \
127 .hw_value = (chan), \
128 .flags = (flag), \
129 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800130 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800131}
132
133#define HDD5GHZCHAN(freq, chan, flag) { \
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -0700134 .band = HDD_NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800135 .center_freq = (freq), \
136 .hw_value = (chan), \
137 .flags = (flag), \
138 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800139 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800140}
141
142#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
143 { \
144 .bitrate = rate, \
145 .hw_value = rate_id, \
146 .flags = flag, \
147 }
148
Dustin Brown5f7d38e2017-08-16 11:30:08 -0700149#ifndef WLAN_AKM_SUITE_FT_8021X
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800150#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
Dustin Brown5f7d38e2017-08-16 11:30:08 -0700151#endif
152
Dustin Brown234d45f2017-08-16 11:45:05 -0700153#ifndef WLAN_AKM_SUITE_FT_PSK
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800154#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Dustin Brown234d45f2017-08-16 11:45:05 -0700155#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800156
157#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800158
Agrawal Ashish65634612016-08-18 13:24:32 +0530159#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
160 mode <= DFS_MODE_DEPRIORITIZE))
Agrawal Ashish65634612016-08-18 13:24:32 +0530161
Peng Xu4d67c8f2015-10-16 16:02:26 -0700162#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530163#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700164
Mohit Khannaceb97782017-04-05 16:27:08 -0700165/*
166 * Number of DPTRACE records to dump when a cfg80211 disconnect with reason
167 * WLAN_REASON_DEAUTH_LEAVING DEAUTH is received from user-space.
168 */
169#define WLAN_DEAUTH_DPTRACE_DUMP_COUNT 100
Mukul Sharma05504ac2017-06-08 12:35:53 +0530170#ifndef WLAN_CIPHER_SUITE_GCMP
171#define WLAN_CIPHER_SUITE_GCMP 0x000FAC08
172#endif
173#ifndef WLAN_CIPHER_SUITE_GCMP_256
174#define WLAN_CIPHER_SUITE_GCMP_256 0x000FAC09
175#endif
Mohit Khannaceb97782017-04-05 16:27:08 -0700176
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +0530177static const u32 hdd_gcmp_cipher_suits[] = {
178 WLAN_CIPHER_SUITE_GCMP,
179 WLAN_CIPHER_SUITE_GCMP_256,
180};
181
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800182static const u32 hdd_cipher_suites[] = {
183 WLAN_CIPHER_SUITE_WEP40,
184 WLAN_CIPHER_SUITE_WEP104,
185 WLAN_CIPHER_SUITE_TKIP,
186#ifdef FEATURE_WLAN_ESE
187#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
188#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
189 WLAN_CIPHER_SUITE_BTK,
190 WLAN_CIPHER_SUITE_KRK,
191 WLAN_CIPHER_SUITE_CCMP,
192#else
193 WLAN_CIPHER_SUITE_CCMP,
194#endif
195#ifdef FEATURE_WLAN_WAPI
196 WLAN_CIPHER_SUITE_SMS4,
197#endif
198#ifdef WLAN_FEATURE_11W
199 WLAN_CIPHER_SUITE_AES_CMAC,
Padma, Santhosh Kumar4117d7a2017-12-20 17:39:33 +0530200#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
201 WLAN_CIPHER_SUITE_BIP_GMAC_128,
202 WLAN_CIPHER_SUITE_BIP_GMAC_256,
203#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800204#endif
205};
206
Abhishek Singhf512bf32016-05-04 16:47:46 +0530207static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800208 HDD2GHZCHAN(2412, 1, 0),
209 HDD2GHZCHAN(2417, 2, 0),
210 HDD2GHZCHAN(2422, 3, 0),
211 HDD2GHZCHAN(2427, 4, 0),
212 HDD2GHZCHAN(2432, 5, 0),
213 HDD2GHZCHAN(2437, 6, 0),
214 HDD2GHZCHAN(2442, 7, 0),
215 HDD2GHZCHAN(2447, 8, 0),
216 HDD2GHZCHAN(2452, 9, 0),
217 HDD2GHZCHAN(2457, 10, 0),
218 HDD2GHZCHAN(2462, 11, 0),
219 HDD2GHZCHAN(2467, 12, 0),
220 HDD2GHZCHAN(2472, 13, 0),
221 HDD2GHZCHAN(2484, 14, 0),
222};
223
Abhishek Singhf512bf32016-05-04 16:47:46 +0530224static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800225 HDD5GHZCHAN(5180, 36, 0),
226 HDD5GHZCHAN(5200, 40, 0),
227 HDD5GHZCHAN(5220, 44, 0),
228 HDD5GHZCHAN(5240, 48, 0),
229 HDD5GHZCHAN(5260, 52, 0),
230 HDD5GHZCHAN(5280, 56, 0),
231 HDD5GHZCHAN(5300, 60, 0),
232 HDD5GHZCHAN(5320, 64, 0),
233 HDD5GHZCHAN(5500, 100, 0),
234 HDD5GHZCHAN(5520, 104, 0),
235 HDD5GHZCHAN(5540, 108, 0),
236 HDD5GHZCHAN(5560, 112, 0),
237 HDD5GHZCHAN(5580, 116, 0),
238 HDD5GHZCHAN(5600, 120, 0),
239 HDD5GHZCHAN(5620, 124, 0),
240 HDD5GHZCHAN(5640, 128, 0),
241 HDD5GHZCHAN(5660, 132, 0),
242 HDD5GHZCHAN(5680, 136, 0),
243 HDD5GHZCHAN(5700, 140, 0),
244 HDD5GHZCHAN(5720, 144, 0),
245 HDD5GHZCHAN(5745, 149, 0),
246 HDD5GHZCHAN(5765, 153, 0),
247 HDD5GHZCHAN(5785, 157, 0),
248 HDD5GHZCHAN(5805, 161, 0),
249 HDD5GHZCHAN(5825, 165, 0),
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +0530250};
251
252static const struct ieee80211_channel hdd_channels_dot11p[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800253 HDD5GHZCHAN(5852, 170, 0),
254 HDD5GHZCHAN(5855, 171, 0),
255 HDD5GHZCHAN(5860, 172, 0),
256 HDD5GHZCHAN(5865, 173, 0),
257 HDD5GHZCHAN(5870, 174, 0),
258 HDD5GHZCHAN(5875, 175, 0),
259 HDD5GHZCHAN(5880, 176, 0),
260 HDD5GHZCHAN(5885, 177, 0),
261 HDD5GHZCHAN(5890, 178, 0),
262 HDD5GHZCHAN(5895, 179, 0),
263 HDD5GHZCHAN(5900, 180, 0),
264 HDD5GHZCHAN(5905, 181, 0),
265 HDD5GHZCHAN(5910, 182, 0),
266 HDD5GHZCHAN(5915, 183, 0),
267 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800268};
269
270static struct ieee80211_rate g_mode_rates[] = {
271 HDD_G_MODE_RATETAB(10, 0x1, 0),
272 HDD_G_MODE_RATETAB(20, 0x2, 0),
273 HDD_G_MODE_RATETAB(55, 0x4, 0),
274 HDD_G_MODE_RATETAB(110, 0x8, 0),
275 HDD_G_MODE_RATETAB(60, 0x10, 0),
276 HDD_G_MODE_RATETAB(90, 0x20, 0),
277 HDD_G_MODE_RATETAB(120, 0x40, 0),
278 HDD_G_MODE_RATETAB(180, 0x80, 0),
279 HDD_G_MODE_RATETAB(240, 0x100, 0),
280 HDD_G_MODE_RATETAB(360, 0x200, 0),
281 HDD_G_MODE_RATETAB(480, 0x400, 0),
282 HDD_G_MODE_RATETAB(540, 0x800, 0),
283};
284
285static struct ieee80211_rate a_mode_rates[] = {
286 HDD_G_MODE_RATETAB(60, 0x10, 0),
287 HDD_G_MODE_RATETAB(90, 0x20, 0),
288 HDD_G_MODE_RATETAB(120, 0x40, 0),
289 HDD_G_MODE_RATETAB(180, 0x80, 0),
290 HDD_G_MODE_RATETAB(240, 0x100, 0),
291 HDD_G_MODE_RATETAB(360, 0x200, 0),
292 HDD_G_MODE_RATETAB(480, 0x400, 0),
293 HDD_G_MODE_RATETAB(540, 0x800, 0),
294};
295
296static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530297 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800298 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -0700299 .band = HDD_NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800300 .bitrates = g_mode_rates,
301 .n_bitrates = g_mode_rates_size,
302 .ht_cap.ht_supported = 1,
303 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
304 | IEEE80211_HT_CAP_GRN_FLD
305 | IEEE80211_HT_CAP_DSSSCCK40
306 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
307 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
308 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
309 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
310 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
311 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
312 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
313};
314
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800315static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530316 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800317 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Srinivas Girigowda11c28e02017-06-27 20:06:21 -0700318 .band = HDD_NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800319 .bitrates = a_mode_rates,
320 .n_bitrates = a_mode_rates_size,
321 .ht_cap.ht_supported = 1,
322 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
323 | IEEE80211_HT_CAP_GRN_FLD
324 | IEEE80211_HT_CAP_DSSSCCK40
325 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
326 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
327 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
328 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
329 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
330 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
331 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
332 .vht_cap.vht_supported = 1,
333};
334
335/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800336 * TX/RX direction for each kind of interface
337 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800338static const struct ieee80211_txrx_stypes
339 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
340 [NL80211_IFTYPE_STATION] = {
341 .tx = 0xffff,
342 .rx = BIT(SIR_MAC_MGMT_ACTION) |
Padma, Santhosh Kumar1ccc1332017-09-13 17:39:01 +0530343 BIT(SIR_MAC_MGMT_PROBE_REQ) |
344 BIT(SIR_MAC_MGMT_AUTH),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800345 },
346 [NL80211_IFTYPE_AP] = {
347 .tx = 0xffff,
348 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
349 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
350 BIT(SIR_MAC_MGMT_PROBE_REQ) |
351 BIT(SIR_MAC_MGMT_DISASSOC) |
352 BIT(SIR_MAC_MGMT_AUTH) |
353 BIT(SIR_MAC_MGMT_DEAUTH) |
354 BIT(SIR_MAC_MGMT_ACTION),
355 },
356 [NL80211_IFTYPE_ADHOC] = {
357 .tx = 0xffff,
358 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
359 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
360 BIT(SIR_MAC_MGMT_PROBE_REQ) |
361 BIT(SIR_MAC_MGMT_DISASSOC) |
362 BIT(SIR_MAC_MGMT_AUTH) |
363 BIT(SIR_MAC_MGMT_DEAUTH) |
364 BIT(SIR_MAC_MGMT_ACTION),
365 },
366 [NL80211_IFTYPE_P2P_CLIENT] = {
367 .tx = 0xffff,
368 .rx = BIT(SIR_MAC_MGMT_ACTION) |
369 BIT(SIR_MAC_MGMT_PROBE_REQ),
370 },
371 [NL80211_IFTYPE_P2P_GO] = {
372 /* This is also same as for SoftAP */
373 .tx = 0xffff,
374 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
375 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
376 BIT(SIR_MAC_MGMT_PROBE_REQ) |
377 BIT(SIR_MAC_MGMT_DISASSOC) |
378 BIT(SIR_MAC_MGMT_AUTH) |
379 BIT(SIR_MAC_MGMT_DEAUTH) |
380 BIT(SIR_MAC_MGMT_ACTION),
381 },
382};
383
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800384/* Interface limits and combinations registered by the driver */
385
386/* STA ( + STA ) combination */
387static const struct ieee80211_iface_limit
388 wlan_hdd_sta_iface_limit[] = {
389 {
390 .max = 3, /* p2p0 is a STA as well */
391 .types = BIT(NL80211_IFTYPE_STATION),
392 },
393};
394
395/* ADHOC (IBSS) limit */
396static const struct ieee80211_iface_limit
397 wlan_hdd_adhoc_iface_limit[] = {
398 {
399 .max = 1,
400 .types = BIT(NL80211_IFTYPE_STATION),
401 },
402 {
403 .max = 1,
404 .types = BIT(NL80211_IFTYPE_ADHOC),
405 },
406};
407
408/* AP ( + AP ) combination */
409static const struct ieee80211_iface_limit
410 wlan_hdd_ap_iface_limit[] = {
411 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530412 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800413 .types = BIT(NL80211_IFTYPE_AP),
414 },
415};
416
417/* P2P limit */
418static const struct ieee80211_iface_limit
419 wlan_hdd_p2p_iface_limit[] = {
420 {
421 .max = 1,
422 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
423 },
424 {
425 .max = 1,
426 .types = BIT(NL80211_IFTYPE_P2P_GO),
427 },
428};
429
430static const struct ieee80211_iface_limit
431 wlan_hdd_sta_ap_iface_limit[] = {
432 {
433 /* We need 1 extra STA interface for OBSS scan when SAP starts
434 * with HT40 in STA+SAP concurrency mode
435 */
436 .max = (1 + SAP_MAX_OBSS_STA_CNT),
437 .types = BIT(NL80211_IFTYPE_STATION),
438 },
439 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530440 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800441 .types = BIT(NL80211_IFTYPE_AP),
442 },
443};
444
445/* STA + P2P combination */
446static const struct ieee80211_iface_limit
447 wlan_hdd_sta_p2p_iface_limit[] = {
448 {
449 /* One reserved for dedicated P2PDEV usage */
450 .max = 2,
451 .types = BIT(NL80211_IFTYPE_STATION)
452 },
453 {
454 /* Support for two identical (GO + GO or CLI + CLI)
455 * or dissimilar (GO + CLI) P2P interfaces
456 */
457 .max = 2,
458 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
459 },
460};
461
462/* STA + AP + P2PGO combination */
463static const struct ieee80211_iface_limit
464wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
465 /* Support for AP+P2PGO interfaces */
466 {
467 .max = 2,
468 .types = BIT(NL80211_IFTYPE_STATION)
469 },
470 {
471 .max = 1,
472 .types = BIT(NL80211_IFTYPE_P2P_GO)
473 },
474 {
475 .max = 1,
476 .types = BIT(NL80211_IFTYPE_AP)
477 }
478};
479
480/* SAP + P2P combination */
481static const struct ieee80211_iface_limit
482wlan_hdd_sap_p2p_iface_limit[] = {
483 {
484 /* 1 dedicated for p2p0 which is a STA type */
485 .max = 1,
486 .types = BIT(NL80211_IFTYPE_STATION)
487 },
488 {
489 /* The p2p interface in SAP+P2P can be GO/CLI.
490 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
491 */
492 .max = 1,
493 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
494 },
495 {
496 /* SAP+GO to support only one SAP interface */
497 .max = 1,
498 .types = BIT(NL80211_IFTYPE_AP)
499 }
500};
501
502/* P2P + P2P combination */
503static const struct ieee80211_iface_limit
504wlan_hdd_p2p_p2p_iface_limit[] = {
505 {
506 /* 1 dedicated for p2p0 which is a STA type */
507 .max = 1,
508 .types = BIT(NL80211_IFTYPE_STATION)
509 },
510 {
511 /* The p2p interface in P2P+P2P can be GO/CLI.
512 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
513 */
514 .max = 2,
515 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
516 },
517};
518
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700519static const struct ieee80211_iface_limit
520 wlan_hdd_mon_iface_limit[] = {
521 {
522 .max = 3, /* Monitor interface */
523 .types = BIT(NL80211_IFTYPE_MONITOR),
524 },
525};
526
527static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800528 wlan_hdd_iface_combination[] = {
529 /* STA */
530 {
531 .limits = wlan_hdd_sta_iface_limit,
532 .num_different_channels = 2,
533 .max_interfaces = 3,
534 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
535 },
536 /* ADHOC */
537 {
538 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700539 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800540 .max_interfaces = 2,
541 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
542 },
543 /* AP */
544 {
545 .limits = wlan_hdd_ap_iface_limit,
546 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530547 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800548 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
hqu3c4ed3d2017-09-19 11:42:35 +0800549#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) || \
550 defined(CFG80211_BEACON_INTERVAL_BACKPORT)
551 .beacon_int_min_gcd = 1,
552#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800553 },
554 /* P2P */
555 {
556 .limits = wlan_hdd_p2p_iface_limit,
557 .num_different_channels = 2,
558 .max_interfaces = 2,
559 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
560 },
561 /* STA + AP */
562 {
563 .limits = wlan_hdd_sta_ap_iface_limit,
564 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530565 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800566 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
567 .beacon_int_infra_match = true,
hqu3c4ed3d2017-09-19 11:42:35 +0800568#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) || \
569 defined(CFG80211_BEACON_INTERVAL_BACKPORT)
570 .beacon_int_min_gcd = 1,
571#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800572 },
573 /* STA + P2P */
574 {
575 .limits = wlan_hdd_sta_p2p_iface_limit,
576 .num_different_channels = 2,
577 /* one interface reserved for P2PDEV dedicated usage */
578 .max_interfaces = 4,
579 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
580 .beacon_int_infra_match = true,
581 },
582 /* STA + P2P GO + SAP */
583 {
584 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
585 /* we can allow 3 channels for three different persona
586 * but due to firmware limitation, allow max 2 concrnt channels.
587 */
588 .num_different_channels = 2,
589 /* one interface reserved for P2PDEV dedicated usage */
590 .max_interfaces = 4,
591 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
592 .beacon_int_infra_match = true,
593 },
594 /* SAP + P2P */
595 {
596 .limits = wlan_hdd_sap_p2p_iface_limit,
597 .num_different_channels = 2,
598 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
599 .max_interfaces = 3,
600 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
601 .beacon_int_infra_match = true,
602 },
603 /* P2P + P2P */
604 {
605 .limits = wlan_hdd_p2p_p2p_iface_limit,
606 .num_different_channels = 2,
607 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
608 .max_interfaces = 3,
609 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
610 .beacon_int_infra_match = true,
611 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530612 /* Monitor */
613 {
614 .limits = wlan_hdd_mon_iface_limit,
615 .max_interfaces = 3,
616 .num_different_channels = 2,
617 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
618 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800619};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800620
621static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800622
623#ifdef WLAN_NL80211_TESTMODE
624enum wlan_hdd_tm_attr {
625 WLAN_HDD_TM_ATTR_INVALID = 0,
626 WLAN_HDD_TM_ATTR_CMD = 1,
627 WLAN_HDD_TM_ATTR_DATA = 2,
628 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
629 WLAN_HDD_TM_ATTR_TYPE = 4,
630 /* keep last */
631 WLAN_HDD_TM_ATTR_AFTER_LAST,
632 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
633};
634
635enum wlan_hdd_tm_cmd {
636 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
637 WLAN_HDD_TM_CMD_WLAN_HB = 1,
638};
639
640#define WLAN_HDD_TM_DATA_MAX_LEN 5000
641
642static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
643 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
644 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
645 .len = WLAN_HDD_TM_DATA_MAX_LEN},
646};
647#endif /* WLAN_NL80211_TESTMODE */
648
Lin Baia016e9a2017-08-29 19:10:42 +0800649enum wlan_hdd_vendor_ie_access_policy {
650 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
651 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
652};
653
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800654#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
655static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
656 .flags = WIPHY_WOWLAN_MAGIC_PKT,
657 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
658 .pattern_min_len = 1,
659 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
660};
661#endif
662
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800663/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530664 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
665 * @flags: Pointer to the flags to Add channel switch flag.
666 *
667 * This Function adds Channel Switch support flag, if channel switch is
668 * supported by kernel.
669 * Return: void.
670 */
671#ifdef CHANNEL_SWITCH_SUPPORTED
672static inline void hdd_add_channel_switch_support(uint32_t *flags)
673{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800674 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530675}
676#else
677static inline void hdd_add_channel_switch_support(uint32_t *flags)
678{
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530679}
680#endif
681
Manikandan Mohan22b83722015-12-15 15:03:23 -0800682#ifdef FEATURE_WLAN_TDLS
683
684/* TDLS capabilities params */
685#define PARAM_MAX_TDLS_SESSION \
686 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
687#define PARAM_TDLS_FEATURE_SUPPORT \
688 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
689
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530690/**
Jeff Johnson118a4a02018-05-06 00:14:15 -0700691 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilities.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800692 * @wiphy: WIPHY structure pointer
693 * @wdev: Wireless device structure pointer
694 * @data: Pointer to the data received
695 * @data_len: Length of the data received
696 *
697 * This function provides TDLS capabilities
698 *
699 * Return: 0 on success and errno on failure
700 */
701static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
702 struct wireless_dev *wdev,
703 const void *data,
704 int data_len)
705{
706 int status;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -0700707 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800708 struct sk_buff *skb;
709 uint32_t set = 0;
Frank Liu5c63dc82017-09-07 14:49:05 +0800710 uint32_t max_num_tdls_sta = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800711
Dustin Brownfdf17c12018-03-14 12:55:34 -0700712 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -0800713
Anurag Chouhan6d760662016-02-20 16:05:43 +0530714 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800715 hdd_err("Command not allowed in FTM mode");
716 return -EPERM;
717 }
718
719 status = wlan_hdd_validate_context(hdd_ctx);
720 if (status)
721 return status;
722
723 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
724 NLMSG_HDRLEN);
725 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700726 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800727 goto fail;
728 }
729
730 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800731 hdd_debug("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800732 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
733 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700734 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800735 goto fail;
736 }
737 } else {
738 set = set | WIFI_TDLS_SUPPORT;
739 set = set | (hdd_ctx->config->fTDLSExternalControl ?
740 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
741 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
742 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Frank Liu5c63dc82017-09-07 14:49:05 +0800743 if (hdd_ctx->config->fEnableTDLSSleepSta ||
744 hdd_ctx->config->fEnableTDLSBufferSta ||
745 hdd_ctx->config->fEnableTDLSOffChannel)
746 max_num_tdls_sta = HDD_MAX_NUM_TDLS_STA_P_UAPSD_OFFCHAN;
747 else
748 max_num_tdls_sta = HDD_MAX_NUM_TDLS_STA;
749
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800750 hdd_debug("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800751 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
Frank Liu5c63dc82017-09-07 14:49:05 +0800752 max_num_tdls_sta) ||
753 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700754 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800755 goto fail;
756 }
757 }
758 return cfg80211_vendor_cmd_reply(skb);
759fail:
760 if (skb)
761 kfree_skb(skb);
762 return -EINVAL;
763}
764
765/**
Jeff Johnson118a4a02018-05-06 00:14:15 -0700766 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilities.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800767 * @wiphy: WIPHY structure pointer
768 * @wdev: Wireless device structure pointer
769 * @data: Pointer to the data received
770 * @data_len: Length of the data received
771 *
772 * This function provides TDLS capabilities
773 *
774 * Return: 0 on success and errno on failure
775 */
776static int
777wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
778 struct wireless_dev *wdev,
779 const void *data,
780 int data_len)
781{
782 int ret;
783
784 cds_ssr_protect(__func__);
785 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
786 data, data_len);
787 cds_ssr_unprotect(__func__);
788
789 return ret;
790}
791#endif
792
793#ifdef QCA_HT_2040_COEX
794static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
795#endif
796
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700797int wlan_hdd_merge_avoid_freqs(struct ch_avoid_ind_type *destFreqList,
798 struct ch_avoid_ind_type *srcFreqList)
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530799{
800 int i;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700801 struct ch_avoid_freq_type *avoid_range =
802 &destFreqList->avoid_freq_range[destFreqList->ch_avoid_range_cnt];
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530803
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700804 destFreqList->ch_avoid_range_cnt += srcFreqList->ch_avoid_range_cnt;
Jeff Johnson31304cc2017-09-30 19:08:09 -0700805 if (destFreqList->ch_avoid_range_cnt > CH_AVOID_MAX_RANGE) {
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530806 hdd_err("avoid freq overflow");
807 return -EINVAL;
808 }
809
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700810 for (i = 0; i < srcFreqList->ch_avoid_range_cnt; i++) {
811 avoid_range->start_freq =
812 srcFreqList->avoid_freq_range[i].start_freq;
813 avoid_range->end_freq =
814 srcFreqList->avoid_freq_range[i].end_freq;
815 avoid_range++;
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530816 }
817 return 0;
818}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800819/*
820 * FUNCTION: wlan_hdd_send_avoid_freq_event
821 * This is called when wlan driver needs to send vendor specific
822 * avoid frequency range event to userspace
823 */
Jeff Johnsonb8944722017-09-03 09:03:19 -0700824int wlan_hdd_send_avoid_freq_event(struct hdd_context *hdd_ctx,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700825 struct ch_avoid_ind_type *avoid_freq_list)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800826{
827 struct sk_buff *vendor_event;
828
Dustin Brown491d54b2018-03-14 12:39:11 -0700829 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800830
Jeff Johnsonb8944722017-09-03 09:03:19 -0700831 if (!hdd_ctx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700832 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800833 return -EINVAL;
834 }
835
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700836 if (!avoid_freq_list) {
837 hdd_err("avoid_freq_list is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800838 return -EINVAL;
839 }
840
Jeff Johnsonb8944722017-09-03 09:03:19 -0700841 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700842 NULL, sizeof(struct ch_avoid_ind_type),
843 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
844 GFP_KERNEL);
845
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800846 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700847 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800848 return -EINVAL;
849 }
850
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700851 memcpy(skb_put(vendor_event, sizeof(struct ch_avoid_ind_type)),
852 (void *)avoid_freq_list, sizeof(struct ch_avoid_ind_type));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800853
854 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
855
Dustin Browne74003f2018-03-14 12:51:58 -0700856 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800857 return 0;
858}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800859
Anurag Chouhan4085ff72017-10-05 18:09:56 +0530860/*
861 * define short names for the global vendor params
862 * used by QCA_NL80211_VENDOR_SUBCMD_HANG
863 */
864#define HANG_REASON_INDEX QCA_NL80211_VENDOR_SUBCMD_HANG_REASON_INDEX
865
866/**
867 * hdd_convert_hang_reason() - Convert cds recovery reason to vendor specific
868 * hang reason
869 * @reason: cds recovery reason
870 *
871 * Return: Vendor specific reason code
872 */
873static enum qca_wlan_vendor_hang_reason
874hdd_convert_hang_reason(enum qdf_hang_reason reason)
875{
Mahesh Kumar Kalikot Veetil9111a572017-10-10 16:11:11 -0700876 u32 ret_val;
Anurag Chouhan4085ff72017-10-05 18:09:56 +0530877
878 switch (reason) {
879 case QDF_RX_HASH_NO_ENTRY_FOUND:
880 ret_val = QCA_WLAN_HANG_RX_HASH_NO_ENTRY_FOUND;
881 break;
882 case QDF_PEER_DELETION_TIMEDOUT:
883 ret_val = QCA_WLAN_HANG_PEER_DELETION_TIMEDOUT;
884 break;
885 case QDF_PEER_UNMAP_TIMEDOUT:
886 ret_val = QCA_WLAN_HANG_PEER_UNMAP_TIMEDOUT;
887 break;
888 case QDF_SCAN_REQ_EXPIRED:
889 ret_val = QCA_WLAN_HANG_SCAN_REQ_EXPIRED;
890 break;
891 case QDF_SCAN_ATTEMPT_FAILURES:
892 ret_val = QCA_WLAN_HANG_SCAN_ATTEMPT_FAILURES;
893 break;
894 case QDF_GET_MSG_BUFF_FAILURE:
895 ret_val = QCA_WLAN_HANG_GET_MSG_BUFF_FAILURE;
896 break;
897 case QDF_ACTIVE_LIST_TIMEOUT:
898 ret_val = QCA_WLAN_HANG_ACTIVE_LIST_TIMEOUT;
899 break;
900 case QDF_SUSPEND_TIMEOUT:
901 ret_val = QCA_WLAN_HANG_SUSPEND_TIMEOUT;
902 break;
903 case QDF_RESUME_TIMEOUT:
904 ret_val = QCA_WLAN_HANG_RESUME_TIMEOUT;
905 break;
906 case QDF_REASON_UNSPECIFIED:
907 default:
908 ret_val = QCA_WLAN_HANG_REASON_UNSPECIFIED;
909 }
910 return ret_val;
911}
912
913/**
914 * wlan_hdd_send_hang_reason_event() - Send hang reason to the userspace
915 * @hdd_ctx: Pointer to hdd context
916 * @reason: cds recovery reason
917 *
918 * Return: 0 on success or failure reason
919 */
920int wlan_hdd_send_hang_reason_event(struct hdd_context *hdd_ctx,
921 enum qdf_hang_reason reason)
922{
923 struct sk_buff *vendor_event;
924 enum qca_wlan_vendor_hang_reason hang_reason;
925
Dustin Brown491d54b2018-03-14 12:39:11 -0700926 hdd_enter();
Anurag Chouhan4085ff72017-10-05 18:09:56 +0530927
928 if (!hdd_ctx) {
929 hdd_err("HDD context is null");
930 return -EINVAL;
931 }
932
933 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
934 NULL,
935 sizeof(uint32_t),
936 HANG_REASON_INDEX,
937 GFP_KERNEL);
938 if (!vendor_event) {
939 hdd_err("cfg80211_vendor_event_alloc failed");
940 return -ENOMEM;
941 }
942
943 hang_reason = hdd_convert_hang_reason(reason);
944
945 if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_HANG_REASON,
Mahesh Kumar Kalikot Veetil9111a572017-10-10 16:11:11 -0700946 (uint32_t)hang_reason)) {
Anurag Chouhan4085ff72017-10-05 18:09:56 +0530947 hdd_err("QCA_WLAN_VENDOR_ATTR_HANG_REASON put fail");
948 kfree_skb(vendor_event);
949 return -EINVAL;
950 }
951
952 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
953
Dustin Browne74003f2018-03-14 12:51:58 -0700954 hdd_exit();
Anurag Chouhan4085ff72017-10-05 18:09:56 +0530955 return 0;
956}
Mahesh Kumar Kalikot Veetil9111a572017-10-10 16:11:11 -0700957
Anurag Chouhan4085ff72017-10-05 18:09:56 +0530958#undef HANG_REASON_INDEX
959
Ajit Pal Singh5edd6982017-05-10 11:04:13 +0530960/**
961 * wlan_hdd_get_adjacent_chan(): Gets next/previous channel
962 * with respect to the channel passed.
963 * @chan: Channel
964 * @upper: If "true" then next channel is returned or else
965 * previous channel is returned.
966 *
967 * This function returns the next/previous adjacent-channel to
968 * the channel passed. If "upper = true" then next channel is
969 * returned else previous is returned.
970 */
971int wlan_hdd_get_adjacent_chan(uint8_t chan, bool upper)
972{
973 enum channel_enum ch_idx = reg_get_chan_enum(chan);
974
975 if (ch_idx == INVALID_CHANNEL)
976 return -EINVAL;
977
978 if (upper && (ch_idx < (NUM_CHANNELS - 1)))
979 ch_idx++;
980 else if (!upper && (ch_idx > CHAN_ENUM_1))
981 ch_idx--;
982 else
983 return -EINVAL;
984
985 return WLAN_REG_CH_NUM(ch_idx);
986}
987
988/**
989 * wlan_hdd_send_avoid_freq_for_dnbs(): Sends list of frequencies to be
990 * avoided when Do_Not_Break_Stream is active.
Jeff Johnsonb8944722017-09-03 09:03:19 -0700991 * @hdd_ctx: HDD Context
Ajit Pal Singh5edd6982017-05-10 11:04:13 +0530992 * @op_chan: AP/P2P-GO operating channel
993 *
994 * This function sends list of frequencies to be avoided when
995 * Do_Not_Break_Stream is active.
996 * To clear the avoid_frequency_list in the application,
997 * op_chan = 0 can be passed.
998 *
999 * Return: 0 on success and errno on failure
1000 */
Jeff Johnsonb8944722017-09-03 09:03:19 -07001001int wlan_hdd_send_avoid_freq_for_dnbs(struct hdd_context *hdd_ctx, uint8_t op_chan)
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301002{
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001003 struct ch_avoid_ind_type p2p_avoid_freq_list;
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301004 uint8_t min_chan, max_chan;
1005 int ret;
1006 int chan;
1007
Dustin Brown491d54b2018-03-14 12:39:11 -07001008 hdd_enter();
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301009
Jeff Johnsonb8944722017-09-03 09:03:19 -07001010 if (!hdd_ctx) {
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301011 hdd_err("invalid param");
1012 return -EINVAL;
1013 }
1014
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001015 qdf_mem_zero(&p2p_avoid_freq_list, sizeof(struct ch_avoid_ind_type));
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301016 /*
1017 * If channel passed is zero, clear the avoid_freq list in application.
1018 */
1019 if (!op_chan) {
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301020#ifdef FEATURE_WLAN_CH_AVOID
Jeff Johnsonb8944722017-09-03 09:03:19 -07001021 mutex_lock(&hdd_ctx->avoid_freq_lock);
1022 qdf_mem_zero(&hdd_ctx->dnbs_avoid_freq_list,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001023 sizeof(struct ch_avoid_ind_type));
Jeff Johnsonb8944722017-09-03 09:03:19 -07001024 if (hdd_ctx->coex_avoid_freq_list.ch_avoid_range_cnt)
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301025 memcpy(&p2p_avoid_freq_list,
Jeff Johnsonb8944722017-09-03 09:03:19 -07001026 &hdd_ctx->coex_avoid_freq_list,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001027 sizeof(struct ch_avoid_ind_type));
Jeff Johnsonb8944722017-09-03 09:03:19 -07001028 mutex_unlock(&hdd_ctx->avoid_freq_lock);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301029#endif
Jeff Johnsonb8944722017-09-03 09:03:19 -07001030 ret = wlan_hdd_send_avoid_freq_event(hdd_ctx,
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301031 &p2p_avoid_freq_list);
1032 if (ret)
1033 hdd_err("wlan_hdd_send_avoid_freq_event error:%d",
1034 ret);
1035
1036 return ret;
1037 }
1038
1039 if (WLAN_REG_IS_24GHZ_CH(op_chan)) {
1040 min_chan = REG_MIN_24GHZ_CH_NUM;
1041 max_chan = REG_MAX_24GHZ_CH_NUM;
1042 } else if WLAN_REG_IS_5GHZ_CH(op_chan) {
1043 min_chan = REG_MIN_5GHZ_CH_NUM;
1044 max_chan = REG_MAX_5GHZ_CH_NUM;
1045 } else {
1046 hdd_err("invalid channel:%d", op_chan);
1047 return -EINVAL;
1048 }
1049
1050 if ((op_chan > min_chan) && (op_chan < max_chan)) {
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001051 p2p_avoid_freq_list.ch_avoid_range_cnt = 2;
1052 p2p_avoid_freq_list.avoid_freq_range[0].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301053 wlan_chan_to_freq(min_chan);
1054
1055 /* Get channel before the op_chan */
1056 chan = wlan_hdd_get_adjacent_chan(op_chan, false);
1057 if (chan < 0)
1058 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001059 p2p_avoid_freq_list.avoid_freq_range[0].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301060 wlan_chan_to_freq(chan);
1061
1062 /* Get channel next to the op_chan */
1063 chan = wlan_hdd_get_adjacent_chan(op_chan, true);
1064 if (chan < 0)
1065 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001066 p2p_avoid_freq_list.avoid_freq_range[1].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301067 wlan_chan_to_freq(chan);
1068
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001069 p2p_avoid_freq_list.avoid_freq_range[1].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301070 wlan_chan_to_freq(max_chan);
1071 } else if (op_chan == min_chan) {
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001072 p2p_avoid_freq_list.ch_avoid_range_cnt = 1;
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301073
1074 chan = wlan_hdd_get_adjacent_chan(op_chan, true);
1075 if (chan < 0)
1076 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001077 p2p_avoid_freq_list.avoid_freq_range[0].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301078 wlan_chan_to_freq(chan);
1079
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001080 p2p_avoid_freq_list.avoid_freq_range[0].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301081 wlan_chan_to_freq(max_chan);
1082 } else {
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001083 p2p_avoid_freq_list.ch_avoid_range_cnt = 1;
1084 p2p_avoid_freq_list.avoid_freq_range[0].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301085 wlan_chan_to_freq(min_chan);
1086
1087 chan = wlan_hdd_get_adjacent_chan(op_chan, false);
1088 if (chan < 0)
1089 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001090 p2p_avoid_freq_list.avoid_freq_range[0].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301091 wlan_chan_to_freq(chan);
1092 }
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301093#ifdef FEATURE_WLAN_CH_AVOID
Jeff Johnsonb8944722017-09-03 09:03:19 -07001094 mutex_lock(&hdd_ctx->avoid_freq_lock);
1095 hdd_ctx->dnbs_avoid_freq_list = p2p_avoid_freq_list;
1096 if (hdd_ctx->coex_avoid_freq_list.ch_avoid_range_cnt) {
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301097 ret = wlan_hdd_merge_avoid_freqs(&p2p_avoid_freq_list,
Jeff Johnsonb8944722017-09-03 09:03:19 -07001098 &hdd_ctx->coex_avoid_freq_list);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301099 if (ret) {
Jeff Johnsonb8944722017-09-03 09:03:19 -07001100 mutex_unlock(&hdd_ctx->avoid_freq_lock);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301101 hdd_err("avoid freq merge failed");
1102 return ret;
1103 }
1104 }
Jeff Johnsonb8944722017-09-03 09:03:19 -07001105 mutex_unlock(&hdd_ctx->avoid_freq_lock);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301106#endif
Jeff Johnsonb8944722017-09-03 09:03:19 -07001107 ret = wlan_hdd_send_avoid_freq_event(hdd_ctx, &p2p_avoid_freq_list);
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301108 if (ret)
1109 hdd_err("wlan_hdd_send_avoid_freq_event error:%d", ret);
1110
1111 return ret;
1112}
1113
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001114/* vendor specific events */
1115static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001116 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
1117 .vendor_id =
1118 QCA_NL80211_VENDOR_ID,
1119 .subcmd =
1120 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
1121 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001122
1123#ifdef WLAN_FEATURE_NAN
1124 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
1125 .vendor_id =
1126 QCA_NL80211_VENDOR_ID,
1127 .subcmd =
1128 QCA_NL80211_VENDOR_SUBCMD_NAN
1129 },
1130#endif
1131
1132#ifdef WLAN_FEATURE_STATS_EXT
1133 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
1134 .vendor_id =
1135 QCA_NL80211_VENDOR_ID,
1136 .subcmd =
1137 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
1138 },
1139#endif /* WLAN_FEATURE_STATS_EXT */
1140#ifdef FEATURE_WLAN_EXTSCAN
1141 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
1142 .vendor_id =
1143 QCA_NL80211_VENDOR_ID,
1144 .subcmd =
1145 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
1146 },
1147 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
1148 .vendor_id =
1149 QCA_NL80211_VENDOR_ID,
1150 .subcmd =
1151 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
1152 },
1153 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
1154 .
1155 vendor_id
1156 =
1157 QCA_NL80211_VENDOR_ID,
1158 .subcmd =
1159 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
1160 },
1161 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
1162 .
1163 vendor_id
1164 =
1165 QCA_NL80211_VENDOR_ID,
1166 .
1167 subcmd =
1168 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
1169 },
1170 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
1171 .
1172 vendor_id
1173 =
1174 QCA_NL80211_VENDOR_ID,
1175 .
1176 subcmd
1177 =
1178 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
1179 },
1180 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
1181 .
1182 vendor_id
1183 =
1184 QCA_NL80211_VENDOR_ID,
1185 .subcmd =
1186 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
1187 },
1188 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
1189 .vendor_id =
1190 QCA_NL80211_VENDOR_ID,
1191 .subcmd =
1192 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
1193 },
1194 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
1195 .
1196 vendor_id
1197 =
1198 QCA_NL80211_VENDOR_ID,
1199 .subcmd =
1200 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
1201 },
1202 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
1203 .
1204 vendor_id
1205 =
1206 QCA_NL80211_VENDOR_ID,
1207 .subcmd =
1208 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
1209 },
1210 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
1211 .
1212 vendor_id
1213 =
1214 QCA_NL80211_VENDOR_ID,
1215 .
1216 subcmd
1217 =
1218 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
1219 },
1220 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
1221 .
1222 vendor_id
1223 =
1224 QCA_NL80211_VENDOR_ID,
1225 .
1226 subcmd =
1227 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
1228 },
1229 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
1230 .
1231 vendor_id
1232 =
1233 QCA_NL80211_VENDOR_ID,
1234 .
1235 subcmd
1236 =
1237 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
1238 },
1239 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
1240 .
1241 vendor_id
1242 =
1243 QCA_NL80211_VENDOR_ID,
1244 .
1245 subcmd
1246 =
1247 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
1248 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001249#endif /* FEATURE_WLAN_EXTSCAN */
1250
1251#ifdef WLAN_FEATURE_LINK_LAYER_STATS
1252 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
1253 .vendor_id =
1254 QCA_NL80211_VENDOR_ID,
1255 .subcmd =
1256 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
1257 },
1258 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
1259 .vendor_id =
1260 QCA_NL80211_VENDOR_ID,
1261 .subcmd =
1262 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
1263 },
1264 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
1265 .vendor_id =
1266 QCA_NL80211_VENDOR_ID,
1267 .subcmd =
1268 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
1269 },
1270 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
1271 .vendor_id =
1272 QCA_NL80211_VENDOR_ID,
1273 .subcmd =
1274 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
1275 },
1276 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
1277 .vendor_id =
1278 QCA_NL80211_VENDOR_ID,
1279 .subcmd =
1280 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
1281 },
1282 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
1283 .vendor_id =
1284 QCA_NL80211_VENDOR_ID,
1285 .subcmd =
1286 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
1287 },
Zhang Qianca38fb12016-12-23 11:10:48 +08001288 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX] = {
1289 .vendor_id =
1290 QCA_NL80211_VENDOR_ID,
1291 .subcmd =
1292 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT
1293 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001294#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
1295 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
1296 .vendor_id =
1297 QCA_NL80211_VENDOR_ID,
1298 .subcmd =
1299 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
1300 },
1301 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
1302 .vendor_id = QCA_NL80211_VENDOR_ID,
1303 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
1304 },
1305#ifdef WLAN_FEATURE_ROAM_OFFLOAD
1306 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
1307 .vendor_id =
1308 QCA_NL80211_VENDOR_ID,
1309 .subcmd =
1310 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1311 },
1312#endif
1313 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1314 .vendor_id =
1315 QCA_NL80211_VENDOR_ID,
1316 .subcmd =
1317 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1318 },
1319 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1320 .vendor_id =
1321 QCA_NL80211_VENDOR_ID,
1322 .subcmd =
1323 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1324 },
1325 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1326 .vendor_id =
1327 QCA_NL80211_VENDOR_ID,
1328 .subcmd =
1329 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1330 },
1331 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1332 .vendor_id =
1333 QCA_NL80211_VENDOR_ID,
1334 .subcmd =
1335 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1336 },
1337 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1338 .vendor_id =
1339 QCA_NL80211_VENDOR_ID,
1340 .subcmd =
1341 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1342 },
1343#ifdef FEATURE_WLAN_EXTSCAN
1344 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1345 .vendor_id = QCA_NL80211_VENDOR_ID,
1346 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1347 },
1348 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1349 .vendor_id = QCA_NL80211_VENDOR_ID,
1350 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1351 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001352 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1353 .vendor_id = QCA_NL80211_VENDOR_ID,
1354 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1355 },
1356#endif /* FEATURE_WLAN_EXTSCAN */
1357 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1358 .vendor_id = QCA_NL80211_VENDOR_ID,
1359 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1360 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001361#ifdef WLAN_FEATURE_TSF
1362 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1363 .vendor_id = QCA_NL80211_VENDOR_ID,
1364 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1365 },
1366#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001367 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1368 .vendor_id = QCA_NL80211_VENDOR_ID,
1369 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1370 },
1371 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1372 .vendor_id = QCA_NL80211_VENDOR_ID,
1373 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1374 },
1375 /* OCB events */
1376 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1377 .vendor_id = QCA_NL80211_VENDOR_ID,
1378 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1379 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001380#ifdef FEATURE_LFR_SUBNET_DETECTION
1381 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1382 .vendor_id = QCA_NL80211_VENDOR_ID,
1383 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1384 },
1385#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001386
1387#ifdef WLAN_FEATURE_NAN_DATAPATH
1388 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1389 .vendor_id = QCA_NL80211_VENDOR_ID,
1390 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1391 },
1392#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001393
1394 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1395 .vendor_id = QCA_NL80211_VENDOR_ID,
1396 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1397 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301398 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1399 .vendor_id = QCA_NL80211_VENDOR_ID,
1400 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1401 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301402 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1403 .vendor_id = QCA_NL80211_VENDOR_ID,
1404 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1405 },
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05301406 [QCA_NL80211_VENDOR_SUBCMD_PWR_SAVE_FAIL_DETECTED_INDEX] = {
1407 .vendor_id = QCA_NL80211_VENDOR_ID,
1408 .subcmd = QCA_NL80211_VENDOR_SUBCMD_CHIP_PWRSAVE_FAILURE
Anurag Chouhan3920c0f2017-09-11 17:10:56 +05301409 },
1410 [QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET_INDEX] = {
1411 .vendor_id = QCA_NL80211_VENDOR_ID,
1412 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET,
1413 },
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301414 [QCA_NL80211_VENDOR_SUBCMD_HANG_REASON_INDEX] = {
1415 .vendor_id = QCA_NL80211_VENDOR_ID,
1416 .subcmd = QCA_NL80211_VENDOR_SUBCMD_HANG,
1417 },
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +05301418 [QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO_INDEX] = {
1419 .vendor_id = QCA_NL80211_VENDOR_ID,
1420 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO,
1421 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001422#ifdef WLAN_UMAC_CONVERGENCE
1423 COMMON_VENDOR_EVENTS
1424#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001425};
1426
1427/**
1428 * __is_driver_dfs_capable() - get driver DFS capability
1429 * @wiphy: pointer to wireless wiphy structure.
1430 * @wdev: pointer to wireless_dev structure.
1431 * @data: Pointer to the data to be passed via vendor interface
1432 * @data_len:Length of the data to be passed
1433 *
1434 * This function is called by userspace to indicate whether or not
1435 * the driver supports DFS offload.
1436 *
1437 * Return: 0 on success, negative errno on failure
1438 */
1439static int __is_driver_dfs_capable(struct wiphy *wiphy,
1440 struct wireless_dev *wdev,
1441 const void *data,
1442 int data_len)
1443{
1444 u32 dfs_capability = 0;
1445 struct sk_buff *temp_skbuff;
1446 int ret_val;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07001447 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001448
Dustin Brownfdf17c12018-03-14 12:55:34 -07001449 hdd_enter_dev(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001450
1451 ret_val = wlan_hdd_validate_context(hdd_ctx);
1452 if (ret_val)
1453 return ret_val;
1454
Anurag Chouhan6d760662016-02-20 16:05:43 +05301455 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001456 hdd_err("Command not allowed in FTM mode");
1457 return -EPERM;
1458 }
1459
Peng Xu8e8b0392018-04-30 11:32:34 -07001460#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) || \
1461 defined(CFG80211_DFS_OFFLOAD_BACKPORT)
1462 dfs_capability =
1463 wiphy_ext_feature_isset(wiphy,
1464 NL80211_EXT_FEATURE_DFS_OFFLOAD);
1465#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001466 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Peng Xu8e8b0392018-04-30 11:32:34 -07001467#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001468
1469 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1470 NLMSG_HDRLEN);
1471
1472 if (temp_skbuff != NULL) {
1473 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1474 dfs_capability);
1475 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001476 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001477 kfree_skb(temp_skbuff);
1478
1479 return ret_val;
1480 }
1481
1482 return cfg80211_vendor_cmd_reply(temp_skbuff);
1483 }
1484
Jeff Johnson020db452016-06-29 14:37:26 -07001485 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001486 return -ENOMEM;
1487}
1488
1489/**
1490 * is_driver_dfs_capable() - get driver DFS capability
1491 * @wiphy: pointer to wireless wiphy structure.
1492 * @wdev: pointer to wireless_dev structure.
1493 * @data: Pointer to the data to be passed via vendor interface
1494 * @data_len:Length of the data to be passed
1495 *
1496 * This function is called by userspace to indicate whether or not
1497 * the driver supports DFS offload. This is an SSR-protected
1498 * wrapper function.
1499 *
1500 * Return: 0 on success, negative errno on failure
1501 */
1502static int is_driver_dfs_capable(struct wiphy *wiphy,
1503 struct wireless_dev *wdev,
1504 const void *data,
1505 int data_len)
1506{
1507 int ret;
1508
1509 cds_ssr_protect(__func__);
1510 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1511 cds_ssr_unprotect(__func__);
1512
1513 return ret;
1514}
1515
1516/**
1517 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1518 *
1519 * @adapter: SAP adapter pointer
1520 *
1521 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1522 * radio. So in case of DFS MCC scenario override current SAP given config
1523 * to follow concurrent SAP DFS config
1524 *
1525 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1526 */
Jeff Johnsone5006672017-08-29 14:39:02 -07001527int wlan_hdd_sap_cfg_dfs_override(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001528{
Jeff Johnsone5006672017-08-29 14:39:02 -07001529 struct hdd_adapter *con_sap_adapter;
Jeff Johnsone4c11db2018-05-05 23:22:32 -07001530 tsap_config_t *sap_config, *con_sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001531 int con_ch;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07001532 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001533
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001534 if (!hdd_ctx) {
1535 hdd_err("hdd context is NULL");
1536 return 0;
1537 }
1538
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001539 /*
1540 * Check if AP+AP case, once primary AP chooses a DFS
1541 * channel secondary AP should always follow primary APs channel
1542 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001543 if (!policy_mgr_concurrent_beaconing_sessions_running(
1544 hdd_ctx->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001545 return 0;
1546
1547 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1548 if (!con_sap_adapter)
1549 return 0;
1550
Jeff Johnsonb9424862017-10-30 08:49:35 -07001551 sap_config = &adapter->session.ap.sap_config;
1552 con_sap_config = &con_sap_adapter->session.ap.sap_config;
1553 con_ch = con_sap_adapter->session.ap.operating_channel;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001554
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001555 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, con_ch))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001556 return 0;
1557
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001558 hdd_debug("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001559 sap_config->channel, con_ch);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001560 hdd_debug("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001561 sap_config->channel = con_ch;
1562
1563 if (con_sap_config->acs_cfg.acs_mode == true) {
1564 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1565 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001566 hdd_err("Primary AP channel config error");
1567 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001568 con_ch, con_sap_config->acs_cfg.pri_ch,
1569 con_sap_config->acs_cfg.ht_sec_ch);
1570 return -EINVAL;
1571 }
1572 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1573 * MCC restriction. So free ch list allocated in do_acs
1574 * func for Sec AP and realloc for Pri AP ch list size
1575 */
1576 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301577 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001578
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301579 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001580 &con_sap_config->acs_cfg,
1581 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301582 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001583 sizeof(uint8_t) *
1584 con_sap_config->acs_cfg.ch_list_count);
1585 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001586 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001587 return -ENOMEM;
1588 }
1589
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301590 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001591 con_sap_config->acs_cfg.ch_list,
1592 con_sap_config->acs_cfg.ch_list_count);
1593
1594 } else {
1595 sap_config->acs_cfg.pri_ch = con_ch;
1596 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1597 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1598 }
1599
1600 return con_ch;
1601}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001602
1603/**
wadesong1795e142018-01-05 11:13:07 +08001604 * wlan_hdd_set_acs_ch_range : Populate ACS hw mode and channel range values
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001605 * @sap_cfg: pointer to SAP config struct
wadesong1795e142018-01-05 11:13:07 +08001606 * @hw_mode: hw mode retrieved from vendor command buffer
1607 * @ht_enabled: whether HT phy mode is enabled
1608 * @vht_enabled: whether VHT phy mode is enabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001609 *
wadesong1795e142018-01-05 11:13:07 +08001610 * This function populates the ACS hw mode based on the configuration retrieved
1611 * from the vendor command buffer; and sets ACS start and end channel for the
1612 * given band.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001613 *
wadesong1795e142018-01-05 11:13:07 +08001614 * Return: 0 if success; -EINVAL if ACS channel list is NULL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001615 */
wadesong1795e142018-01-05 11:13:07 +08001616static int wlan_hdd_set_acs_ch_range(
Jeff Johnsone4c11db2018-05-05 23:22:32 -07001617 tsap_config_t *sap_cfg, enum qca_wlan_vendor_acs_hw_mode hw_mode,
wadesong1795e142018-01-05 11:13:07 +08001618 bool ht_enabled, bool vht_enabled)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001619{
1620 int i;
Srinivas Girigowda576b2352017-08-25 14:44:26 -07001621
wadesong1795e142018-01-05 11:13:07 +08001622 if (hw_mode == QCA_ACS_MODE_IEEE80211B) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001623 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001624 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1625 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_14);
wadesong1795e142018-01-05 11:13:07 +08001626 } else if (hw_mode == QCA_ACS_MODE_IEEE80211G) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001627 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001628 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1629 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_13);
wadesong1795e142018-01-05 11:13:07 +08001630 } else if (hw_mode == QCA_ACS_MODE_IEEE80211A) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001631 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001632 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_36);
1633 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
wadesong1795e142018-01-05 11:13:07 +08001634 } else if (hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001635 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001636 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1637 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001638 }
1639
1640 if (ht_enabled)
1641 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1642
1643 if (vht_enabled)
1644 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1645
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001646 /* Parse ACS Chan list from hostapd */
1647 if (!sap_cfg->acs_cfg.ch_list)
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05301648 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001649
1650 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1651 sap_cfg->acs_cfg.end_ch =
1652 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1653 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301654 /* avoid channel as start channel */
1655 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1656 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001657 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1658 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1659 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1660 }
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05301661
1662 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001663}
1664
1665
1666static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1667
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301668
Jeff Johnsone4c11db2018-05-05 23:22:32 -07001669static void hdd_update_acs_channel_list(tsap_config_t *sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001670 enum band_info band)
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301671{
1672 int i, temp_count = 0;
1673 int acs_list_count = sap_config->acs_cfg.ch_list_count;
1674
1675 for (i = 0; i < acs_list_count; i++) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001676 if (BAND_2G == band) {
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301677 if (WLAN_REG_IS_24GHZ_CH(
1678 sap_config->acs_cfg.ch_list[i])) {
1679 sap_config->acs_cfg.ch_list[temp_count] =
1680 sap_config->acs_cfg.ch_list[i];
1681 temp_count++;
1682 }
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001683 } else if (BAND_5G == band) {
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301684 if (WLAN_REG_IS_5GHZ_CH(
1685 sap_config->acs_cfg.ch_list[i])) {
1686 sap_config->acs_cfg.ch_list[temp_count] =
1687 sap_config->acs_cfg.ch_list[i];
1688 temp_count++;
1689 }
1690 }
1691 }
1692 sap_config->acs_cfg.ch_list_count = temp_count;
1693}
1694
1695
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001696/**
1697 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1698 * @adapter: pointer to SAP adapter struct
1699 *
1700 * This function starts the ACS procedure if there are no
1701 * constraints like MBSSID DFS restrictions.
1702 *
1703 * Return: Status of ACS Start procedure
1704 */
Jeff Johnsone5006672017-08-29 14:39:02 -07001705int wlan_hdd_cfg80211_start_acs(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001706{
1707
Kiran Kumar Lokere85cb36b2017-09-14 15:19:14 -07001708 struct hdd_context *hdd_ctx;
Jeff Johnsone4c11db2018-05-05 23:22:32 -07001709 tsap_config_t *sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001710 tpWLAN_SAPEventCB acs_event_callback;
1711 int status;
1712
Kiran Kumar Lokere85cb36b2017-09-14 15:19:14 -07001713 if (!adapter) {
Jeff Johnsondd2f1fc2018-05-06 11:22:52 -07001714 hdd_err("adapter is NULL");
Kiran Kumar Lokere85cb36b2017-09-14 15:19:14 -07001715 return -EINVAL;
1716 }
1717 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb9424862017-10-30 08:49:35 -07001718 sap_config = &adapter->session.ap.sap_config;
Agrawal Ashish65634612016-08-18 13:24:32 +05301719 if (hdd_ctx->acs_policy.acs_channel)
1720 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1721 else
1722 sap_config->channel = AUTO_CHANNEL_SELECT;
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301723 /*
1724 * No DFS SCC is allowed in Auto use case. Hence not
1725 * calling DFS override
1726 */
1727 if (QDF_MCC_TO_SCC_SWITCH_FORCE_PREFERRED_WITHOUT_DISCONNECTION !=
1728 hdd_ctx->config->WlanMccToSccSwitchMode) {
1729 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1730 if (status < 0)
1731 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001732
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301733 if (status > 0) {
1734 /*notify hostapd about channel override */
1735 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1736 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1737 return 0;
1738 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001739 }
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301740 /* When first 2 connections are on the same frequency band,
1741 * then PCL would include only channels from the other
1742 * frequency band on which no connections are active
1743 */
1744 if ((policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) == 2) &&
1745 (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY)) {
1746 struct policy_mgr_conc_connection_info *conc_connection_info;
1747 uint32_t i;
Jeff Johnson68755312017-02-10 11:46:55 -08001748
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301749 conc_connection_info = policy_mgr_get_conn_info(&i);
1750 if (conc_connection_info[0].mac ==
1751 conc_connection_info[1].mac) {
1752 if (WLAN_REG_IS_5GHZ_CH(sap_config->acs_cfg.
1753 pcl_channels[0])) {
1754 sap_config->acs_cfg.band =
1755 QCA_ACS_MODE_IEEE80211A;
1756 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001757 BAND_5G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301758 } else {
1759 sap_config->acs_cfg.band =
1760 QCA_ACS_MODE_IEEE80211G;
1761 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001762 BAND_2G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301763 }
1764 }
1765 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001766 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1767 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001768 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001769 return -EINVAL;
1770 }
1771
1772 acs_event_callback = hdd_hostapd_sap_event_cb;
1773
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301774 qdf_mem_copy(sap_config->self_macaddr.bytes,
Jeff Johnson1e851a12017-10-28 14:36:12 -07001775 adapter->mac_addr.bytes, sizeof(struct qdf_mac_addr));
Dustin Brown5e89ef82018-03-14 11:50:23 -07001776 hdd_info("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001777 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001778 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001779 acs_event_callback, sap_config, adapter->dev);
1780
1781
1782 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001783 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001784 return -EINVAL;
1785 }
bings394afdd2017-01-09 11:22:38 +08001786 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1787 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001788 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1789
1790 return 0;
1791}
1792
1793/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301794 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1795 * @hdd_ctx: hdd context
1796 * @acs_chan_params: external acs channel params
1797 * @sap_config: SAP config
1798 *
1799 * This API provides unsorted pcl list.
1800 * this list is a subset of the valid channel list given by hostapd.
1801 * if channel is not present in pcl, weightage will be given as zero
1802 *
1803 * Return: Zero on success, non-zero on failure
1804 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07001805static void hdd_update_vendor_pcl_list(struct hdd_context *hdd_ctx,
Kapil Gupta8878ad92017-02-13 11:56:04 +05301806 struct hdd_vendor_acs_chan_params *acs_chan_params,
Jeff Johnsone4c11db2018-05-05 23:22:32 -07001807 tsap_config_t *sap_config)
Kapil Gupta8878ad92017-02-13 11:56:04 +05301808{
1809 int i, j;
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301810 /*
1811 * PCL shall contain only the preferred channels from the
1812 * application. If those channels are not present in the
1813 * driver PCL, then set the weight to zero
1814 */
1815 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1816 acs_chan_params->vendor_pcl_list[i] =
1817 sap_config->acs_cfg.ch_list[i];
1818 acs_chan_params->vendor_weight_list[i] = 0;
1819 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1820 if (sap_config->acs_cfg.ch_list[i] ==
1821 sap_config->acs_cfg.pcl_channels[j]) {
1822 acs_chan_params->vendor_weight_list[i] =
1823 sap_config->
1824 acs_cfg.pcl_channels_weight_list[j];
1825 break;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301826 }
1827 }
1828 }
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301829 acs_chan_params->pcl_count = sap_config->acs_cfg.ch_list_count;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301830}
1831
1832/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301833 * hdd_update_reg_chan_info : This API contructs channel info
1834 * for all the given channel
1835 * @adapter: pointer to SAP adapter struct
1836 * @channel_count: channel count
1837 * @channel_list: channel list
1838 *
1839 * Return: Status of of channel information updation
1840 */
Jeff Johnsone5006672017-08-29 14:39:02 -07001841static int hdd_update_reg_chan_info(struct hdd_adapter *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301842 uint32_t channel_count,
1843 uint8_t *channel_list)
1844{
1845 int i;
1846 struct hdd_channel_info *icv;
Amar Singhal5cccafe2017-02-15 12:42:58 -08001847 struct ch_params ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301848 uint8_t bw_offset = 0, chan = 0;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07001849 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsone4c11db2018-05-05 23:22:32 -07001850 tsap_config_t *sap_config = &adapter->session.ap.sap_config;
Kapil Gupta086c6202016-12-11 18:17:06 +05301851
1852 /* memory allocation */
1853 sap_config->channel_info = qdf_mem_malloc(
1854 sizeof(struct hdd_channel_info) *
1855 channel_count);
1856 if (!sap_config->channel_info) {
1857 hdd_err("memory allocation failed");
1858 return -ENOMEM;
1859
1860 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301861 sap_config->channel_info_count = channel_count;
Kapil Gupta086c6202016-12-11 18:17:06 +05301862 for (i = 0; i < channel_count; i++) {
1863 icv = &sap_config->channel_info[i];
1864 chan = channel_list[i];
1865
1866 if (chan == 0)
1867 continue;
1868
1869 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1870 bw_offset = 1 << BW_40_OFFSET_BIT;
1871 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1872 bw_offset = 1 << BW_20_OFFSET_BIT;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001873 icv->freq = wlan_reg_get_channel_freq(hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301874 icv->ieee_chan_number = chan;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001875 icv->max_reg_power = wlan_reg_get_channel_reg_power(
1876 hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301877
1878 /* filling demo values */
1879 icv->max_radio_power = HDD_MAX_TX_POWER;
1880 icv->min_radio_power = HDD_MIN_TX_POWER;
1881 /* not supported in current driver */
1882 icv->max_antenna_gain = 0;
1883
1884 icv->reg_class_id = wlan_hdd_find_opclass(
1885 WLAN_HDD_GET_HAL_CTX(adapter),
1886 chan, bw_offset);
1887
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001888 if (WLAN_REG_IS_5GHZ_CH(chan)) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301889 ch_params.ch_width = sap_config->acs_cfg.ch_width;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001890 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan,
1891 0, &ch_params);
Kapil Gupta086c6202016-12-11 18:17:06 +05301892 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1893 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1894 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001895
Kapil Gupta086c6202016-12-11 18:17:06 +05301896 icv->flags = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001897 icv->flags = cds_get_vendor_reg_flags(hdd_ctx->hdd_pdev, chan,
Kapil Gupta086c6202016-12-11 18:17:06 +05301898 sap_config->acs_cfg.ch_width,
1899 sap_config->acs_cfg.is_ht_enabled,
1900 sap_config->acs_cfg.is_vht_enabled,
1901 hdd_ctx->config->enable_sub_20_channel_width);
Kapil Guptac1224bf2017-06-22 21:22:40 +05301902 if (icv->flags & IEEE80211_CHAN_PASSIVE)
1903 icv->flagext |= IEEE80211_CHAN_DFS;
Kapil Gupta086c6202016-12-11 18:17:06 +05301904
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +05301905 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 +05301906 icv->freq, icv->flags,
1907 icv->flagext, icv->ieee_chan_number,
1908 icv->max_reg_power, icv->max_radio_power,
1909 icv->min_radio_power, icv->reg_class_id,
1910 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1911 icv->vht_center_freq_seg1);
1912 }
1913 return 0;
1914}
1915
1916/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1917#define CHAN_INFO_ATTR_FLAGS \
1918 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1919#define CHAN_INFO_ATTR_FLAG_EXT \
1920 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1921#define CHAN_INFO_ATTR_FREQ \
1922 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1923#define CHAN_INFO_ATTR_MAX_REG_POWER \
1924 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1925#define CHAN_INFO_ATTR_MAX_POWER \
1926 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1927#define CHAN_INFO_ATTR_MIN_POWER \
1928 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1929#define CHAN_INFO_ATTR_REG_CLASS_ID \
1930 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1931#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1932 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1933#define CHAN_INFO_ATTR_VHT_SEG_0 \
1934 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1935#define CHAN_INFO_ATTR_VHT_SEG_1 \
1936 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1937
1938/**
1939 * hdd_cfg80211_update_channel_info() - add channel info attributes
1940 * @skb: pointer to sk buff
1941 * @hdd_ctx: pointer to hdd station context
1942 * @idx: attribute index
1943 *
1944 * Return: Success(0) or reason code for failure
1945 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301946static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301947hdd_cfg80211_update_channel_info(struct sk_buff *skb,
Jeff Johnsone4c11db2018-05-05 23:22:32 -07001948 tsap_config_t *sap_config, int idx)
Kapil Gupta086c6202016-12-11 18:17:06 +05301949{
1950 struct nlattr *nla_attr, *channel;
1951 struct hdd_channel_info *icv;
1952 int i;
1953
1954 nla_attr = nla_nest_start(skb, idx);
1955 if (!nla_attr)
1956 goto fail;
1957
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301958 for (i = 0; i < sap_config->channel_info_count; i++) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301959 channel = nla_nest_start(skb, i);
1960 if (!channel)
1961 goto fail;
1962
1963 icv = &sap_config->channel_info[i];
1964 if (!icv) {
1965 hdd_err("channel info not found");
1966 goto fail;
1967 }
1968 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1969 icv->freq) ||
1970 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1971 icv->flags) ||
Kapil Gupta63e75282017-05-18 20:55:10 +05301972 nla_put_u32(skb, CHAN_INFO_ATTR_FLAG_EXT,
Kapil Gupta086c6202016-12-11 18:17:06 +05301973 icv->flagext) ||
1974 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1975 icv->max_reg_power) ||
1976 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1977 icv->max_radio_power) ||
1978 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1979 icv->min_radio_power) ||
1980 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1981 icv->reg_class_id) ||
1982 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1983 icv->max_antenna_gain) ||
1984 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1985 icv->vht_center_freq_seg0) ||
1986 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1987 icv->vht_center_freq_seg1)) {
1988 hdd_err("put fail");
1989 goto fail;
1990 }
1991 nla_nest_end(skb, channel);
1992 }
1993 nla_nest_end(skb, nla_attr);
1994 return 0;
1995fail:
1996 hdd_err("nl channel update failed");
1997 return -EINVAL;
1998}
1999#undef CHAN_INFO_ATTR_FLAGS
2000#undef CHAN_INFO_ATTR_FLAG_EXT
2001#undef CHAN_INFO_ATTR_FREQ
2002#undef CHAN_INFO_ATTR_MAX_REG_POWER
2003#undef CHAN_INFO_ATTR_MAX_POWER
2004#undef CHAN_INFO_ATTR_MIN_POWER
2005#undef CHAN_INFO_ATTR_REG_CLASS_ID
2006#undef CHAN_INFO_ATTR_ANTENNA_GAIN
2007#undef CHAN_INFO_ATTR_VHT_SEG_0
2008#undef CHAN_INFO_ATTR_VHT_SEG_1
2009
2010/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05302011 * hdd_cfg80211_update_pcl() - add pcl info attributes
2012 * @skb: pointer to sk buff
2013 * @hdd_ctx: pointer to hdd station context
2014 * @idx: attribute index
2015 * @vendor_pcl_list: PCL list
2016 * @vendor_weight_list: PCL weights
2017 *
2018 * Return: Success(0) or reason code for failure
2019 */
2020static int32_t
2021hdd_cfg80211_update_pcl(struct sk_buff *skb,
2022 uint8_t ch_list_count, int idx,
2023 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
2024{
2025 struct nlattr *nla_attr, *channel;
2026 int i;
2027
2028 nla_attr = nla_nest_start(skb, idx);
2029
2030 if (!nla_attr)
2031 goto fail;
2032
2033 for (i = 0; i < ch_list_count; i++) {
2034 channel = nla_nest_start(skb, i);
2035 if (!channel)
2036 goto fail;
Kapil Gupta63e75282017-05-18 20:55:10 +05302037 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CHANNEL,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302038 vendor_pcl_list[i]) ||
Kapil Gupta63e75282017-05-18 20:55:10 +05302039 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302040 vendor_weight_list[i])) {
2041 hdd_err("put fail");
2042 goto fail;
2043 }
2044 nla_nest_end(skb, channel);
2045 }
2046 nla_nest_end(skb, nla_attr);
2047
2048 return 0;
2049fail:
2050 hdd_err("updating pcl list failed");
2051 return -EINVAL;
2052}
2053
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002054static void hdd_get_scan_band(struct hdd_context *hdd_ctx,
Jeff Johnsone4c11db2018-05-05 23:22:32 -07002055 tsap_config_t *sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002056 enum band_info *band)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302057{
2058 /* Get scan band */
Kapil Guptac1224bf2017-06-22 21:22:40 +05302059 if ((sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211B) ||
2060 (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211G)) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002061 *band = BAND_2G;
Kapil Guptac1224bf2017-06-22 21:22:40 +05302062 } else if (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211A) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002063 *band = BAND_5G;
Kapil Guptac1224bf2017-06-22 21:22:40 +05302064 } else if (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002065 *band = BAND_ALL;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302066 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302067}
2068
Kapil Gupta63e75282017-05-18 20:55:10 +05302069
2070/**
2071 * hdd_get_freq_list: API to get Frequency list based on channel list
2072 * @channel_list: channel list
2073 * @freq_list: frequency list
2074 * @channel_count: channel count
2075 *
2076 * Return: None
2077 */
2078static void hdd_get_freq_list(uint8_t *channel_list, uint32_t *freq_list,
2079 uint32_t channel_count)
2080{
2081 int count;
2082
2083 for (count = 0; count < channel_count ; count++)
2084 freq_list[count] = cds_chan_to_freq(channel_list[count]);
2085}
2086
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302087int hdd_cfg80211_update_acs_config(struct hdd_adapter *adapter,
2088 uint8_t reason)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302089{
2090 struct sk_buff *skb;
Jeff Johnsone4c11db2018-05-05 23:22:32 -07002091 tsap_config_t *sap_config;
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302092 uint32_t channel_count = 0, status = -EINVAL;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302093 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
Kapil Gupta63e75282017-05-18 20:55:10 +05302094 uint32_t freq_list[QDF_MAX_NUM_CHAN] = {0};
Kapil Gupta8878ad92017-02-13 11:56:04 +05302095 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
2096 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
2097 struct hdd_vendor_acs_chan_params acs_chan_params;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002098 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002099 enum band_info band = BAND_2G;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302100 eCsrPhyMode phy_mode;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302101 enum qca_wlan_vendor_attr_external_acs_policy acs_policy;
2102 uint32_t i;
2103
Kapil Gupta8878ad92017-02-13 11:56:04 +05302104
2105 if (!hdd_ctx) {
2106 hdd_err("HDD context is NULL");
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302107 return -EINVAL;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302108 }
2109
Dustin Brown491d54b2018-03-14 12:39:11 -07002110 hdd_enter();
Jeff Johnsonb9424862017-10-30 08:49:35 -07002111 sap_config = &adapter->session.ap.sap_config;
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302112 /* When first 2 connections are on the same frequency band,
2113 * then PCL would include only channels from the other
2114 * frequency band on which no connections are active
2115 */
2116 if ((policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) == 2) &&
2117 (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY)) {
2118 struct policy_mgr_conc_connection_info *conc_connection_info;
2119
2120 conc_connection_info = policy_mgr_get_conn_info(&i);
2121 if (conc_connection_info[0].mac ==
2122 conc_connection_info[1].mac) {
2123
2124 if (WLAN_REG_IS_5GHZ_CH(sap_config->acs_cfg.
2125 pcl_channels[0])) {
2126 sap_config->acs_cfg.band =
2127 QCA_ACS_MODE_IEEE80211A;
2128 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002129 BAND_5G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302130 } else {
2131 sap_config->acs_cfg.band =
2132 QCA_ACS_MODE_IEEE80211G;
2133 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002134 BAND_2G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302135 }
2136 }
2137 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302138
Jeff Johnsonb9424862017-10-30 08:49:35 -07002139 hdd_get_scan_band(hdd_ctx, &adapter->session.ap.sap_config, &band);
Nachiket Kukade3208c162017-08-29 17:40:59 +05302140
2141 if (sap_config->acs_cfg.ch_list) {
2142 /* Copy INI or hostapd provided ACS channel range*/
2143 qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
2144 sap_config->acs_cfg.ch_list_count);
2145 channel_count = sap_config->acs_cfg.ch_list_count;
2146 } else {
2147 /* No channel list provided, copy all valid channels */
2148 wlan_hdd_sap_get_valid_channellist(adapter,
2149 &channel_count,
2150 channel_list,
2151 band);
2152 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302153
2154 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
Kapil Gupta63e75282017-05-18 20:55:10 +05302155 hdd_get_freq_list(channel_list, freq_list, channel_count);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302156 /* Get phymode */
Jeff Johnsonb9424862017-10-30 08:49:35 -07002157 phy_mode = adapter->session.ap.sap_config.acs_cfg.hw_mode;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302158
2159 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
2160 &(adapter->wdev),
2161 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
2162 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
2163 GFP_KERNEL);
2164
2165 if (!skb) {
2166 hdd_err("cfg80211_vendor_event_alloc failed");
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302167 return -ENOMEM;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302168 }
2169 /*
2170 * Application expects pcl to be a subset of channel list
2171 * Remove all channels which are not in channel list from pcl
2172 * and add weight as zero
2173 */
2174 acs_chan_params.channel_count = channel_count;
2175 acs_chan_params.channel_list = channel_list;
2176 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
2177 acs_chan_params.vendor_weight_list = vendor_weight_list;
2178
2179 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
2180 sap_config);
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302181
2182 if (acs_chan_params.channel_count) {
2183 hdd_debug("ACS channel list: len: %d",
2184 acs_chan_params.channel_count);
2185 for (i = 0; i < acs_chan_params.channel_count; i++)
2186 hdd_debug("%d ", acs_chan_params.channel_list[i]);
2187 }
2188
2189 if (acs_chan_params.pcl_count) {
2190 hdd_debug("ACS PCL list: len: %d",
2191 acs_chan_params.pcl_count);
2192 for (i = 0; i < acs_chan_params.pcl_count; i++)
2193 hdd_debug("channel:%d, weight:%d ",
2194 acs_chan_params.
2195 vendor_pcl_list[i],
2196 acs_chan_params.
2197 vendor_weight_list[i]);
2198 }
2199
2200 if (HDD_EXTERNAL_ACS_PCL_MANDATORY ==
2201 hdd_ctx->config->external_acs_policy) {
2202 acs_policy =
2203 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY;
2204 } else {
2205 acs_policy =
2206 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED;
2207 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302208 /* Update values in NL buffer */
2209 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
2210 reason) ||
Kapil Gupta63e75282017-05-18 20:55:10 +05302211 nla_put_flag(skb,
2212 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED) ||
2213 nla_put_flag(skb,
2214 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT)
2215 ||
Kapil Gupta8878ad92017-02-13 11:56:04 +05302216 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
2217 sap_config->acs_cfg.ch_width) ||
Kapil Gupta8878ad92017-02-13 11:56:04 +05302218 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
2219 band) ||
2220 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
2221 phy_mode) ||
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +05302222 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST,
Kapil Gupta63e75282017-05-18 20:55:10 +05302223 channel_count * sizeof(uint32_t), freq_list)) {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302224 hdd_err("nla put fail");
2225 goto fail;
2226 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302227 status =
2228 hdd_cfg80211_update_pcl(skb,
2229 acs_chan_params.
2230 pcl_count,
2231 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
2232 vendor_pcl_list,
2233 vendor_weight_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302234
2235 if (status != 0)
2236 goto fail;
2237
2238 status = hdd_cfg80211_update_channel_info(skb, sap_config,
2239 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
2240
Kapil Gupta63e75282017-05-18 20:55:10 +05302241 qdf_mem_free(sap_config->channel_info);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302242 if (status != 0)
2243 goto fail;
2244
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302245 status = nla_put_u32(skb,
2246 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY,
2247 acs_policy);
2248
2249 if (status != 0)
2250 goto fail;
2251
Kapil Gupta8878ad92017-02-13 11:56:04 +05302252 cfg80211_vendor_event(skb, GFP_KERNEL);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302253 return 0;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302254fail:
2255 if (skb)
2256 kfree_skb(skb);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302257 return status;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302258}
2259
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302260/**
2261 * hdd_create_acs_timer(): Initialize vendor ACS timer
2262 * @adapter: pointer to SAP adapter struct
2263 *
2264 * This function initializes the vendor ACS timer.
2265 *
2266 * Return: Status of create vendor ACS timer
2267 */
Jeff Johnsone5006672017-08-29 14:39:02 -07002268static int hdd_create_acs_timer(struct hdd_adapter *adapter)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302269{
2270 struct hdd_external_acs_timer_context *timer_context;
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302271 QDF_STATUS status;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302272
Jeff Johnsonb9424862017-10-30 08:49:35 -07002273 if (adapter->session.ap.vendor_acs_timer_initialized)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302274 return 0;
2275
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302276 hdd_debug("Starting vendor app based ACS");
Kapil Gupta8878ad92017-02-13 11:56:04 +05302277 timer_context = qdf_mem_malloc(sizeof(*timer_context));
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302278 if (!timer_context) {
2279 hdd_err("Could not allocate for timer_context");
2280 return -ENOMEM;
2281 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302282 timer_context->adapter = adapter;
2283
2284 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
Jeff Johnsonb9424862017-10-30 08:49:35 -07002285 status = qdf_mc_timer_init(&adapter->session.ap.vendor_acs_timer,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302286 QDF_TIMER_TYPE_SW,
2287 hdd_acs_response_timeout_handler, timer_context);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302288 if (status != QDF_STATUS_SUCCESS) {
2289 hdd_err("Failed to initialize acs response timeout timer");
2290 return -EFAULT;
2291 }
Jeff Johnsonb9424862017-10-30 08:49:35 -07002292 adapter->session.ap.vendor_acs_timer_initialized = true;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302293 return 0;
2294}
2295
Ashish Kumar Dhanotiyacc770eb2017-06-08 19:31:15 +05302296static const struct nla_policy
2297wlan_hdd_cfg80211_do_acs_policy[QCA_WLAN_VENDOR_ATTR_ACS_MAX+1] = {
2298 [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
2299 [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
2300 [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
2301 [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
2302 [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
2303 [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_UNSPEC },
2304 [QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST] = { .type = NLA_UNSPEC },
2305};
2306
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302307int hdd_start_vendor_acs(struct hdd_adapter *adapter)
2308{
2309 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2310 int status;
2311
2312 status = hdd_create_acs_timer(adapter);
2313 if (status != 0) {
2314 hdd_err("failed to create acs timer");
2315 return status;
2316 }
2317 status = hdd_update_acs_timer_reason(adapter,
2318 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2319 if (status != 0) {
2320 hdd_err("failed to update acs timer reason");
2321 return status;
2322 }
2323
2324 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2325 status = qdf_status_to_os_return(wlan_sap_set_vendor_acs(
2326 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2327 true));
2328 else
2329 status = qdf_status_to_os_return(wlan_sap_set_vendor_acs(
2330 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2331 false));
2332
2333 return status;
2334}
2335
Kapil Gupta8878ad92017-02-13 11:56:04 +05302336/**
Ashish Kumar Dhanotiyacc770eb2017-06-08 19:31:15 +05302337 * __wlan_hdd_cfg80211_do_acs(): CFG80211 handler function for DO_ACS Vendor CMD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002338 * @wiphy: Linux wiphy struct pointer
2339 * @wdev: Linux wireless device struct pointer
2340 * @data: ACS information from hostapd
2341 * @data_len: ACS information length
2342 *
2343 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2344 * and starts ACS procedure.
2345 *
2346 * Return: ACS procedure start status
2347 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002348static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2349 struct wireless_dev *wdev,
2350 const void *data, int data_len)
2351{
2352 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07002353 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002354 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnsone4c11db2018-05-05 23:22:32 -07002355 tsap_config_t *sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002356 struct sk_buff *temp_skbuff;
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302357 int ret, i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002358 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
2359 bool ht_enabled, ht40_enabled, vht_enabled;
wadesong1795e142018-01-05 11:13:07 +08002360 uint8_t ch_width;
2361 enum qca_wlan_vendor_acs_hw_mode hw_mode;
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05302362 QDF_STATUS qdf_status;
Himanshu Agarwal33163982018-05-17 18:11:10 +05302363 uint8_t conc_channel;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002364
2365 /* ***Note*** Donot set SME config related to ACS operation here because
2366 * ACS operation is not synchronouse and ACS for Second AP may come when
2367 * ACS operation for first AP is going on. So only do_acs is split to
Jeff Johnsonfa7d9602018-05-06 11:25:31 -07002368 * separate start_acs routine. Also SME-PMAC struct that is used to
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002369 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
2370 * config shall be set only from start_acs.
2371 */
2372
Dustin Brownfdf17c12018-03-14 12:55:34 -07002373 hdd_enter_dev(ndev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08002374
Anurag Chouhan6d760662016-02-20 16:05:43 +05302375 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002376 hdd_err("Command not allowed in FTM mode");
2377 return -EPERM;
2378 }
2379
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302380 ret = wlan_hdd_validate_context(hdd_ctx);
2381 if (ret)
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302382 return ret;
2383
Hanumanth Reddy Pothula89b0dce2018-05-18 12:49:43 +05302384 if (!((adapter->device_mode == QDF_SAP_MODE) ||
2385 (adapter->device_mode == QDF_P2P_GO_MODE))) {
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302386 hdd_err("Invalid device mode %d", adapter->device_mode);
2387 return -EINVAL;
2388 }
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302389
Naveen Rawat64e477e2016-05-20 10:34:56 -07002390 if (cds_is_sub_20_mhz_enabled()) {
2391 hdd_err("ACS not supported in sub 20 MHz ch wd.");
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302392 return -EINVAL;
Naveen Rawat64e477e2016-05-20 10:34:56 -07002393 }
2394
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302395 if (qdf_atomic_read(&adapter->session.ap.acs_in_progress) > 0) {
Abhinav Kumar5eda62d2018-02-13 13:00:39 +05302396 hdd_err("ACS rejected as previous req already in progress");
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302397 return -EINVAL;
2398 } else {
2399 qdf_atomic_set(&adapter->session.ap.acs_in_progress, 1);
Abhinav Kumar5eda62d2018-02-13 13:00:39 +05302400 }
2401
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302402 ret = wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data,
Dustin Brown4ea21db2018-01-05 14:13:17 -08002403 data_len,
2404 wlan_hdd_cfg80211_do_acs_policy);
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302405 if (ret) {
Jeff Johnson020db452016-06-29 14:37:26 -07002406 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002407 goto out;
2408 }
2409
2410 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002411 hdd_err("Attr hw_mode failed");
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302412 ret = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002413 goto out;
2414 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302415 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002416
2417 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
2418 ht_enabled =
2419 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
2420 else
2421 ht_enabled = 0;
2422
2423 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
2424 ht40_enabled =
2425 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
2426 else
2427 ht40_enabled = 0;
2428
Kapil Guptac1224bf2017-06-22 21:22:40 +05302429 hdd_debug("ht40_enabled %d", ht40_enabled);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002430 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
2431 vht_enabled =
2432 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
2433 else
2434 vht_enabled = 0;
2435
Bala Venkateshb9cf3362017-11-09 15:48:46 +05302436 if (((adapter->device_mode == QDF_SAP_MODE) &&
2437 (hdd_ctx->config->sap_force_11n_for_11ac)) ||
2438 ((adapter->device_mode == QDF_P2P_GO_MODE) &&
2439 (hdd_ctx->config->go_force_11n_for_11ac))) {
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302440 vht_enabled = 0;
Dustin Brownbacc48f2018-03-14 14:48:44 -07002441 hdd_info("VHT is Disabled in ACS");
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302442 }
2443
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002444 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
2445 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
2446 } else {
2447 if (ht_enabled && ht40_enabled)
2448 ch_width = 40;
2449 else
2450 ch_width = 20;
2451 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302452
Bala Venkateshb9cf3362017-11-09 15:48:46 +05302453 /* this may be possible, when sap_force_11n_for_11ac or
2454 * go_force_11n_for_11ac is set
2455 */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302456 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
2457 if (ht_enabled && ht40_enabled)
2458 ch_width = 40;
2459 else
2460 ch_width = 20;
2461 }
2462
Hanumanth Reddy Pothula560d5712018-03-15 18:11:27 +05302463 sap_config = &adapter->session.ap.sap_config;
2464
2465 /* Check and free if memory is already allocated for acs channel list */
2466 wlan_hdd_undo_acs(adapter);
2467
2468 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
2469
Kapil Guptac1224bf2017-06-22 21:22:40 +05302470 hdd_debug("channel width =%d", ch_width);
Himanshu Agarwal75e74412018-02-01 20:51:47 +05302471 if (ch_width == 160)
2472 sap_config->acs_cfg.ch_width = CH_WIDTH_160MHZ;
2473 else if (ch_width == 80)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002474 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
2475 else if (ch_width == 40)
2476 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
2477 else
2478 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
2479
2480 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
2481 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
2482 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
2483 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
2484 * since it contains the frequency values of the channels in
2485 * the channel list.
2486 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
2487 * is present
2488 */
Himanshu Agarwal1b3be702018-02-20 12:16:57 +05302489
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002490 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
2491 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
Srinivas Girigowda576b2352017-08-25 14:44:26 -07002492
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002493 sap_config->acs_cfg.ch_list_count = nla_len(
2494 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
2495 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302496 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002497 sizeof(uint8_t) *
2498 sap_config->acs_cfg.ch_list_count);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302499 if (!sap_config->acs_cfg.ch_list) {
2500 hdd_err("ACS config alloc fail");
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302501 ret = -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002502 goto out;
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302503 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002504
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302505 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002506 sap_config->acs_cfg.ch_list_count);
2507 }
2508 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
2509 uint32_t *freq =
2510 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
2511 sap_config->acs_cfg.ch_list_count = nla_len(
2512 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
2513 sizeof(uint32_t);
2514 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302515 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002516 sap_config->acs_cfg.ch_list_count);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302517 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07002518 hdd_err("ACS config alloc fail");
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302519 ret = -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002520 goto out;
2521 }
2522
2523 /* convert frequency to channel */
2524 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
2525 sap_config->acs_cfg.ch_list[i] =
2526 ieee80211_frequency_to_channel(freq[i]);
2527 }
2528 }
2529
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302530 if (!sap_config->acs_cfg.ch_list_count) {
Amar Singhal5f783132018-03-29 13:58:50 -07002531 hdd_err("acs config chan count 0");
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302532 ret = -EINVAL;
2533 goto out;
2534 }
2535
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002536 hdd_debug("get pcl for DO_ACS vendor command");
2537
2538 /* consult policy manager to get PCL */
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05302539 qdf_status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc, PM_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05302540 sap_config->acs_cfg.pcl_channels,
2541 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302542 sap_config->acs_cfg.pcl_channels_weight_list,
2543 QDF_MAX_NUM_CHAN);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302544 if (qdf_status != QDF_STATUS_SUCCESS)
Jeff Johnson020db452016-06-29 14:37:26 -07002545 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002546
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302547 if (sap_config->acs_cfg.pcl_ch_count) {
2548 hdd_debug("ACS config PCL: len: %d",
2549 sap_config->acs_cfg.pcl_ch_count);
2550 for (i = 0; i < sap_config->acs_cfg.pcl_ch_count; i++)
2551 hdd_debug("channel:%d, weight:%d ",
2552 sap_config->acs_cfg.
2553 pcl_channels[i],
2554 sap_config->acs_cfg.
2555 pcl_channels_weight_list[i]);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05302556 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302557
Tushnim Bhattacharyya087bff32018-02-21 13:25:15 -08002558 if (hw_mode == QCA_ACS_MODE_IEEE80211ANY)
2559 policy_mgr_trim_acs_channel_list(hdd_ctx->hdd_psoc,
2560 sap_config->acs_cfg.ch_list,
2561 &sap_config->acs_cfg.ch_list_count);
2562
Kapil Guptac1224bf2017-06-22 21:22:40 +05302563 sap_config->acs_cfg.band = hw_mode;
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302564 ret = wlan_hdd_set_acs_ch_range(sap_config, hw_mode,
Himanshu Agarwal8b3d3e92018-02-08 23:03:54 +05302565 ht_enabled, vht_enabled);
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302566 if (ret) {
Himanshu Agarwal8b3d3e92018-02-08 23:03:54 +05302567 hdd_err("set acs channel range failed");
2568 goto out;
2569 }
2570
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05302571 /* ACS override for android */
Himanshu Agarwal4ecf6ca2018-05-09 16:48:56 +05302572 if (ht_enabled &&
Himanshu Agarwal8b3d3e92018-02-08 23:03:54 +05302573 sap_config->acs_cfg.end_ch >= WLAN_REG_CH_NUM(CHAN_ENUM_36) &&
Himanshu Agarwal4ecf6ca2018-05-09 16:48:56 +05302574 ((adapter->device_mode == QDF_SAP_MODE &&
2575 !hdd_ctx->config->sap_force_11n_for_11ac &&
2576 hdd_ctx->config->sap_11ac_override) ||
2577 (adapter->device_mode == QDF_P2P_GO_MODE &&
2578 !hdd_ctx->config->go_force_11n_for_11ac &&
2579 hdd_ctx->config->go_11ac_override))) {
2580 hdd_debug("ACS Config override for 11AC, vhtChannelWidth %d",
2581 hdd_ctx->config->vhtChannelWidth);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002582 vht_enabled = 1;
2583 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2584 sap_config->acs_cfg.ch_width =
2585 hdd_ctx->config->vhtChannelWidth;
Himanshu Agarwal29a9a3e2018-02-21 17:44:37 +05302586 }
2587
2588 /* No VHT80 in 2.4G so perform ACS accordingly */
2589 if (sap_config->acs_cfg.end_ch <= 14 &&
2590 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
2591 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
2592 hdd_debug("resetting to 40Mhz in 2.4Ghz");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002593 }
2594
Kapil Guptac1224bf2017-06-22 21:22:40 +05302595 hdd_debug("ACS Config for %s: HW_MODE: %d ACS_BW: %d HT: %d VHT: %d START_CH: %d END_CH: %d band %d",
2596 adapter->dev->name, sap_config->acs_cfg.hw_mode,
Himanshu Agarwal1ed8bff2018-02-07 12:50:41 +05302597 sap_config->acs_cfg.ch_width, ht_enabled, vht_enabled,
Kapil Guptac1224bf2017-06-22 21:22:40 +05302598 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch,
2599 sap_config->acs_cfg.band);
wadesongcb0ded22018-02-02 17:57:20 +08002600 host_log_acs_req_event(adapter->dev->name,
2601 csr_phy_mode_str(sap_config->acs_cfg.hw_mode),
2602 ch_width, ht_enabled, vht_enabled,
2603 sap_config->acs_cfg.start_ch,
2604 sap_config->acs_cfg.end_ch);
gaoleze5108942017-03-31 16:56:42 +08002605 if (hdd_ctx->config->auto_channel_select_weight)
2606 sap_config->auto_channel_select_weight =
2607 hdd_ctx->config->auto_channel_select_weight;
2608
Kapil Gupta8878ad92017-02-13 11:56:04 +05302609 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2610 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2611
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002612 if (sap_config->acs_cfg.ch_list_count) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002613 hdd_debug("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002614 sap_config->acs_cfg.ch_list_count);
2615 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002616 hdd_debug("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002617 }
Himanshu Agarwal33163982018-05-17 18:11:10 +05302618
2619 conc_channel = policy_mgr_mode_specific_get_channel(hdd_ctx->hdd_psoc,
2620 PM_STA_MODE);
2621 if (hdd_ctx->config->external_acs_policy ==
2622 HDD_EXTERNAL_ACS_PCL_MANDATORY) {
2623 if ((conc_channel >= WLAN_REG_CH_NUM(CHAN_ENUM_36) &&
2624 sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211A) ||
2625 (conc_channel <= WLAN_REG_CH_NUM(CHAN_ENUM_14) &&
2626 (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211B ||
2627 sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211A))) {
2628 sap_config->acs_cfg.pri_ch = conc_channel;
2629 wlan_sap_set_sap_ctx_acs_cfg(
2630 WLAN_HDD_GET_SAP_CTX_PTR(adapter), sap_config);
2631 sap_config_acs_result(hdd_ctx->hHal,
2632 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2633 sap_config->acs_cfg.ht_sec_ch);
2634 sap_config->ch_params.ch_width =
2635 sap_config->acs_cfg.ch_width;
2636 sap_config->ch_params.sec_ch_offset =
2637 sap_config->acs_cfg.ht_sec_ch;
2638 sap_config->ch_params.center_freq_seg0 =
2639 sap_config->acs_cfg.vht_seg0_center_ch;
2640 sap_config->ch_params.center_freq_seg1 =
2641 sap_config->acs_cfg.vht_seg1_center_ch;
2642 /*notify hostapd about channel override */
2643 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
2644 ret = 0;
2645 goto out;
2646 }
2647 }
2648
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002649 sap_config->acs_cfg.acs_mode = true;
2650 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002651 /* ***Note*** Completion variable usage is not allowed
2652 * here since ACS scan operation may take max 2.2 sec
2653 * for 5G band:
2654 * 9 Active channel X 40 ms active scan time +
2655 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002656 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2657 * for this long. So we split up the scanning part.
2658 */
2659 set_bit(ACS_PENDING, &adapter->event_flags);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002660 hdd_debug("ACS Pending for %s", adapter->dev->name);
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302661 ret = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002662 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302663 /* Check if vendor specific acs is enabled */
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302664 if (hdd_ctx->config->vendor_acs_support)
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302665 ret = hdd_start_vendor_acs(adapter);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302666 else
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302667 ret = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002668 }
2669
2670out:
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302671 if (ret == 0) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002672 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2673 NLMSG_HDRLEN);
2674 if (temp_skbuff != NULL)
2675 return cfg80211_vendor_cmd_reply(temp_skbuff);
2676 }
Abhinav Kumarb638b5d2018-03-26 12:25:41 +05302677 qdf_atomic_set(&adapter->session.ap.acs_in_progress, 0);
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002678 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002679 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2680
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302681 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002682}
2683
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002684/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002685 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2686 * @wiphy: Linux wiphy struct pointer
2687 * @wdev: Linux wireless device struct pointer
2688 * @data: ACS information from hostapd
2689 * @data_len: ACS information len
2690 *
2691 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2692 * and starts ACS procedure.
2693 *
2694 * Return: ACS procedure start status
2695 */
2696
2697static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2698 struct wireless_dev *wdev,
2699 const void *data, int data_len)
2700{
2701 int ret;
2702
2703 cds_ssr_protect(__func__);
2704 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2705 cds_ssr_unprotect(__func__);
2706
2707 return ret;
2708}
2709
2710/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002711 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2712 * @adapter: Pointer to adapter struct
2713 *
2714 * This function handle cleanup of what was done in DO_ACS, including free
2715 * memory.
2716 *
2717 * Return: void
2718 */
2719
Jeff Johnsone5006672017-08-29 14:39:02 -07002720void wlan_hdd_undo_acs(struct hdd_adapter *adapter)
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002721{
2722 if (adapter == NULL)
2723 return;
Jeff Johnsonb9424862017-10-30 08:49:35 -07002724 if (adapter->session.ap.sap_config.acs_cfg.ch_list) {
2725 qdf_mem_free(adapter->session.ap.sap_config.acs_cfg.ch_list);
2726 adapter->session.ap.sap_config.acs_cfg.ch_list = NULL;
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002727 }
2728}
2729
2730/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002731 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2732 * @work: Linux workqueue struct pointer for ACS work
2733 *
2734 * This function starts the ACS procedure which was marked pending when an ACS
2735 * procedure was in progress for a concurrent SAP interface.
2736 *
2737 * Return: None
2738 */
2739
2740static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2741{
Jeff Johnsone5006672017-08-29 14:39:02 -07002742 struct hdd_adapter *adapter = container_of(work, struct hdd_adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002743 acs_pending_work.work);
Kiran Kumar Lokere85cb36b2017-09-14 15:19:14 -07002744 if (!adapter)
2745 return;
2746 clear_bit(ACS_PENDING, &adapter->event_flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002747 wlan_hdd_cfg80211_start_acs(adapter);
2748}
2749
2750/**
2751 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2752 * @adapter: Pointer to SAP adapter struct
2753 * @pri_channel: SAP ACS procedure selected Primary channel
2754 * @sec_channel: SAP ACS procedure selected secondary channel
2755 *
2756 * This is a callback function from SAP module on ACS procedure is completed.
2757 * This function send the ACS selected channel information to hostapd
2758 *
2759 * Return: None
2760 */
2761
Jeff Johnsone5006672017-08-29 14:39:02 -07002762void wlan_hdd_cfg80211_acs_ch_select_evt(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002763{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002764 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsone4c11db2018-05-05 23:22:32 -07002765 tsap_config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002766 struct sk_buff *vendor_event;
2767 int ret_val;
Jeff Johnsone5006672017-08-29 14:39:02 -07002768 struct hdd_adapter *con_sap_adapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002769 uint16_t ch_width;
2770
2771 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002772 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002773 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2774 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2775 GFP_KERNEL);
2776
2777 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002778 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002779 return;
2780 }
2781
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002782 ret_val = nla_put_u8(vendor_event,
2783 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2784 sap_cfg->acs_cfg.pri_ch);
2785 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002786 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002787 kfree_skb(vendor_event);
2788 return;
2789 }
2790
2791 ret_val = nla_put_u8(vendor_event,
2792 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2793 sap_cfg->acs_cfg.ht_sec_ch);
2794 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002795 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002796 kfree_skb(vendor_event);
2797 return;
2798 }
2799
2800 ret_val = nla_put_u8(vendor_event,
2801 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2802 sap_cfg->acs_cfg.vht_seg0_center_ch);
2803 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002804 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002805 kfree_skb(vendor_event);
2806 return;
2807 }
2808
2809 ret_val = nla_put_u8(vendor_event,
2810 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2811 sap_cfg->acs_cfg.vht_seg1_center_ch);
2812 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002813 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002814 kfree_skb(vendor_event);
2815 return;
2816 }
2817
Himanshu Agarwal75e74412018-02-01 20:51:47 +05302818 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_160MHZ)
2819 ch_width = 160;
2820 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002821 ch_width = 80;
2822 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2823 ch_width = 40;
2824 else
2825 ch_width = 20;
2826
2827 ret_val = nla_put_u16(vendor_event,
2828 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2829 ch_width);
2830 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002831 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002832 kfree_skb(vendor_event);
2833 return;
2834 }
2835 if (sap_cfg->acs_cfg.pri_ch > 14)
2836 ret_val = nla_put_u8(vendor_event,
2837 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2838 QCA_ACS_MODE_IEEE80211A);
2839 else
2840 ret_val = nla_put_u8(vendor_event,
2841 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2842 QCA_ACS_MODE_IEEE80211G);
2843
2844 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002845 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002846 kfree_skb(vendor_event);
2847 return;
2848 }
2849
Mahesh Kumar Kalikot Veetilec1da142017-09-20 10:01:13 -07002850 hdd_debug("ACS result for %s: PRI_CH: %d SEC_CH: %d VHT_SEG0: %d VHT_SEG1: %d ACS_BW: %d",
2851 adapter->dev->name, sap_cfg->acs_cfg.pri_ch,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002852 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2853 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2854
2855 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2856 /* ***Note*** As already mentioned Completion variable usage is not
2857 * allowed here since ACS scan operation may take max 2.2 sec.
2858 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2859 * operation.
2860 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2861 * when Primary AP ACS is complete and secondary AP ACS is started here
2862 * immediately, Primary AP start_bss may come inbetween ACS operation
Jeff Johnson60ed45a2018-05-06 15:28:49 -07002863 * and overwrite Sec AP ACS parameters. Thus Sec AP ACS is executed with
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002864 * delay. This path and below constraint will be removed on sessionizing
2865 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2866 * As per design constraint user space control application must take
2867 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2868 * this code path. Sec AP hostapd should be started after Primary AP
2869 * start beaconing which can be confirmed by getchannel iwpriv command
2870 */
2871
2872 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2873 if (con_sap_adapter &&
2874 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002875 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2876 wlan_hdd_cfg80211_start_pending_acs);
hqu71a1a3b2018-01-23 15:38:13 +08002877 /* Lets give 1500ms for OBSS + START_BSS to complete */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002878 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
hqu71a1a3b2018-01-23 15:38:13 +08002879 msecs_to_jiffies(1500));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002880 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002881}
2882
2883static int
2884__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2885 struct wireless_dev *wdev,
2886 const void *data,
2887 int data_len)
2888{
Jeff Johnsonb8944722017-09-03 09:03:19 -07002889 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002890 struct sk_buff *skb = NULL;
2891 uint32_t fset = 0;
2892 int ret;
2893
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002894 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302895
Anurag Chouhan6d760662016-02-20 16:05:43 +05302896 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002897 hdd_err("Command not allowed in FTM mode");
2898 return -EPERM;
2899 }
2900
Jeff Johnsonb8944722017-09-03 09:03:19 -07002901 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302902 if (ret)
2903 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002904
2905 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002906 hdd_debug("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002907 fset |= WIFI_FEATURE_INFRA;
2908 }
Jeff Johnsonb8944722017-09-03 09:03:19 -07002909 if (true == hdd_is_5g_supported(hdd_ctx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002910 hdd_debug("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002911 fset |= WIFI_FEATURE_INFRA_5G;
2912 }
2913#ifdef WLAN_FEATURE_P2P
2914 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2915 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002916 hdd_debug("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002917 fset |= WIFI_FEATURE_P2P;
2918 }
2919#endif
2920 fset |= WIFI_FEATURE_SOFT_AP;
2921
2922 /* HOTSPOT is a supplicant feature, enable it by default */
2923 fset |= WIFI_FEATURE_HOTSPOT;
2924
2925#ifdef FEATURE_WLAN_EXTSCAN
Jeff Johnsonb8944722017-09-03 09:03:19 -07002926 if (hdd_ctx->config->extscan_enabled &&
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302927 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002928 hdd_debug("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002929 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2930 }
2931#endif
2932 if (wlan_hdd_nan_is_supported()) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002933 hdd_debug("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002934 fset |= WIFI_FEATURE_NAN;
2935 }
2936 if (sme_is_feature_supported_by_fw(RTT)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002937 hdd_debug("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002938 fset |= WIFI_FEATURE_D2D_RTT;
2939 fset |= WIFI_FEATURE_D2AP_RTT;
2940 }
2941#ifdef FEATURE_WLAN_SCAN_PNO
Jeff Johnsonb8944722017-09-03 09:03:19 -07002942 if (hdd_ctx->config->configPNOScanSupport &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002943 sme_is_feature_supported_by_fw(PNO)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002944 hdd_debug("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002945 fset |= WIFI_FEATURE_PNO;
2946 }
2947#endif
2948 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2949#ifdef FEATURE_WLAN_TDLS
Jeff Johnsonb8944722017-09-03 09:03:19 -07002950 if ((true == hdd_ctx->config->fEnableTDLSSupport) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002951 sme_is_feature_supported_by_fw(TDLS)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002952 hdd_debug("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002953 fset |= WIFI_FEATURE_TDLS;
2954 }
2955 if (sme_is_feature_supported_by_fw(TDLS) &&
Jeff Johnsonb8944722017-09-03 09:03:19 -07002956 (true == hdd_ctx->config->fEnableTDLSOffChannel) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002957 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002958 hdd_debug("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002959 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2960 }
2961#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002962 fset |= WIFI_FEATURE_AP_STA;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002963 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002964 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Srinivas Girigowda5a1da622017-07-12 17:07:44 -07002965 fset |= WIFI_FEATURE_SET_TX_POWER_LIMIT;
Sourav Mohapatra804359e2017-12-07 13:52:05 +05302966 fset |= WIFI_FEATURE_CONFIG_NDO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002967
2968 if (hdd_link_layer_stats_supported())
2969 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2970
Jeff Johnsonb8944722017-09-03 09:03:19 -07002971 if (hdd_roaming_supported(hdd_ctx))
Srinivas Girigowda8df27ea2017-01-06 12:42:16 -08002972 fset |= WIFI_FEATURE_CONTROL_ROAMING;
2973
2974 if (hdd_scan_random_mac_addr_supported())
2975 fset |= WIFI_FEATURE_SCAN_RAND;
2976
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002977 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2978 NLMSG_HDRLEN);
2979 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002980 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002981 return -EINVAL;
2982 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002983 hdd_debug("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002984 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002985 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002986 goto nla_put_failure;
2987 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302988 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302989 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002990nla_put_failure:
2991 kfree_skb(skb);
2992 return -EINVAL;
2993}
2994
2995/**
2996 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2997 * @wiphy: pointer to wireless wiphy structure.
2998 * @wdev: pointer to wireless_dev structure.
2999 * @data: Pointer to the data to be passed via vendor interface
3000 * @data_len:Length of the data to be passed
3001 *
3002 * Return: Return the Success or Failure code.
3003 */
3004static int
3005wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
3006 struct wireless_dev *wdev,
3007 const void *data, int data_len)
3008{
3009 int ret = 0;
3010
3011 cds_ssr_protect(__func__);
3012 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
3013 data, data_len);
3014 cds_ssr_unprotect(__func__);
3015
3016 return ret;
3017}
3018
3019/**
3020 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
3021 * @wiphy: pointer to wireless wiphy structure.
3022 * @wdev: pointer to wireless_dev structure.
3023 * @data: Pointer to the data to be passed via vendor interface
3024 * @data_len:Length of the data to be passed
3025 *
3026 * Set the MAC address that is to be used for scanning.
3027 *
3028 * Return: Return the Success or Failure code.
3029 */
3030static int
3031__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
3032 struct wireless_dev *wdev,
3033 const void *data,
3034 int data_len)
3035{
3036 tpSirScanMacOui pReqMsg = NULL;
Jeff Johnsonb8944722017-09-03 09:03:19 -07003037 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003038 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303039 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003040 int ret;
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003041 int len;
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +05303042 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07003043 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003044
Dustin Brownfdf17c12018-03-14 12:55:34 -07003045 hdd_enter_dev(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003046
Anurag Chouhan6d760662016-02-20 16:05:43 +05303047 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003048 hdd_err("Command not allowed in FTM mode");
3049 return -EPERM;
3050 }
3051
Jeff Johnsonb8944722017-09-03 09:03:19 -07003052 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303053 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003054 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003055
Jeff Johnsonb8944722017-09-03 09:03:19 -07003056 if (false == hdd_ctx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07003057 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003058 return -ENOTSUPP;
3059 }
3060
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003061 /*
3062 * audit note: it is ok to pass a NULL policy here since only
3063 * one attribute is parsed and it is explicitly validated
3064 */
Dustin Brown4ea21db2018-01-05 14:13:17 -08003065 if (wlan_cfg80211_nla_parse(tb,
3066 QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
3067 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003068 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003069 return -EINVAL;
3070 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303071 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003072 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07003073 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003074 return -ENOMEM;
3075 }
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003076
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003077 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003078 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003079 goto fail;
3080 }
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003081
3082 len = nla_len(tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]);
3083 if (len != sizeof(pReqMsg->oui)) {
3084 hdd_err("attr mac oui invalid size %d expected %zu",
3085 len, sizeof(pReqMsg->oui));
3086 goto fail;
3087 }
3088
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003089 nla_memcpy(&pReqMsg->oui[0],
3090 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
3091 sizeof(pReqMsg->oui));
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +05303092
3093 /* populate pReqMsg for mac addr randomization */
Jeff Johnson1b780e42017-10-31 14:11:45 -07003094 pReqMsg->vdev_id = adapter->session_id;
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +05303095 pReqMsg->enb_probe_req_sno_randomization = true;
3096
3097 hdd_debug("Oui (%02x:%02x:%02x), vdev_id = %d", pReqMsg->oui[0],
3098 pReqMsg->oui[1], pReqMsg->oui[2], pReqMsg->vdev_id);
Rajeev Kumar Sirasanagandlaaec0b082017-06-21 11:59:41 +05303099
Jeff Johnsonb8944722017-09-03 09:03:19 -07003100 hdd_update_ie_whitelist_attr(&pReqMsg->ie_whitelist, hdd_ctx->config);
Rajeev Kumar Sirasanagandlaaec0b082017-06-21 11:59:41 +05303101
Jeff Johnsonb8944722017-09-03 09:03:19 -07003102 status = sme_set_scanning_mac_oui(hdd_ctx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303103 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003104 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003105 goto fail;
3106 }
3107 return 0;
3108fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303109 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003110 return -EINVAL;
3111}
3112
3113/**
3114 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
3115 * @wiphy: pointer to wireless wiphy structure.
3116 * @wdev: pointer to wireless_dev structure.
3117 * @data: Pointer to the data to be passed via vendor interface
3118 * @data_len:Length of the data to be passed
3119 *
3120 * Set the MAC address that is to be used for scanning. This is an
3121 * SSR-protecting wrapper function.
3122 *
3123 * Return: Return the Success or Failure code.
3124 */
3125static int
3126wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
3127 struct wireless_dev *wdev,
3128 const void *data,
3129 int data_len)
3130{
3131 int ret;
3132
3133 cds_ssr_protect(__func__);
3134 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
3135 data, data_len);
3136 cds_ssr_unprotect(__func__);
3137
3138 return ret;
3139}
3140
Rajeev Kumar Sirasanagandlabff450c2017-06-05 19:03:25 +05303141#define MAX_CONCURRENT_MATRIX \
3142 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX
3143#define MATRIX_CONFIG_PARAM_SET_SIZE_MAX \
3144 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX
3145static const struct nla_policy
3146wlan_hdd_get_concurrency_matrix_policy[MAX_CONCURRENT_MATRIX + 1] = {
3147 [MATRIX_CONFIG_PARAM_SET_SIZE_MAX] = {.type = NLA_U32},
3148};
3149
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003150/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303151 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
3152 * @wiphy: pointer phy adapter
3153 * @wdev: pointer to wireless device structure
3154 * @data: pointer to data buffer
3155 * @data_len: length of data
3156 *
3157 * This routine will give concurrency matrix
3158 *
3159 * Return: int status code
3160 */
3161static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
3162 struct wireless_dev *wdev,
3163 const void *data,
3164 int data_len)
3165{
3166 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
3167 uint8_t i, feature_sets, max_feature_sets;
Rajeev Kumar Sirasanagandlabff450c2017-06-05 19:03:25 +05303168 struct nlattr *tb[MAX_CONCURRENT_MATRIX + 1];
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303169 struct sk_buff *reply_skb;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07003170 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303171 int ret;
3172
Dustin Brownfdf17c12018-03-14 12:55:34 -07003173 hdd_enter_dev(wdev->netdev);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303174
3175 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3176 hdd_err("Command not allowed in FTM mode");
3177 return -EPERM;
3178 }
3179
3180 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303181 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303182 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303183
Dustin Brown4ea21db2018-01-05 14:13:17 -08003184 if (wlan_cfg80211_nla_parse(tb, MAX_CONCURRENT_MATRIX, data, data_len,
3185 wlan_hdd_get_concurrency_matrix_policy)) {
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303186 hdd_err("Invalid ATTR");
3187 return -EINVAL;
3188 }
3189
3190 /* Parse and fetch max feature set */
Rajeev Kumar Sirasanagandlabff450c2017-06-05 19:03:25 +05303191 if (!tb[MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303192 hdd_err("Attr max feature set size failed");
3193 return -EINVAL;
3194 }
Rajeev Kumar Sirasanagandlabff450c2017-06-05 19:03:25 +05303195 max_feature_sets = nla_get_u32(tb[MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003196 hdd_debug("Max feature set size: %d", max_feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303197
3198 /* Fill feature combination matrix */
3199 feature_sets = 0;
3200 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07003201 WIFI_FEATURE_P2P;
3202 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
3203 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303204 /* Add more feature combinations here */
3205
3206 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003207 hdd_debug("Number of feature sets: %d", feature_sets);
3208 hdd_debug("Feature set matrix");
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303209 for (i = 0; i < feature_sets; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003210 hdd_debug("[%d] 0x%02X", i, feature_set_matrix[i]);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303211
3212 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
3213 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
3214 if (!reply_skb) {
3215 hdd_err("Feature set matrix: buffer alloc fail");
3216 return -ENOMEM;
3217 }
3218
3219 if (nla_put_u32(reply_skb,
Jeff Johnson59eb5fd2017-10-05 09:42:39 -07003220 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
3221 feature_sets) ||
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303222 nla_put(reply_skb,
Jeff Johnson59eb5fd2017-10-05 09:42:39 -07003223 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
3224 sizeof(u32) * feature_sets,
3225 feature_set_matrix)) {
3226 hdd_err("nla put fail");
3227 kfree_skb(reply_skb);
3228 return -EINVAL;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303229 }
3230 return cfg80211_vendor_cmd_reply(reply_skb);
3231}
3232
Rajeev Kumar Sirasanagandlabff450c2017-06-05 19:03:25 +05303233#undef MAX_CONCURRENT_MATRIX
3234#undef MATRIX_CONFIG_PARAM_SET_SIZE_MAX
3235
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303236/**
3237 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
3238 * @wiphy: pointer to wireless wiphy structure.
3239 * @wdev: pointer to wireless_dev structure.
3240 * @data: Pointer to the data to be passed via vendor interface
3241 * @data_len:Length of the data to be passed
3242 *
3243 * Retrieves the concurrency feature set matrix
3244 *
3245 * Return: 0 on success, negative errno on failure
3246 */
3247static int
3248wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
3249 struct wireless_dev *wdev,
3250 const void *data,
3251 int data_len)
3252{
3253 int ret;
3254
3255 cds_ssr_protect(__func__);
3256 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
3257 data, data_len);
3258 cds_ssr_unprotect(__func__);
3259
3260 return ret;
3261}
3262
3263/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003264 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
3265 * @feature_flags: pointer to the byte array of features.
3266 * @feature: Feature to be turned ON in the byte array.
3267 *
3268 * Return: None
3269 *
3270 * This is called to turn ON or SET the feature flag for the requested feature.
3271 **/
3272#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07003273static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
3274 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003275{
3276 uint32_t index;
3277 uint8_t bit_mask;
3278
3279 index = feature / NUM_BITS_IN_BYTE;
3280 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
3281 feature_flags[index] |= bit_mask;
3282}
3283
3284/**
3285 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
3286 * @wiphy: pointer to wireless wiphy structure.
3287 * @wdev: pointer to wireless_dev structure.
3288 * @data: Pointer to the data to be passed via vendor interface
3289 * @data_len:Length of the data to be passed
3290 *
3291 * This is called when wlan driver needs to send supported feature set to
3292 * supplicant upon a request/query from the supplicant.
3293 *
3294 * Return: Return the Success or Failure code.
3295 **/
3296#define MAX_CONCURRENT_CHAN_ON_24G 2
3297#define MAX_CONCURRENT_CHAN_ON_5G 2
3298static int
3299__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
3300 struct wireless_dev *wdev,
3301 const void *data, int data_len)
3302{
3303 struct sk_buff *skb = NULL;
3304 uint32_t dbs_capability = 0;
3305 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303306 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003307 int ret_val;
3308
3309 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07003310 struct hdd_context *hdd_ctx_ptr = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003311
Dustin Brownfdf17c12018-03-14 12:55:34 -07003312 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08003313
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003314 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
3315 if (ret_val)
3316 return ret_val;
3317
Anurag Chouhan6d760662016-02-20 16:05:43 +05303318 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003319 hdd_err("Command not allowed in FTM mode");
3320 return -EPERM;
3321 }
3322
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07003323 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003324 hdd_debug("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003325 wlan_hdd_cfg80211_set_feature(feature_flags,
3326 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
3327 }
3328
3329 wlan_hdd_cfg80211_set_feature(feature_flags,
3330 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08003331 if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx_ptr->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003332 wlan_hdd_cfg80211_set_feature(feature_flags,
3333 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07003334
3335 if (wma_is_p2p_lo_capable())
3336 wlan_hdd_cfg80211_set_feature(feature_flags,
3337 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
3338
yeshwanth sriram guntuka1413dfb2017-06-23 14:09:48 +05303339 if (hdd_ctx_ptr->config->oce_sta_enabled)
3340 wlan_hdd_cfg80211_set_feature(feature_flags,
3341 QCA_WLAN_VENDOR_FEATURE_OCE_STA);
3342
3343 if (hdd_ctx_ptr->config->oce_sap_enabled)
3344 wlan_hdd_cfg80211_set_feature(feature_flags,
3345 QCA_WLAN_VENDOR_FEATURE_OCE_STA_CFON);
3346
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003347 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
3348 NLMSG_HDRLEN);
3349
3350 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003351 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003352 return -ENOMEM;
3353 }
3354
3355 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
3356 sizeof(feature_flags), feature_flags))
3357 goto nla_put_failure;
3358
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08003359 ret = policy_mgr_get_dbs_hw_modes(hdd_ctx_ptr->hdd_psoc,
3360 &one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303361 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003362 if (one_by_one_dbs)
3363 dbs_capability = DRV_DBS_CAPABILITY_1X1;
3364
3365 if (two_by_two_dbs)
3366 dbs_capability = DRV_DBS_CAPABILITY_2X2;
3367
3368 if (!one_by_one_dbs && !two_by_two_dbs)
3369 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
3370 } else {
3371 hdd_err("wma_get_dbs_hw_mode failed");
3372 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
3373 }
3374
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003375 hdd_debug("dbs_capability is %d", dbs_capability);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003376
3377 if (nla_put_u32(skb,
Ganesh Kondabattinid921ed92017-06-20 16:40:48 +05303378 QCA_WLAN_VENDOR_ATTR_CONCURRENCY_CAPA,
3379 dbs_capability))
3380 goto nla_put_failure;
3381
3382
3383 if (nla_put_u32(skb,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003384 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
3385 MAX_CONCURRENT_CHAN_ON_24G))
3386 goto nla_put_failure;
3387
3388 if (nla_put_u32(skb,
3389 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
3390 MAX_CONCURRENT_CHAN_ON_5G))
3391 goto nla_put_failure;
3392
3393 return cfg80211_vendor_cmd_reply(skb);
3394
3395nla_put_failure:
3396 kfree_skb(skb);
3397 return -EINVAL;
3398}
3399
3400/**
3401 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
3402 * @wiphy: pointer to wireless wiphy structure.
3403 * @wdev: pointer to wireless_dev structure.
3404 * @data: Pointer to the data to be passed via vendor interface
3405 * @data_len:Length of the data to be passed
3406 *
3407 * This is called when wlan driver needs to send supported feature set to
3408 * supplicant upon a request/query from the supplicant.
3409 *
3410 * Return: Return the Success or Failure code.
3411 */
3412static int
3413wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
3414 struct wireless_dev *wdev,
3415 const void *data, int data_len)
3416{
3417 int ret;
3418
3419 cds_ssr_protect(__func__);
3420 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
3421 data, data_len);
3422 cds_ssr_unprotect(__func__);
3423
3424 return ret;
3425}
3426
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303427#define PARAM_NUM_NW \
3428 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
3429#define PARAM_SET_BSSID \
3430 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003431#define PARAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303432#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Ravi Kumar Bokka6cb9b372017-06-08 20:12:39 +05303433#define MAX_ROAMING_PARAM \
3434 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003435#define PARAM_NUM_BSSID \
3436 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID
3437#define PARAM_BSSID_PREFS \
3438 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS
3439#define PARAM_ROAM_BSSID \
3440 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID
3441#define PARAM_RSSI_MODIFIER \
3442 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER
3443#define PARAMS_NUM_BSSID \
3444 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID
3445#define PARAM_BSSID_PARAMS \
3446 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS
3447#define PARAM_A_BAND_BOOST_THLD \
3448 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD
3449#define PARAM_A_BAND_PELT_THLD \
3450 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD
3451#define PARAM_A_BAND_BOOST_FACTOR \
3452 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR
3453#define PARAM_A_BAND_PELT_FACTOR \
3454 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR
3455#define PARAM_A_BAND_MAX_BOOST \
3456 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST
3457#define PARAM_ROAM_HISTERESYS \
3458 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS
3459#define PARAM_RSSI_TRIGGER \
3460 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER
3461#define PARAM_ROAM_ENABLE \
3462 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE
3463
Ravi Kumar Bokka6cb9b372017-06-08 20:12:39 +05303464
3465static const struct nla_policy
3466wlan_hdd_set_roam_param_policy[MAX_ROAMING_PARAM + 1] = {
3467 [QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD] = {.type = NLA_U32},
3468 [QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID] = {.type = NLA_U32},
3469 [PARAM_NUM_NW] = {.type = NLA_U32},
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003470 [PARAM_A_BAND_BOOST_FACTOR] = {.type = NLA_U32},
3471 [PARAM_A_BAND_PELT_FACTOR] = {.type = NLA_U32},
3472 [PARAM_A_BAND_MAX_BOOST] = {.type = NLA_U32},
3473 [PARAM_ROAM_HISTERESYS] = {.type = NLA_S32},
3474 [PARAM_A_BAND_BOOST_THLD] = {.type = NLA_S32},
Srinivas Girigowda4ffe7c82017-07-18 11:45:23 -07003475 [PARAM_A_BAND_PELT_THLD] = {.type = NLA_S32},
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003476 [PARAM_RSSI_TRIGGER] = {.type = NLA_U32},
3477 [PARAM_ROAM_ENABLE] = { .type = NLA_S32},
3478 [PARAM_NUM_BSSID] = {.type = NLA_U32},
3479 [PARAM_RSSI_MODIFIER] = {.type = NLA_U32},
3480 [PARAMS_NUM_BSSID] = {.type = NLA_U32},
3481 [PARAM_ROAM_BSSID] = {.type = NLA_UNSPEC, .len = QDF_MAC_ADDR_SIZE},
3482 [PARAM_SET_BSSID] = {.type = NLA_UNSPEC, .len = QDF_MAC_ADDR_SIZE},
Ravi Kumar Bokka6cb9b372017-06-08 20:12:39 +05303483};
3484
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003485/**
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003486 * hdd_set_white_list() - parse white list
3487 * @hddctx: HDD context
3488 * @roam_params: roam params
3489 * @tb: list of attributes
3490 * @session_id: session id
3491 *
3492 * Return: 0 on success; error number on failure
3493 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07003494static int hdd_set_white_list(struct hdd_context *hddctx,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003495 struct roam_ext_params *roam_params,
3496 struct nlattr **tb, uint8_t session_id)
3497{
3498 int rem, i;
3499 uint32_t buf_len = 0, count;
3500 struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
3501 struct nlattr *curr_attr = NULL;
3502
3503 i = 0;
3504 if (tb[PARAM_NUM_NW]) {
3505 count = nla_get_u32(tb[PARAM_NUM_NW]);
3506 } else {
3507 hdd_err("Number of networks is not provided");
3508 goto fail;
3509 }
3510
3511 if (count && tb[PARAM_SSID_LIST]) {
3512 nla_for_each_nested(curr_attr,
3513 tb[PARAM_SSID_LIST], rem) {
Dustin Brown4ea21db2018-01-05 14:13:17 -08003514 if (wlan_cfg80211_nla_parse(tb2,
3515 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
3516 nla_data(curr_attr),
3517 nla_len(curr_attr),
3518 wlan_hdd_set_roam_param_policy)) {
3519 hdd_err("nla_parse failed");
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003520 goto fail;
3521 }
3522 /* Parse and Fetch allowed SSID list*/
3523 if (!tb2[PARAM_LIST_SSID]) {
3524 hdd_err("attr allowed ssid failed");
3525 goto fail;
3526 }
3527 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
3528 /*
3529 * Upper Layers include a null termination
3530 * character. Check for the actual permissible
3531 * length of SSID and also ensure not to copy
3532 * the NULL termination character to the driver
3533 * buffer.
3534 */
3535 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
3536 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
3537 nla_memcpy(roam_params->ssid_allowed_list[i].ssId,
3538 tb2[PARAM_LIST_SSID], buf_len - 1);
3539 roam_params->ssid_allowed_list[i].length = buf_len - 1;
3540 hdd_debug("SSID[%d]: %.*s,length = %d",
3541 i,
3542 roam_params->ssid_allowed_list[i].length,
3543 roam_params->ssid_allowed_list[i].ssId,
3544 roam_params->ssid_allowed_list[i].length);
3545 i++;
3546 } else {
3547 hdd_err("Invalid buffer length");
3548 }
3549 }
3550 }
3551
3552 if (i != count) {
3553 hdd_err("Invalid number of SSIDs i = %d, count = %d", i, count);
3554 goto fail;
3555 }
3556
3557 roam_params->num_ssid_allowed_list = i;
3558 hdd_debug("Num of Allowed SSID %d", roam_params->num_ssid_allowed_list);
3559 sme_update_roam_params(hddctx->hHal, session_id,
3560 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
3561 return 0;
3562
3563fail:
3564 return -EINVAL;
3565}
3566
3567/**
3568 * hdd_set_bssid_prefs() - parse set bssid prefs
3569 * @hddctx: HDD context
3570 * @roam_params: roam params
3571 * @tb: list of attributes
3572 * @session_id: session id
3573 *
3574 * Return: 0 on success; error number on failure
3575 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07003576static int hdd_set_bssid_prefs(struct hdd_context *hddctx,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003577 struct roam_ext_params *roam_params,
3578 struct nlattr **tb, uint8_t session_id)
3579{
3580 int rem, i;
3581 uint32_t count;
3582 struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
3583 struct nlattr *curr_attr = NULL;
3584
3585 /* Parse and fetch number of preferred BSSID */
3586 if (!tb[PARAM_NUM_BSSID]) {
3587 hdd_err("attr num of preferred bssid failed");
3588 goto fail;
3589 }
3590 count = nla_get_u32(tb[PARAM_NUM_BSSID]);
3591 if (count > MAX_BSSID_FAVORED) {
3592 hdd_err("Preferred BSSID count %u exceeds max %u",
3593 count, MAX_BSSID_FAVORED);
3594 goto fail;
3595 }
3596 hdd_debug("Num of Preferred BSSID (%d)", count);
3597 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS]) {
3598 hdd_err("attr Preferred BSSID failed");
3599 goto fail;
3600 }
3601
3602 i = 0;
3603 nla_for_each_nested(curr_attr,
3604 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
3605 rem) {
3606 if (i == count) {
3607 hdd_warn("Ignoring excess Preferred BSSID");
3608 break;
3609 }
3610
Dustin Brown4ea21db2018-01-05 14:13:17 -08003611 if (wlan_cfg80211_nla_parse(tb2,
3612 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3613 nla_data(curr_attr),
3614 nla_len(curr_attr),
3615 wlan_hdd_set_roam_param_policy)) {
3616 hdd_err("nla_parse failed");
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003617 goto fail;
3618 }
3619 /* Parse and fetch MAC address */
3620 if (!tb2[PARAM_ROAM_BSSID]) {
3621 hdd_err("attr mac address failed");
3622 goto fail;
3623 }
3624 nla_memcpy(roam_params->bssid_favored[i].bytes,
3625 tb2[PARAM_ROAM_BSSID],
3626 QDF_MAC_ADDR_SIZE);
3627 hdd_debug(MAC_ADDRESS_STR,
3628 MAC_ADDR_ARRAY(roam_params->bssid_favored[i].bytes));
3629 /* Parse and fetch preference factor*/
3630 if (!tb2[PARAM_RSSI_MODIFIER]) {
3631 hdd_err("BSSID Preference score failed");
3632 goto fail;
3633 }
3634 roam_params->bssid_favored_factor[i] = nla_get_u32(
3635 tb2[PARAM_RSSI_MODIFIER]);
3636 hdd_debug("BSSID Preference score (%d)",
3637 roam_params->bssid_favored_factor[i]);
3638 i++;
3639 }
3640 if (i < count)
3641 hdd_warn("Num Preferred BSSID %u less than expected %u",
3642 i, count);
3643
3644 roam_params->num_bssid_favored = i;
3645 sme_update_roam_params(hddctx->hHal, session_id,
3646 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3647
3648 return 0;
3649
3650fail:
3651 return -EINVAL;
3652}
3653
3654/**
3655 * hdd_set_blacklist_bssid() - parse set blacklist bssid
3656 * @hddctx: HDD context
3657 * @roam_params: roam params
3658 * @tb: list of attributes
3659 * @session_id: session id
3660 *
3661 * Return: 0 on success; error number on failure
3662 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07003663static int hdd_set_blacklist_bssid(struct hdd_context *hddctx,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003664 struct roam_ext_params *roam_params,
3665 struct nlattr **tb,
3666 uint8_t session_id)
3667{
3668 int rem, i;
3669 uint32_t count;
3670 struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
3671 struct nlattr *curr_attr = NULL;
3672
3673 /* Parse and fetch number of blacklist BSSID */
3674 if (!tb[PARAMS_NUM_BSSID]) {
3675 hdd_err("attr num of blacklist bssid failed");
3676 goto fail;
3677 }
3678 count = nla_get_u32(tb[PARAMS_NUM_BSSID]);
3679 if (count > MAX_BSSID_AVOID_LIST) {
3680 hdd_err("Blacklist BSSID count %u exceeds max %u",
3681 count, MAX_BSSID_AVOID_LIST);
3682 goto fail;
3683 }
3684 hdd_debug("Num of blacklist BSSID (%d)", count);
3685
3686 i = 0;
3687 if (count && tb[PARAM_BSSID_PARAMS]) {
3688 nla_for_each_nested(curr_attr,
3689 tb[PARAM_BSSID_PARAMS],
3690 rem) {
3691 if (i == count) {
3692 hdd_warn("Ignoring excess Blacklist BSSID");
3693 break;
3694 }
3695
Dustin Brown4ea21db2018-01-05 14:13:17 -08003696 if (wlan_cfg80211_nla_parse(tb2,
Dustin Brown3fb15042017-08-15 15:54:49 -07003697 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3698 nla_data(curr_attr),
3699 nla_len(curr_attr),
3700 wlan_hdd_set_roam_param_policy)) {
Dustin Brown4ea21db2018-01-05 14:13:17 -08003701 hdd_err("nla_parse failed");
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003702 goto fail;
3703 }
3704 /* Parse and fetch MAC address */
3705 if (!tb2[PARAM_SET_BSSID]) {
3706 hdd_err("attr blacklist addr failed");
3707 goto fail;
3708 }
3709 nla_memcpy(roam_params->bssid_avoid_list[i].bytes,
3710 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3711 hdd_debug(MAC_ADDRESS_STR,
3712 MAC_ADDR_ARRAY(roam_params->bssid_avoid_list[i].bytes));
3713 i++;
3714 }
3715 }
3716
3717 if (i < count)
3718 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3719 i, count);
3720
3721 roam_params->num_bssid_avoid_list = i;
3722 sme_update_roam_params(hddctx->hHal, session_id,
3723 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3724
3725 return 0;
3726fail:
3727 return -EINVAL;
3728}
3729
3730/**
3731 * hdd_set_ext_roam_params() - parse ext roam params
3732 * @hddctx: HDD context
3733 * @roam_params: roam params
3734 * @tb: list of attributes
3735 * @session_id: session id
3736 *
3737 * Return: 0 on success; error number on failure
3738 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07003739static int hdd_set_ext_roam_params(struct hdd_context *hddctx,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003740 const void *data, int data_len,
3741 uint8_t session_id,
3742 struct roam_ext_params *roam_params)
3743{
3744 uint32_t cmd_type, req_id;
3745 struct nlattr *tb[MAX_ROAMING_PARAM + 1];
3746 int ret;
3747
Dustin Brown4ea21db2018-01-05 14:13:17 -08003748 if (wlan_cfg80211_nla_parse(tb, MAX_ROAMING_PARAM, data, data_len,
3749 wlan_hdd_set_roam_param_policy)) {
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003750 hdd_err("Invalid ATTR");
3751 return -EINVAL;
3752 }
3753 /* Parse and fetch Command Type */
3754 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
3755 hdd_err("roam cmd type failed");
3756 goto fail;
3757 }
3758
3759 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
3760 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
3761 hdd_err("attr request id failed");
3762 goto fail;
3763 }
3764 req_id = nla_get_u32(
3765 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
3766 hdd_debug("Req Id: %u Cmd Type: %u", req_id, cmd_type);
3767 switch (cmd_type) {
3768 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
3769 ret = hdd_set_white_list(hddctx, roam_params, tb, session_id);
3770 if (ret)
3771 goto fail;
3772 break;
3773
3774 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
3775 /* Parse and fetch 5G Boost Threshold */
3776 if (!tb[PARAM_A_BAND_BOOST_THLD]) {
3777 hdd_err("5G boost threshold failed");
3778 goto fail;
3779 }
3780 roam_params->raise_rssi_thresh_5g = nla_get_s32(
3781 tb[PARAM_A_BAND_BOOST_THLD]);
3782 hdd_debug("5G Boost Threshold (%d)",
3783 roam_params->raise_rssi_thresh_5g);
3784 /* Parse and fetch 5G Penalty Threshold */
Srinivas Girigowda4ffe7c82017-07-18 11:45:23 -07003785 if (!tb[PARAM_A_BAND_PELT_THLD]) {
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003786 hdd_err("5G penalty threshold failed");
3787 goto fail;
3788 }
3789 roam_params->drop_rssi_thresh_5g = nla_get_s32(
Srinivas Girigowda4ffe7c82017-07-18 11:45:23 -07003790 tb[PARAM_A_BAND_PELT_THLD]);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003791 hdd_debug("5G Penalty Threshold (%d)",
3792 roam_params->drop_rssi_thresh_5g);
3793 /* Parse and fetch 5G Boost Factor */
3794 if (!tb[PARAM_A_BAND_BOOST_FACTOR]) {
3795 hdd_err("5G boost Factor failed");
3796 goto fail;
3797 }
3798 roam_params->raise_factor_5g = nla_get_u32(
3799 tb[PARAM_A_BAND_BOOST_FACTOR]);
3800 hdd_debug("5G Boost Factor (%d)",
3801 roam_params->raise_factor_5g);
3802 /* Parse and fetch 5G Penalty factor */
3803 if (!tb[PARAM_A_BAND_PELT_FACTOR]) {
3804 hdd_err("5G Penalty Factor failed");
3805 goto fail;
3806 }
3807 roam_params->drop_factor_5g = nla_get_u32(
3808 tb[PARAM_A_BAND_PELT_FACTOR]);
3809 hdd_debug("5G Penalty factor (%d)",
3810 roam_params->drop_factor_5g);
3811 /* Parse and fetch 5G Max Boost */
3812 if (!tb[PARAM_A_BAND_MAX_BOOST]) {
3813 hdd_err("5G Max Boost failed");
3814 goto fail;
3815 }
3816 roam_params->max_raise_rssi_5g = nla_get_u32(
3817 tb[PARAM_A_BAND_MAX_BOOST]);
3818 hdd_debug("5G Max Boost (%d)",
3819 roam_params->max_raise_rssi_5g);
3820 /* Parse and fetch Rssi Diff */
3821 if (!tb[PARAM_ROAM_HISTERESYS]) {
3822 hdd_err("Rssi Diff failed");
3823 goto fail;
3824 }
3825 roam_params->rssi_diff = nla_get_s32(
3826 tb[PARAM_ROAM_HISTERESYS]);
3827 hdd_debug("RSSI Diff (%d)",
3828 roam_params->rssi_diff);
3829 /* Parse and fetch Alert Rssi Threshold */
3830 if (!tb[PARAM_RSSI_TRIGGER]) {
3831 hdd_err("Alert Rssi Threshold failed");
3832 goto fail;
3833 }
3834 roam_params->alert_rssi_threshold = nla_get_u32(
3835 tb[PARAM_RSSI_TRIGGER]);
3836 hdd_debug("Alert RSSI Threshold (%d)",
3837 roam_params->alert_rssi_threshold);
3838 sme_update_roam_params(hddctx->hHal, session_id,
3839 roam_params,
3840 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
3841 break;
3842 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
3843 /* Parse and fetch Activate Good Rssi Roam */
3844 if (!tb[PARAM_ROAM_ENABLE]) {
3845 hdd_err("Activate Good Rssi Roam failed");
3846 goto fail;
3847 }
3848 roam_params->good_rssi_roam = nla_get_s32(
3849 tb[PARAM_ROAM_ENABLE]);
3850 hdd_debug("Activate Good Rssi Roam (%d)",
3851 roam_params->good_rssi_roam);
3852 sme_update_roam_params(hddctx->hHal, session_id,
3853 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
3854 break;
3855 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
3856 ret = hdd_set_bssid_prefs(hddctx, roam_params, tb, session_id);
3857 if (ret)
3858 goto fail;
3859 break;
3860 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3861 ret = hdd_set_blacklist_bssid(hddctx, roam_params, tb, session_id);
3862 if (ret)
3863 goto fail;
3864 break;
3865 }
3866
3867 return 0;
3868
3869fail:
3870 return -EINVAL;
3871}
3872
3873/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003874 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
3875 * @wiphy: The wiphy structure
3876 * @wdev: The wireless device
3877 * @data: Data passed by framework
3878 * @data_len: Parameters to be configured passed as data
3879 *
3880 * The roaming related parameters are configured by the framework
3881 * using this interface.
3882 *
3883 * Return: Return either success or failure code.
3884 */
3885static int
3886__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3887 struct wireless_dev *wdev, const void *data, int data_len)
3888{
3889 struct net_device *dev = wdev->netdev;
Jeff Johnsonce2ba702017-10-02 13:30:24 -07003890 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -07003891 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003892 struct roam_ext_params *roam_params = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003893 int ret;
3894
Dustin Brownfdf17c12018-03-14 12:55:34 -07003895 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08003896
Anurag Chouhan6d760662016-02-20 16:05:43 +05303897 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003898 hdd_err("Command not allowed in FTM mode");
3899 return -EPERM;
3900 }
3901
Jeff Johnsonb8944722017-09-03 09:03:19 -07003902 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303903 if (ret)
3904 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003905
Jeff Johnsonb8944722017-09-03 09:03:19 -07003906 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05303907 hdd_err("Driver Modules are closed");
3908 return -EINVAL;
3909 }
3910
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003911 roam_params = qdf_mem_malloc(sizeof(*roam_params));
3912 if (!roam_params) {
3913 hdd_err("failed to allocate memory");
3914 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003915 }
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003916
Jeff Johnsonb8944722017-09-03 09:03:19 -07003917 ret = hdd_set_ext_roam_params(hdd_ctx, data, data_len,
Jeff Johnson1b780e42017-10-31 14:11:45 -07003918 adapter->session_id, roam_params);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003919 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003920 goto fail;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303921
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003922 if (roam_params)
3923 qdf_mem_free(roam_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003924 return 0;
3925fail:
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003926 if (roam_params)
3927 qdf_mem_free(roam_params);
3928
3929 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003930}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303931#undef PARAM_NUM_NW
3932#undef PARAM_SET_BSSID
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003933#undef PARAM_SSID_LIST
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303934#undef PARAM_LIST_SSID
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003935#undef MAX_ROAMING_PARAM
3936#undef PARAM_NUM_BSSID
3937#undef PARAM_BSSID_PREFS
3938#undef PARAM_ROAM_BSSID
3939#undef PARAM_RSSI_MODIFIER
3940#undef PARAMS_NUM_BSSID
3941#undef PARAM_BSSID_PARAMS
3942#undef PARAM_A_BAND_BOOST_THLD
3943#undef PARAM_A_BAND_PELT_THLD
3944#undef PARAM_A_BAND_BOOST_FACTOR
3945#undef PARAM_A_BAND_PELT_FACTOR
3946#undef PARAM_A_BAND_MAX_BOOST
3947#undef PARAM_ROAM_HISTERESYS
3948#undef PARAM_RSSI_TRIGGER
3949#undef PARAM_ROAM_ENABLE
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303950
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003951
3952/**
3953 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3954 * @wiphy: pointer to wireless wiphy structure.
3955 * @wdev: pointer to wireless_dev structure.
3956 * @data: Pointer to the data to be passed via vendor interface
3957 * @data_len:Length of the data to be passed
3958 *
3959 * Return: Return the Success or Failure code.
3960 */
3961static int
3962wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3963 struct wireless_dev *wdev,
3964 const void *data,
3965 int data_len)
3966{
3967 int ret;
3968
3969 cds_ssr_protect(__func__);
3970 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3971 data, data_len);
3972 cds_ssr_unprotect(__func__);
3973
3974 return ret;
3975}
3976
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05303977#define PWR_SAVE_FAIL_CMD_INDEX \
3978 QCA_NL80211_VENDOR_SUBCMD_PWR_SAVE_FAIL_DETECTED_INDEX
3979/**
3980 * hdd_chip_pwr_save_fail_detected_cb() - chip power save failure detected
3981 * callback
3982 * @hddctx: HDD context
3983 * @data: chip power save failure detected data
3984 *
3985 * This function reads the chip power save failure detected data and fill in
3986 * the skb with NL attributes and send up the NL event.
3987 * This callback execute in atomic context and must not invoke any
3988 * blocking calls.
3989 *
3990 * Return: none
3991 */
3992void hdd_chip_pwr_save_fail_detected_cb(void *hddctx,
3993 struct chip_pwr_save_fail_detected_params
3994 *data)
3995{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07003996 struct hdd_context *hdd_ctx = hddctx;
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05303997 struct sk_buff *skb;
3998 int flags = cds_get_gfp_flags();
3999
Dustin Brown491d54b2018-03-14 12:39:11 -07004000 hdd_enter();
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304001
4002 if (wlan_hdd_validate_context(hdd_ctx))
4003 return;
4004
4005 if (!data) {
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07004006 hdd_debug("data is null");
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304007 return;
4008 }
4009
4010 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
4011 NULL, NLMSG_HDRLEN +
4012 sizeof(data->failure_reason_code) +
4013 NLMSG_HDRLEN, PWR_SAVE_FAIL_CMD_INDEX,
4014 flags);
4015
4016 if (!skb) {
Dustin Brown5e89ef82018-03-14 11:50:23 -07004017 hdd_info("cfg80211_vendor_event_alloc failed");
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304018 return;
4019 }
4020
Dustin Brownbacc48f2018-03-14 14:48:44 -07004021 hdd_debug("failure reason code: %u", data->failure_reason_code);
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304022
4023 if (nla_put_u32(skb,
4024 QCA_ATTR_CHIP_POWER_SAVE_FAILURE_REASON,
4025 data->failure_reason_code))
4026 goto fail;
4027
4028 cfg80211_vendor_event(skb, flags);
Dustin Browne74003f2018-03-14 12:51:58 -07004029 hdd_exit();
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304030 return;
4031
4032fail:
4033 kfree_skb(skb);
4034}
4035#undef PWR_SAVE_FAIL_CMD_INDEX
4036
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004037static const struct nla_policy
4038wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
4039 +1] = {
4040 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
4041};
4042
4043/**
4044 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
4045 * @hdd_ctx: HDD context
4046 * @device_mode: device mode
4047 * Return: bool
4048 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004049static bool wlan_hdd_check_dfs_channel_for_adapter(struct hdd_context *hdd_ctx,
Jeff Johnsonc1e62782017-11-09 09:50:17 -08004050 enum QDF_OPMODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004051{
Jeff Johnsone5006672017-08-29 14:39:02 -07004052 struct hdd_adapter *adapter;
Jeff Johnson87251032017-08-29 13:31:11 -07004053 struct hdd_ap_ctx *ap_ctx;
Jeff Johnson40dae4e2017-08-29 14:00:25 -07004054 struct hdd_station_ctx *sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004055
Dustin Brown920397d2017-12-13 16:27:50 -08004056 hdd_for_each_adapter(hdd_ctx, adapter) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004057 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08004058 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004059 ap_ctx =
4060 WLAN_HDD_GET_AP_CTX_PTR(adapter);
4061
4062 /*
4063 * if there is SAP already running on DFS channel,
4064 * do not disable scan on dfs channels. Note that
4065 * with SAP on DFS, there cannot be conurrency on
4066 * single radio. But then we can have multiple
4067 * radios !!
4068 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07004069 if (CHANNEL_STATE_DFS == wlan_reg_get_channel_state(
4070 hdd_ctx->hdd_pdev,
Jeff Johnson01206862017-10-27 20:55:59 -07004071 ap_ctx->operating_channel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004072 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004073 return true;
4074 }
4075 }
4076
4077 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08004078 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004079 sta_ctx =
4080 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
4081
4082 /*
4083 * if STA is already connected on DFS channel,
4084 * do not disable scan on dfs channels
4085 */
4086 if (hdd_conn_is_connected(sta_ctx) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07004087 (CHANNEL_STATE_DFS ==
4088 wlan_reg_get_channel_state(hdd_ctx->hdd_pdev,
4089 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07004090 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004091 return true;
4092 }
4093 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004094 }
4095
4096 return false;
4097}
4098
4099/**
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004100 * wlan_hdd_enable_dfs_chan_scan() - disable/enable DFS channels
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004101 * @hdd_ctx: HDD context within host driver
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004102 * @enable_dfs_channels: If true, DFS channels can be used for scanning
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004103 *
4104 * Loops through devices to see who is operating on DFS channels
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004105 * and then disables/enables DFS channels.
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004106 * Fails the disable request if any device is active on a DFS channel.
4107 *
4108 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004109 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004110
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004111int wlan_hdd_enable_dfs_chan_scan(struct hdd_context *hdd_ctx,
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004112 bool enable_dfs_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004113{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304114 QDF_STATUS status;
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004115 bool err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004116
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004117 if (enable_dfs_channels == hdd_ctx->config->enableDFSChnlScan) {
4118 hdd_info("DFS channels are already %s",
4119 enable_dfs_channels ? "enabled" : "disabled");
4120 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004121 }
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004122
4123 if (!enable_dfs_channels) {
4124 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
4125 QDF_STA_MODE);
4126 if (err)
4127 return -EOPNOTSUPP;
4128
4129 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
4130 QDF_SAP_MODE);
4131 if (err)
4132 return -EOPNOTSUPP;
4133 }
4134
4135 hdd_ctx->config->enableDFSChnlScan = enable_dfs_channels;
4136
Min Liu5eaf7242018-03-13 17:32:15 +08004137 status = sme_enable_dfs_chan_scan(hdd_ctx->hHal, enable_dfs_channels);
4138 if (QDF_IS_STATUS_ERROR(status)) {
4139 hdd_err("Failed to set DFS channel scan flag to %d",
4140 enable_dfs_channels);
4141 return qdf_status_to_os_return(status);
4142 }
4143
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004144 hdd_abort_mac_scan_all_adapters(hdd_ctx);
4145
4146 /* pass dfs channel status to regulatory component */
4147 status = ucfg_reg_enable_dfs_channels(hdd_ctx->hdd_pdev,
4148 enable_dfs_channels);
4149
4150 if (QDF_IS_STATUS_ERROR(status))
4151 hdd_err("Failed to %s DFS channels",
4152 enable_dfs_channels ? "enable" : "disable");
4153
4154 return qdf_status_to_os_return(status);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004155}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004156
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004157/**
4158 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
4159 * @wiphy: corestack handler
4160 * @wdev: wireless device
4161 * @data: data
4162 * @data_len: data length
4163 * Return: success(0) or reason code for failure
4164 */
4165static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
4166 struct wireless_dev *wdev,
4167 const void *data,
4168 int data_len)
4169{
4170 struct net_device *dev = wdev->netdev;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004171 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004172 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
4173 int ret_val;
4174 uint32_t no_dfs_flag = 0;
4175
Dustin Brownfdf17c12018-03-14 12:55:34 -07004176 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08004177
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004178 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304179 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004180 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004181
Dustin Brown4ea21db2018-01-05 14:13:17 -08004182 if (wlan_cfg80211_nla_parse(tb,
4183 QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
4184 data, data_len,
4185 wlan_hdd_set_no_dfs_flag_config_policy)) {
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004186 hdd_err("invalid attr");
4187 return -EINVAL;
4188 }
4189
4190 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
4191 hdd_err("attr dfs flag failed");
4192 return -EINVAL;
4193 }
4194
4195 no_dfs_flag = nla_get_u32(
4196 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
4197
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004198 hdd_debug("DFS flag: %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004199
4200 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07004201 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004202 return -EINVAL;
4203 }
4204
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004205 ret_val = wlan_hdd_enable_dfs_chan_scan(hdd_ctx, !no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004206 return ret_val;
4207}
4208
4209/**
4210 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
4211 *
4212 * @wiphy: wiphy device pointer
4213 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07004214 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004215 * @data_len: Buffer length
4216 *
4217 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
4218 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
4219 *
4220 * Return: EOK or other error codes.
4221 */
4222
4223static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
4224 struct wireless_dev *wdev,
4225 const void *data,
4226 int data_len)
4227{
4228 int ret;
4229
4230 cds_ssr_protect(__func__);
4231 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
4232 data, data_len);
4233 cds_ssr_unprotect(__func__);
4234
4235 return ret;
4236}
4237
Manikandan Mohan80dea792016-04-28 16:36:48 -07004238static const struct nla_policy
4239wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
4240 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
4241};
4242
4243/**
4244 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
4245 * @wiphy: wiphy device pointer
4246 * @wdev: wireless device pointer
4247 * @data: Vendor command data buffer
4248 * @data_len: Buffer length
4249 *
4250 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
4251 * setup WISA Mode features.
4252 *
4253 * Return: Success(0) or reason code for failure
4254 */
4255static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
4256 struct wireless_dev *wdev, const void *data, int data_len)
4257{
4258 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07004259 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004260 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Manikandan Mohan80dea792016-04-28 16:36:48 -07004261 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
4262 struct sir_wisa_params wisa;
4263 int ret_val;
4264 QDF_STATUS status;
4265 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07004266 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
4267 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07004268
Dustin Brownfdf17c12018-03-14 12:55:34 -07004269 hdd_enter_dev(dev);
Manikandan Mohan80dea792016-04-28 16:36:48 -07004270 ret_val = wlan_hdd_validate_context(hdd_ctx);
4271 if (ret_val)
4272 goto err;
4273
4274 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
4275 hdd_err("Command not allowed in FTM mode");
4276 return -EPERM;
4277 }
4278
Dustin Brown4ea21db2018-01-05 14:13:17 -08004279 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data,
4280 data_len, wlan_hdd_wisa_cmd_policy)) {
Manikandan Mohan80dea792016-04-28 16:36:48 -07004281 hdd_err("Invalid WISA cmd attributes");
4282 ret_val = -EINVAL;
4283 goto err;
4284 }
4285 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
4286 hdd_err("Invalid WISA mode");
4287 ret_val = -EINVAL;
4288 goto err;
4289 }
4290
4291 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004292 hdd_debug("WISA Mode: %d", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07004293 wisa.mode = wisa_mode;
Jeff Johnson1b780e42017-10-31 14:11:45 -07004294 wisa.vdev_id = adapter->session_id;
Manikandan Mohan80dea792016-04-28 16:36:48 -07004295 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07004296 if (!QDF_IS_STATUS_SUCCESS(status)) {
4297 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07004298 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07004299 }
4300 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07004301 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08004302 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
4303 (struct cdp_pdev *)pdev,
Jeff Johnson1b780e42017-10-31 14:11:45 -07004304 adapter->session_id),
Leo Changfdb45c32016-10-28 11:09:23 -07004305 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07004306err:
Dustin Browne74003f2018-03-14 12:51:58 -07004307 hdd_exit();
Manikandan Mohan80dea792016-04-28 16:36:48 -07004308 return ret_val;
4309}
4310
4311/**
4312 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
4313 * @wiphy: corestack handler
4314 * @wdev: wireless device
4315 * @data: data
4316 * @data_len: data length
4317 *
4318 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
4319 * setup WISA mode features.
4320 *
4321 * Return: Success(0) or reason code for failure
4322 */
4323static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
4324 struct wireless_dev *wdev,
4325 const void *data,
4326 int data_len)
4327{
4328 int ret;
4329
4330 cds_ssr_protect(__func__);
4331 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
4332 cds_ssr_unprotect(__func__);
4333
4334 return ret;
4335}
4336
Anurag Chouhan96919482016-07-13 16:36:57 +05304337/*
4338 * define short names for the global vendor params
4339 * used by __wlan_hdd_cfg80211_get_station_cmd()
4340 */
4341#define STATION_INVALID \
4342 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
4343#define STATION_INFO \
4344 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
4345#define STATION_ASSOC_FAIL_REASON \
4346 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
Will Huang496b36c2017-07-11 16:38:50 +08004347#define STATION_REMOTE \
4348 QCA_WLAN_VENDOR_ATTR_GET_STATION_REMOTE
Anurag Chouhan96919482016-07-13 16:36:57 +05304349#define STATION_MAX \
4350 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
4351
Will Huang496b36c2017-07-11 16:38:50 +08004352/* define short names for get station info attributes */
4353#define LINK_INFO_STANDARD_NL80211_ATTR \
4354 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_LINK_STANDARD_NL80211_ATTR
4355#define AP_INFO_STANDARD_NL80211_ATTR \
4356 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AP_STANDARD_NL80211_ATTR
4357#define INFO_ROAM_COUNT \
4358 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ROAM_COUNT
4359#define INFO_AKM \
4360 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AKM
4361#define WLAN802_11_MODE \
4362 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_802_11_MODE
4363#define AP_INFO_HS20_INDICATION \
4364 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AP_HS20_INDICATION
4365#define HT_OPERATION \
4366 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_HT_OPERATION
4367#define VHT_OPERATION \
4368 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_VHT_OPERATION
4369#define INFO_ASSOC_FAIL_REASON \
4370 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ASSOC_FAIL_REASON
4371#define REMOTE_MAX_PHY_RATE \
4372 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_MAX_PHY_RATE
4373#define REMOTE_TX_PACKETS \
4374 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_PACKETS
4375#define REMOTE_TX_BYTES \
4376 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_BYTES
4377#define REMOTE_RX_PACKETS \
4378 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_PACKETS
4379#define REMOTE_RX_BYTES \
4380 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_BYTES
4381#define REMOTE_LAST_TX_RATE \
4382 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_LAST_TX_RATE
4383#define REMOTE_LAST_RX_RATE \
4384 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_LAST_RX_RATE
4385#define REMOTE_WMM \
4386 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_WMM
4387#define REMOTE_SUPPORTED_MODE \
4388 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_SUPPORTED_MODE
4389#define REMOTE_AMPDU \
4390 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_AMPDU
4391#define REMOTE_TX_STBC \
4392 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_STBC
4393#define REMOTE_RX_STBC \
4394 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_STBC
4395#define REMOTE_CH_WIDTH\
4396 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_CH_WIDTH
4397#define REMOTE_SGI_ENABLE\
4398 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_SGI_ENABLE
4399#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
4400 #define REMOTE_PAD\
4401 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_PAD
4402#endif
4403
Anurag Chouhan96919482016-07-13 16:36:57 +05304404static const struct nla_policy
4405hdd_get_station_policy[STATION_MAX + 1] = {
4406 [STATION_INFO] = {.type = NLA_FLAG},
4407 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
Will Huang496b36c2017-07-11 16:38:50 +08004408 [STATION_REMOTE] = {.type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE},
Anurag Chouhan96919482016-07-13 16:36:57 +05304409};
4410
Yu Wang157d1472018-03-09 16:05:01 +08004411#ifdef QCA_SUPPORT_CP_STATS
4412static int hdd_get_sta_congestion(struct hdd_adapter *adapter,
4413 uint32_t *congestion)
4414{
4415 QDF_STATUS status;
4416 struct cca_stats cca_stats;
4417
4418 status = ucfg_mc_cp_stats_cca_stats_get(adapter->hdd_vdev, &cca_stats);
4419 if (QDF_IS_STATUS_ERROR(status))
4420 return -EINVAL;
4421
4422 *congestion = cca_stats.congestion;
4423 return 0;
4424}
4425#else
4426static int hdd_get_sta_congestion(struct hdd_adapter *adapter,
4427 uint32_t *congestion)
4428{
4429 struct hdd_station_ctx *hdd_sta_ctx;
4430
4431 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
4432 *congestion = hdd_sta_ctx->conn_info.cca;
4433 return 0;
4434}
4435#endif
4436
Anurag Chouhan96919482016-07-13 16:36:57 +05304437/**
4438 * hdd_get_station_assoc_fail() - Handle get station assoc fail
4439 * @hdd_ctx: HDD context within host driver
4440 * @wdev: wireless device
4441 *
4442 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
4443 * Validate cmd attributes and send the station info to upper layers.
4444 *
4445 * Return: Success(0) or reason code for failure
4446 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004447static int hdd_get_station_assoc_fail(struct hdd_context *hdd_ctx,
Jeff Johnsone5006672017-08-29 14:39:02 -07004448 struct hdd_adapter *adapter)
Anurag Chouhan96919482016-07-13 16:36:57 +05304449{
4450 struct sk_buff *skb = NULL;
4451 uint32_t nl_buf_len;
Jeff Johnson40dae4e2017-08-29 14:00:25 -07004452 struct hdd_station_ctx *hdd_sta_ctx;
Yu Wang157d1472018-03-09 16:05:01 +08004453 uint32_t congestion;
Anurag Chouhan96919482016-07-13 16:36:57 +05304454
4455 nl_buf_len = NLMSG_HDRLEN;
4456 nl_buf_len += sizeof(uint32_t);
4457 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
4458
4459 if (!skb) {
4460 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
4461 return -ENOMEM;
4462 }
4463
4464 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
4465
4466 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
4467 hdd_sta_ctx->conn_info.assoc_status_code)) {
4468 hdd_err("put fail");
4469 goto fail;
4470 }
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05304471
Yu Wang157d1472018-03-09 16:05:01 +08004472 if (hdd_get_sta_congestion(adapter, &congestion))
4473 congestion = 0;
4474
4475 hdd_info("congestion:%d", congestion);
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05304476 if (nla_put_u32(skb, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
Yu Wang157d1472018-03-09 16:05:01 +08004477 congestion)) {
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05304478 hdd_err("put fail");
4479 goto fail;
4480 }
4481
Anurag Chouhan96919482016-07-13 16:36:57 +05304482 return cfg80211_vendor_cmd_reply(skb);
4483fail:
4484 if (skb)
4485 kfree_skb(skb);
4486 return -EINVAL;
4487}
4488
4489/**
4490 * hdd_map_auth_type() - transform auth type specific to
4491 * vendor command
4492 * @auth_type: csr auth type
4493 *
4494 * Return: Success(0) or reason code for failure
4495 */
4496static int hdd_convert_auth_type(uint32_t auth_type)
4497{
4498 uint32_t ret_val;
4499
4500 switch (auth_type) {
4501 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
4502 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
4503 break;
4504 case eCSR_AUTH_TYPE_SHARED_KEY:
4505 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
4506 break;
4507 case eCSR_AUTH_TYPE_WPA:
4508 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
4509 break;
4510 case eCSR_AUTH_TYPE_WPA_PSK:
4511 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
4512 break;
4513 case eCSR_AUTH_TYPE_AUTOSWITCH:
4514 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
4515 break;
4516 case eCSR_AUTH_TYPE_WPA_NONE:
4517 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
4518 break;
4519 case eCSR_AUTH_TYPE_RSN:
4520 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
4521 break;
4522 case eCSR_AUTH_TYPE_RSN_PSK:
4523 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
4524 break;
4525 case eCSR_AUTH_TYPE_FT_RSN:
4526 ret_val = QCA_WLAN_AUTH_TYPE_FT;
4527 break;
4528 case eCSR_AUTH_TYPE_FT_RSN_PSK:
4529 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
4530 break;
4531 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
4532 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
4533 break;
4534 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
4535 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
4536 break;
4537 case eCSR_AUTH_TYPE_CCKM_WPA:
4538 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
4539 break;
4540 case eCSR_AUTH_TYPE_CCKM_RSN:
4541 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
4542 break;
4543 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
4544 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
4545 break;
4546 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
4547 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
4548 break;
4549 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
4550 case eCSR_AUTH_TYPE_FAILED:
4551 case eCSR_AUTH_TYPE_NONE:
4552 default:
4553 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
4554 break;
4555 }
4556 return ret_val;
4557}
4558
4559/**
4560 * hdd_map_dot_11_mode() - transform dot11mode type specific to
4561 * vendor command
4562 * @dot11mode: dot11mode
4563 *
4564 * Return: Success(0) or reason code for failure
4565 */
4566static int hdd_convert_dot11mode(uint32_t dot11mode)
4567{
4568 uint32_t ret_val;
4569
4570 switch (dot11mode) {
4571 case eCSR_CFG_DOT11_MODE_11A:
4572 ret_val = QCA_WLAN_802_11_MODE_11A;
4573 break;
4574 case eCSR_CFG_DOT11_MODE_11B:
4575 ret_val = QCA_WLAN_802_11_MODE_11B;
4576 break;
4577 case eCSR_CFG_DOT11_MODE_11G:
4578 ret_val = QCA_WLAN_802_11_MODE_11G;
4579 break;
4580 case eCSR_CFG_DOT11_MODE_11N:
4581 ret_val = QCA_WLAN_802_11_MODE_11N;
4582 break;
4583 case eCSR_CFG_DOT11_MODE_11AC:
4584 ret_val = QCA_WLAN_802_11_MODE_11AC;
4585 break;
4586 case eCSR_CFG_DOT11_MODE_AUTO:
4587 case eCSR_CFG_DOT11_MODE_ABG:
4588 default:
4589 ret_val = QCA_WLAN_802_11_MODE_INVALID;
4590 }
4591 return ret_val;
4592}
4593
4594/**
4595 * hdd_add_tx_bitrate() - add tx bitrate attribute
4596 * @skb: pointer to sk buff
4597 * @hdd_sta_ctx: pointer to hdd station context
4598 * @idx: attribute index
4599 *
4600 * Return: Success(0) or reason code for failure
4601 */
4602static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
Jeff Johnson40dae4e2017-08-29 14:00:25 -07004603 struct hdd_station_ctx *hdd_sta_ctx,
Anurag Chouhan96919482016-07-13 16:36:57 +05304604 int idx)
4605{
4606 struct nlattr *nla_attr;
4607 uint32_t bitrate, bitrate_compat;
4608
4609 nla_attr = nla_nest_start(skb, idx);
Srinivas Girigowdaccc69062018-05-29 18:24:17 -07004610 if (!nla_attr) {
4611 hdd_err("nla_nest_start failed");
Anurag Chouhan96919482016-07-13 16:36:57 +05304612 goto fail;
Srinivas Girigowdaccc69062018-05-29 18:24:17 -07004613 }
4614
Anurag Chouhan96919482016-07-13 16:36:57 +05304615 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304616 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->
4617 cache_conn_info.txrate);
Anurag Chouhan96919482016-07-13 16:36:57 +05304618
4619 /* report 16-bit bitrate only if we can */
4620 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
Srinivas Girigowdaccc69062018-05-29 18:24:17 -07004621
Srinivas Girigowda27cdaa12018-05-30 19:21:01 -07004622 if (bitrate > 0) {
4623 if (nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
4624 hdd_err("put fail bitrate: %u", bitrate);
4625 goto fail;
4626 }
Srinivas Girigowdaccc69062018-05-29 18:24:17 -07004627 } else {
4628 hdd_err("Invalid bitrate: %u", bitrate);
Anurag Chouhan96919482016-07-13 16:36:57 +05304629 }
Srinivas Girigowdaccc69062018-05-29 18:24:17 -07004630
Srinivas Girigowda27cdaa12018-05-30 19:21:01 -07004631 if (bitrate_compat > 0) {
4632 if (nla_put_u16(skb, NL80211_RATE_INFO_BITRATE,
4633 bitrate_compat)) {
4634 hdd_err("put fail bitrate_compat: %u", bitrate_compat);
4635 goto fail;
4636 }
Srinivas Girigowdaccc69062018-05-29 18:24:17 -07004637 } else {
4638 hdd_err("Invalid bitrate_compat: %u", bitrate_compat);
Anurag Chouhan96919482016-07-13 16:36:57 +05304639 }
Srinivas Girigowdaccc69062018-05-29 18:24:17 -07004640
Anurag Chouhan96919482016-07-13 16:36:57 +05304641 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304642 hdd_sta_ctx->cache_conn_info.txrate.nss)) {
Anurag Chouhan96919482016-07-13 16:36:57 +05304643 hdd_err("put fail");
4644 goto fail;
4645 }
4646 nla_nest_end(skb, nla_attr);
4647 return 0;
4648fail:
4649 return -EINVAL;
4650}
4651
4652/**
4653 * hdd_add_sta_info() - add station info attribute
4654 * @skb: pointer to sk buff
4655 * @hdd_sta_ctx: pointer to hdd station context
4656 * @idx: attribute index
4657 *
4658 * Return: Success(0) or reason code for failure
4659 */
4660static int32_t hdd_add_sta_info(struct sk_buff *skb,
Jeff Johnson40dae4e2017-08-29 14:00:25 -07004661 struct hdd_station_ctx *hdd_sta_ctx, int idx)
Anurag Chouhan96919482016-07-13 16:36:57 +05304662{
4663 struct nlattr *nla_attr;
4664
4665 nla_attr = nla_nest_start(skb, idx);
Srinivas Girigowdaccc69062018-05-29 18:24:17 -07004666 if (!nla_attr) {
4667 hdd_err("nla_nest_start failed");
Anurag Chouhan96919482016-07-13 16:36:57 +05304668 goto fail;
Srinivas Girigowdaccc69062018-05-29 18:24:17 -07004669 }
4670
Anurag Chouhan96919482016-07-13 16:36:57 +05304671 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304672 (hdd_sta_ctx->cache_conn_info.signal + 100))) {
Anurag Chouhan96919482016-07-13 16:36:57 +05304673 hdd_err("put fail");
4674 goto fail;
4675 }
Srinivas Girigowdaccc69062018-05-29 18:24:17 -07004676 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE)) {
4677 hdd_err("hdd_add_tx_bitrate failed");
Anurag Chouhan96919482016-07-13 16:36:57 +05304678 goto fail;
Srinivas Girigowdaccc69062018-05-29 18:24:17 -07004679 }
4680
Anurag Chouhan96919482016-07-13 16:36:57 +05304681 nla_nest_end(skb, nla_attr);
4682 return 0;
4683fail:
4684 return -EINVAL;
4685}
4686
4687/**
4688 * hdd_add_survey_info() - add survey info attribute
4689 * @skb: pointer to sk buff
4690 * @hdd_sta_ctx: pointer to hdd station context
4691 * @idx: attribute index
4692 *
4693 * Return: Success(0) or reason code for failure
4694 */
4695static int32_t hdd_add_survey_info(struct sk_buff *skb,
Jeff Johnson40dae4e2017-08-29 14:00:25 -07004696 struct hdd_station_ctx *hdd_sta_ctx,
Anurag Chouhan96919482016-07-13 16:36:57 +05304697 int idx)
4698{
4699 struct nlattr *nla_attr;
4700
4701 nla_attr = nla_nest_start(skb, idx);
4702 if (!nla_attr)
4703 goto fail;
4704 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304705 hdd_sta_ctx->cache_conn_info.freq) ||
Anurag Chouhan96919482016-07-13 16:36:57 +05304706 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304707 (hdd_sta_ctx->cache_conn_info.noise + 100))) {
Anurag Chouhan96919482016-07-13 16:36:57 +05304708 hdd_err("put fail");
4709 goto fail;
4710 }
4711 nla_nest_end(skb, nla_attr);
4712 return 0;
4713fail:
4714 return -EINVAL;
4715}
4716
4717/**
4718 * hdd_add_link_standard_info() - add link info attribute
4719 * @skb: pointer to sk buff
4720 * @hdd_sta_ctx: pointer to hdd station context
4721 * @idx: attribute index
4722 *
4723 * Return: Success(0) or reason code for failure
4724 */
4725static int32_t
4726hdd_add_link_standard_info(struct sk_buff *skb,
Jeff Johnson40dae4e2017-08-29 14:00:25 -07004727 struct hdd_station_ctx *hdd_sta_ctx, int idx)
Anurag Chouhan96919482016-07-13 16:36:57 +05304728{
4729 struct nlattr *nla_attr;
4730
4731 nla_attr = nla_nest_start(skb, idx);
Srinivas Girigowdaccc69062018-05-29 18:24:17 -07004732 if (!nla_attr) {
4733 hdd_err("nla_nest_start failed");
Anurag Chouhan96919482016-07-13 16:36:57 +05304734 goto fail;
Srinivas Girigowdaccc69062018-05-29 18:24:17 -07004735 }
4736
Anurag Chouhan96919482016-07-13 16:36:57 +05304737 if (nla_put(skb,
4738 NL80211_ATTR_SSID,
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304739 hdd_sta_ctx->cache_conn_info.last_ssid.SSID.length,
4740 hdd_sta_ctx->cache_conn_info.last_ssid.SSID.ssId)) {
Anurag Chouhan96919482016-07-13 16:36:57 +05304741 hdd_err("put fail");
4742 goto fail;
4743 }
Ashish Kumar Dhanotiya6e270602018-01-18 15:14:58 +05304744 if (nla_put(skb, NL80211_ATTR_MAC, QDF_MAC_ADDR_SIZE,
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304745 hdd_sta_ctx->cache_conn_info.bssId.bytes)) {
Srinivas Girigowdaccc69062018-05-29 18:24:17 -07004746 hdd_err("put bssid failed");
Ashish Kumar Dhanotiya6e270602018-01-18 15:14:58 +05304747 goto fail;
4748 }
Srinivas Girigowdaccc69062018-05-29 18:24:17 -07004749 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO)) {
4750 hdd_err("hdd_add_survey_info failed");
Anurag Chouhan96919482016-07-13 16:36:57 +05304751 goto fail;
Srinivas Girigowdaccc69062018-05-29 18:24:17 -07004752 }
4753
4754 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO)) {
4755 hdd_err("hdd_add_sta_info failed");
Anurag Chouhan96919482016-07-13 16:36:57 +05304756 goto fail;
Srinivas Girigowdaccc69062018-05-29 18:24:17 -07004757 }
Anurag Chouhan96919482016-07-13 16:36:57 +05304758 nla_nest_end(skb, nla_attr);
4759 return 0;
4760fail:
4761 return -EINVAL;
4762}
4763
4764/**
4765 * hdd_add_ap_standard_info() - add ap info attribute
4766 * @skb: pointer to sk buff
4767 * @hdd_sta_ctx: pointer to hdd station context
4768 * @idx: attribute index
4769 *
4770 * Return: Success(0) or reason code for failure
4771 */
4772static int32_t
4773hdd_add_ap_standard_info(struct sk_buff *skb,
Jeff Johnson40dae4e2017-08-29 14:00:25 -07004774 struct hdd_station_ctx *hdd_sta_ctx, int idx)
Anurag Chouhan96919482016-07-13 16:36:57 +05304775{
4776 struct nlattr *nla_attr;
4777
4778 nla_attr = nla_nest_start(skb, idx);
4779 if (!nla_attr)
4780 goto fail;
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304781 if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_present)
Anurag Chouhan96919482016-07-13 16:36:57 +05304782 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304783 sizeof(hdd_sta_ctx->cache_conn_info.vht_caps),
4784 &hdd_sta_ctx->cache_conn_info.vht_caps)) {
Anurag Chouhan96919482016-07-13 16:36:57 +05304785 hdd_err("put fail");
4786 goto fail;
4787 }
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304788 if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_present)
Anurag Chouhan96919482016-07-13 16:36:57 +05304789 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304790 sizeof(hdd_sta_ctx->cache_conn_info.ht_caps),
4791 &hdd_sta_ctx->cache_conn_info.ht_caps)) {
Anurag Chouhan96919482016-07-13 16:36:57 +05304792 hdd_err("put fail");
4793 goto fail;
4794 }
4795 nla_nest_end(skb, nla_attr);
4796 return 0;
4797fail:
4798 return -EINVAL;
4799}
4800
4801/**
4802 * hdd_get_station_info() - send BSS information to supplicant
4803 * @hdd_ctx: pointer to hdd context
4804 * @adapter: pointer to adapter
4805 *
4806 * Return: 0 if success else error status
4807 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004808static int hdd_get_station_info(struct hdd_context *hdd_ctx,
Jeff Johnsone5006672017-08-29 14:39:02 -07004809 struct hdd_adapter *adapter)
Anurag Chouhan96919482016-07-13 16:36:57 +05304810{
4811 struct sk_buff *skb = NULL;
4812 uint8_t *tmp_hs20 = NULL;
4813 uint32_t nl_buf_len;
Jeff Johnson40dae4e2017-08-29 14:00:25 -07004814 struct hdd_station_ctx *hdd_sta_ctx;
Anurag Chouhan96919482016-07-13 16:36:57 +05304815
4816 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
4817
4818 nl_buf_len = NLMSG_HDRLEN;
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304819 nl_buf_len += sizeof(hdd_sta_ctx->
4820 cache_conn_info.last_ssid.SSID.length) +
Ashish Kumar Dhanotiya6e270602018-01-18 15:14:58 +05304821 QDF_MAC_ADDR_SIZE +
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304822 sizeof(hdd_sta_ctx->cache_conn_info.freq) +
4823 sizeof(hdd_sta_ctx->cache_conn_info.noise) +
4824 sizeof(hdd_sta_ctx->cache_conn_info.signal) +
Anurag Chouhan96919482016-07-13 16:36:57 +05304825 (sizeof(uint32_t) * 2) +
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304826 sizeof(hdd_sta_ctx->cache_conn_info.txrate.nss) +
4827 sizeof(hdd_sta_ctx->cache_conn_info.roam_count) +
4828 sizeof(hdd_sta_ctx->cache_conn_info.last_auth_type) +
4829 sizeof(hdd_sta_ctx->cache_conn_info.dot11Mode);
4830 if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_present)
4831 nl_buf_len += sizeof(hdd_sta_ctx->cache_conn_info.vht_caps);
4832 if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_present)
4833 nl_buf_len += sizeof(hdd_sta_ctx->cache_conn_info.ht_caps);
4834 if (hdd_sta_ctx->cache_conn_info.conn_flag.hs20_present) {
4835 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->
4836 cache_conn_info.hs20vendor_ie);
4837 nl_buf_len += (sizeof(hdd_sta_ctx->
4838 cache_conn_info.hs20vendor_ie) - 1);
Anurag Chouhan96919482016-07-13 16:36:57 +05304839 }
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304840 if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_op_present)
4841 nl_buf_len += sizeof(hdd_sta_ctx->
4842 cache_conn_info.ht_operation);
4843 if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_op_present)
4844 nl_buf_len += sizeof(hdd_sta_ctx->
4845 cache_conn_info.vht_operation);
Anurag Chouhan96919482016-07-13 16:36:57 +05304846
4847
4848 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
4849 if (!skb) {
Dustin Brownbacc48f2018-03-14 14:48:44 -07004850 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Anurag Chouhan96919482016-07-13 16:36:57 +05304851 return -ENOMEM;
4852 }
4853
4854 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
4855 LINK_INFO_STANDARD_NL80211_ATTR)) {
4856 hdd_err("put fail");
4857 goto fail;
4858 }
4859 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
4860 AP_INFO_STANDARD_NL80211_ATTR)) {
4861 hdd_err("put fail");
4862 goto fail;
4863 }
4864 if (nla_put_u32(skb, INFO_ROAM_COUNT,
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304865 hdd_sta_ctx->cache_conn_info.roam_count) ||
Anurag Chouhan96919482016-07-13 16:36:57 +05304866 nla_put_u32(skb, INFO_AKM,
4867 hdd_convert_auth_type(
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304868 hdd_sta_ctx->cache_conn_info.last_auth_type)) ||
Anurag Chouhan96919482016-07-13 16:36:57 +05304869 nla_put_u32(skb, WLAN802_11_MODE,
4870 hdd_convert_dot11mode(
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304871 hdd_sta_ctx->cache_conn_info.dot11Mode))) {
Anurag Chouhan96919482016-07-13 16:36:57 +05304872 hdd_err("put fail");
4873 goto fail;
4874 }
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304875 if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_op_present)
Anurag Chouhan96919482016-07-13 16:36:57 +05304876 if (nla_put(skb, HT_OPERATION,
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304877 (sizeof(hdd_sta_ctx->cache_conn_info.ht_operation)),
4878 &hdd_sta_ctx->cache_conn_info.ht_operation)) {
Anurag Chouhan96919482016-07-13 16:36:57 +05304879 hdd_err("put fail");
4880 goto fail;
4881 }
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304882 if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_op_present)
Anurag Chouhan96919482016-07-13 16:36:57 +05304883 if (nla_put(skb, VHT_OPERATION,
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304884 (sizeof(hdd_sta_ctx->
4885 cache_conn_info.vht_operation)),
4886 &hdd_sta_ctx->cache_conn_info.vht_operation)) {
Anurag Chouhan96919482016-07-13 16:36:57 +05304887 hdd_err("put fail");
4888 goto fail;
4889 }
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304890 if (hdd_sta_ctx->cache_conn_info.conn_flag.hs20_present)
Anurag Chouhan96919482016-07-13 16:36:57 +05304891 if (nla_put(skb, AP_INFO_HS20_INDICATION,
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304892 (sizeof(hdd_sta_ctx->cache_conn_info.hs20vendor_ie)
4893 - 1),
Anurag Chouhan96919482016-07-13 16:36:57 +05304894 tmp_hs20 + 1)) {
4895 hdd_err("put fail");
4896 goto fail;
4897 }
4898
4899 return cfg80211_vendor_cmd_reply(skb);
4900fail:
4901 if (skb)
4902 kfree_skb(skb);
4903 return -EINVAL;
4904}
4905
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +05304906struct hdd_station_info *hdd_get_stainfo(struct hdd_station_info *astainfo,
4907 struct qdf_mac_addr mac_addr)
Will Huang496b36c2017-07-11 16:38:50 +08004908{
Jeff Johnson82155922017-09-30 16:54:14 -07004909 struct hdd_station_info *stainfo = NULL;
Will Huang496b36c2017-07-11 16:38:50 +08004910 int i;
4911
4912 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +05304913 if (!qdf_mem_cmp(&astainfo[i].sta_mac,
Will Huang496b36c2017-07-11 16:38:50 +08004914 &mac_addr,
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +05304915 QDF_MAC_ADDR_SIZE)) {
4916 stainfo = &astainfo[i];
4917 break;
4918 }
Will Huang496b36c2017-07-11 16:38:50 +08004919 }
4920
4921 return stainfo;
4922}
4923
4924#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
4925static inline int32_t remote_station_put_u64(struct sk_buff *skb,
4926 int32_t attrtype,
4927 uint64_t value)
4928{
4929 return nla_put_u64_64bit(skb, attrtype, value, REMOTE_PAD);
4930}
4931#else
4932static inline int32_t remote_station_put_u64(struct sk_buff *skb,
4933 int32_t attrtype,
4934 uint64_t value)
4935{
4936 return nla_put_u64(skb, attrtype, value);
4937}
4938#endif
4939
4940/**
Hanumanth Reddy Pothulaf79fbdf2017-10-23 20:10:46 +05304941 * hdd_add_survey_info_sap_get_len - get data length used in
4942 * hdd_add_survey_info_sap()
4943 *
4944 * This function calculates the data length used in hdd_add_survey_info_sap()
4945 *
4946 * Return: total data length used in hdd_add_survey_info_sap()
4947 */
4948static uint32_t hdd_add_survey_info_sap_get_len(void)
4949{
4950 return ((NLA_HDRLEN) + (sizeof(uint32_t) + NLA_HDRLEN));
4951}
4952
4953/**
4954 * hdd_add_survey_info - add survey info attribute
4955 * @skb: pointer to response skb buffer
4956 * @stainfo: station information
4957 * @idx: attribute type index for nla_next_start()
4958 *
4959 * This function adds survey info attribute to response skb buffer
4960 *
4961 * Return : 0 on success and errno on failure
4962 */
4963static int32_t hdd_add_survey_info_sap(struct sk_buff *skb,
4964 struct hdd_station_info *stainfo,
4965 int idx)
4966{
4967 struct nlattr *nla_attr;
4968
4969 nla_attr = nla_nest_start(skb, idx);
4970 if (!nla_attr)
4971 goto fail;
4972 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
4973 stainfo->freq)) {
4974 hdd_err("put fail");
4975 goto fail;
4976 }
4977 nla_nest_end(skb, nla_attr);
4978 return 0;
4979fail:
4980 return -EINVAL;
4981}
4982
4983/**
4984 * hdd_add_tx_bitrate_sap_get_len - get data length used in
4985 * hdd_add_tx_bitrate_sap()
4986 *
4987 * This function calculates the data length used in hdd_add_tx_bitrate_sap()
4988 *
4989 * Return: total data length used in hdd_add_tx_bitrate_sap()
4990 */
4991static uint32_t hdd_add_tx_bitrate_sap_get_len(void)
4992{
4993 return ((NLA_HDRLEN) + (sizeof(uint8_t) + NLA_HDRLEN));
4994}
4995
4996/**
4997 * hdd_add_tx_bitrate_sap - add vhs nss info attribute
4998 * @skb: pointer to response skb buffer
4999 * @stainfo: station information
5000 * @idx: attribute type index for nla_next_start()
5001 *
5002 * This function adds vht nss attribute to response skb buffer
5003 *
5004 * Return : 0 on success and errno on failure
5005 */
5006static int hdd_add_tx_bitrate_sap(struct sk_buff *skb,
5007 struct hdd_station_info *stainfo,
5008 int idx)
5009{
5010 struct nlattr *nla_attr;
5011
5012 nla_attr = nla_nest_start(skb, idx);
5013 if (!nla_attr)
5014 goto fail;
5015
5016 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
5017 stainfo->nss)) {
5018 hdd_err("put fail");
5019 goto fail;
5020 }
5021 nla_nest_end(skb, nla_attr);
5022 return 0;
5023fail:
5024 return -EINVAL;
5025}
5026
5027/**
5028 * hdd_add_sta_info_sap_get_len - get data length used in
5029 * hdd_add_sta_info_sap()
5030 *
5031 * This function calculates the data length used in hdd_add_sta_info_sap()
5032 *
5033 * Return: total data length used in hdd_add_sta_info_sap()
5034 */
5035static uint32_t hdd_add_sta_info_sap_get_len(void)
5036{
5037 return ((NLA_HDRLEN) + (sizeof(uint8_t) + NLA_HDRLEN) +
5038 hdd_add_tx_bitrate_sap_get_len());
5039}
5040
5041/**
5042 * hdd_add_sta_info_sap - add sta signal info attribute
5043 * @skb: pointer to response skb buffer
5044 * @stainfo: station information
5045 * @idx: attribute type index for nla_next_start()
5046 *
5047 * This function adds sta signal attribute to response skb buffer
5048 *
5049 * Return : 0 on success and errno on failure
5050 */
5051static int32_t hdd_add_sta_info_sap(struct sk_buff *skb, int8_t rssi,
5052 struct hdd_station_info *stainfo, int idx)
5053{
5054 struct nlattr *nla_attr;
5055
5056 nla_attr = nla_nest_start(skb, idx);
5057 if (!nla_attr)
5058 goto fail;
5059
5060 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL, rssi)) {
5061 hdd_err("put fail");
5062 goto fail;
5063 }
5064 if (hdd_add_tx_bitrate_sap(skb, stainfo, NL80211_STA_INFO_TX_BITRATE))
5065 goto fail;
5066
5067 nla_nest_end(skb, nla_attr);
5068 return 0;
5069fail:
5070 return -EINVAL;
5071}
5072
5073/**
5074 * hdd_add_link_standard_info_sap_get_len - get data length used in
5075 * hdd_add_link_standard_info_sap()
5076 *
5077 * This function calculates the data length used in
5078 * hdd_add_link_standard_info_sap()
5079 *
5080 * Return: total data length used in hdd_add_link_standard_info_sap()
5081 */
5082static uint32_t hdd_add_link_standard_info_sap_get_len(void)
5083{
5084 return ((NLA_HDRLEN) +
5085 hdd_add_survey_info_sap_get_len() +
5086 hdd_add_sta_info_sap_get_len() +
5087 (sizeof(uint32_t) + NLA_HDRLEN));
5088}
5089
5090/**
5091 * hdd_add_link_standard_info_sap - add add link info attribut
5092 * @skb: pointer to response skb buffer
5093 * @stainfo: station information
5094 * @idx: attribute type index for nla_next_start()
5095 *
5096 * This function adds link info attribut to response skb buffer
5097 *
5098 * Return : 0 on success and errno on failure
5099 */
5100static int hdd_add_link_standard_info_sap(struct sk_buff *skb, int8_t rssi,
5101 struct hdd_station_info *stainfo,
5102 int idx)
5103{
5104 struct nlattr *nla_attr;
5105
5106 nla_attr = nla_nest_start(skb, idx);
5107 if (!nla_attr)
5108 goto fail;
5109 if (hdd_add_survey_info_sap(skb, stainfo, NL80211_ATTR_SURVEY_INFO))
5110 goto fail;
5111 if (hdd_add_sta_info_sap(skb, rssi, stainfo, NL80211_ATTR_STA_INFO))
5112 goto fail;
5113
5114 if (nla_put_u32(skb, NL80211_ATTR_REASON_CODE, stainfo->reason_code)) {
5115 hdd_err("Reason code put fail");
5116 goto fail;
5117 }
5118
5119 nla_nest_end(skb, nla_attr);
5120 return 0;
5121fail:
5122 return -EINVAL;
5123}
5124
5125/**
5126 * hdd_add_ap_standard_info_sap_get_len - get data length used in
5127 * hdd_add_ap_standard_info_sap()
5128 * @stainfo: station information
5129 *
5130 * This function calculates the data length used in
5131 * hdd_add_ap_standard_info_sap()
5132 *
5133 * Return: total data length used in hdd_add_ap_standard_info_sap()
5134 */
5135static uint32_t hdd_add_ap_standard_info_sap_get_len(
5136 struct hdd_station_info *stainfo)
5137{
5138 uint32_t len;
5139
5140 len = NLA_HDRLEN;
5141 if (stainfo->vht_present)
5142 len += (sizeof(stainfo->vht_caps) + NLA_HDRLEN);
5143 if (stainfo->ht_present)
5144 len += (sizeof(stainfo->ht_caps) + NLA_HDRLEN);
5145
5146 return len;
5147}
5148
5149/**
5150 * hdd_add_ap_standard_info_sap - add HT and VHT info attributes
5151 * @skb: pointer to response skb buffer
5152 * @stainfo: station information
5153 * @idx: attribute type index for nla_next_start()
5154 *
5155 * This function adds HT and VHT info attributes to response skb buffer
5156 *
5157 * Return : 0 on success and errno on failure
5158 */
5159static int hdd_add_ap_standard_info_sap(struct sk_buff *skb,
5160 struct hdd_station_info *stainfo,
5161 int idx)
5162{
5163 struct nlattr *nla_attr;
5164
5165 nla_attr = nla_nest_start(skb, idx);
5166 if (!nla_attr)
5167 goto fail;
5168
5169 if (stainfo->vht_present) {
5170 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
5171 sizeof(stainfo->vht_caps),
5172 &stainfo->vht_caps)) {
5173 hdd_err("put fail");
5174 goto fail;
5175 }
5176 }
5177 if (stainfo->ht_present) {
5178 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
5179 sizeof(stainfo->ht_caps),
5180 &stainfo->ht_caps)) {
5181 hdd_err("put fail");
5182 goto fail;
5183 }
5184 }
5185 nla_nest_end(skb, nla_attr);
5186 return 0;
5187fail:
5188 return -EINVAL;
5189}
5190
5191/**
5192 * hdd_decode_ch_width - decode channel band width based
5193 * @ch_width: encoded enum value holding channel band width
5194 *
5195 * This function decodes channel band width from the given encoded enum value.
5196 *
5197 * Returns: decoded channel band width.
5198 */
5199static uint8_t hdd_decode_ch_width(tSirMacHTChannelWidth ch_width)
5200{
5201 switch (ch_width) {
5202 case 0:
5203 return 20;
5204 case 1:
5205 return 40;
5206 case 2:
5207 return 80;
5208 case 3:
5209 case 4:
5210 return 160;
5211 default:
5212 hdd_debug("invalid enum: %d", ch_width);
5213 return 20;
5214 }
5215}
5216
5217/**
5218 * hdd_get_cached_station_remote() - get cached(deleted) peer's info
Will Huang496b36c2017-07-11 16:38:50 +08005219 * @hdd_ctx: hdd context
5220 * @adapter: hostapd interface
5221 * @mac_addr: mac address of requested peer
5222 *
Hanumanth Reddy Pothulaf79fbdf2017-10-23 20:10:46 +05305223 * This function collect and indicate the cached(deleted) peer's info
Will Huang496b36c2017-07-11 16:38:50 +08005224 *
5225 * Return: 0 on success, otherwise error value
5226 */
Hanumanth Reddy Pothulaf79fbdf2017-10-23 20:10:46 +05305227
5228static int hdd_get_cached_station_remote(struct hdd_context *hdd_ctx,
5229 struct hdd_adapter *adapter,
5230 struct qdf_mac_addr mac_addr)
Will Huang496b36c2017-07-11 16:38:50 +08005231{
Hanumanth Reddy Pothulaf79fbdf2017-10-23 20:10:46 +05305232 struct hdd_station_info *stainfo = hdd_get_stainfo(
5233 adapter->cache_sta_info,
5234 mac_addr);
Will Huang496b36c2017-07-11 16:38:50 +08005235 struct sk_buff *skb = NULL;
Hanumanth Reddy Pothulaf79fbdf2017-10-23 20:10:46 +05305236 uint32_t nl_buf_len = NLMSG_HDRLEN;
5237 uint8_t channel_width;
Will Huang496b36c2017-07-11 16:38:50 +08005238
5239 if (!stainfo) {
5240 hdd_err("peer " MAC_ADDRESS_STR " not found",
5241 MAC_ADDR_ARRAY(mac_addr.bytes));
Hanumanth Reddy Pothulaf79fbdf2017-10-23 20:10:46 +05305242 return -EINVAL;
5243 }
5244
5245 nl_buf_len += hdd_add_link_standard_info_sap_get_len() +
5246 hdd_add_ap_standard_info_sap_get_len(stainfo) +
Ashish Kumar Dhanotiyad523f0d2017-10-26 14:15:48 +05305247 (sizeof(stainfo->dot11_mode) + NLA_HDRLEN) +
Hanumanth Reddy Pothulaf79fbdf2017-10-23 20:10:46 +05305248 (sizeof(stainfo->ch_width) + NLA_HDRLEN) +
5249 (sizeof(stainfo->tx_rate) + NLA_HDRLEN) +
5250 (sizeof(stainfo->rx_rate) + NLA_HDRLEN);
5251
5252 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
5253 if (!skb) {
Dustin Brownbacc48f2018-03-14 14:48:44 -07005254 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Hanumanth Reddy Pothulaf79fbdf2017-10-23 20:10:46 +05305255 return -ENOMEM;
5256 }
5257
5258 if (hdd_add_link_standard_info_sap(skb, stainfo->rssi, stainfo,
5259 LINK_INFO_STANDARD_NL80211_ATTR)) {
5260 hdd_err("link standard put fail");
Will Huang496b36c2017-07-11 16:38:50 +08005261 goto fail;
5262 }
5263
Hanumanth Reddy Pothulaf79fbdf2017-10-23 20:10:46 +05305264 if (hdd_add_ap_standard_info_sap(skb, stainfo,
5265 AP_INFO_STANDARD_NL80211_ATTR)) {
5266 hdd_err("ap standard put fail");
5267 goto fail;
5268 }
5269
5270 /* upper layer expects decoded channel BW */
5271 channel_width = hdd_decode_ch_width(stainfo->ch_width);
5272
5273 if (nla_put_u32(skb, REMOTE_SUPPORTED_MODE,
5274 hdd_convert_dot11mode(
5275 stainfo->mode)) ||
5276 nla_put_u8(skb, REMOTE_CH_WIDTH, channel_width)) {
5277 hdd_err("remote ch put fail");
5278 goto fail;
5279 }
5280 if (nla_put_u32(skb, REMOTE_LAST_TX_RATE, stainfo->tx_rate)) {
5281 hdd_err("tx rate put fail");
5282 goto fail;
5283 }
5284 if (nla_put_u32(skb, REMOTE_LAST_RX_RATE, stainfo->rx_rate)) {
5285 hdd_err("rx rate put fail");
5286 goto fail;
5287 }
5288
5289 qdf_mem_zero(stainfo, sizeof(*stainfo));
5290
5291 return cfg80211_vendor_cmd_reply(skb);
5292fail:
5293 if (skb)
5294 kfree_skb(skb);
5295
5296 return -EINVAL;
5297}
5298
5299/**
5300 * hdd_get_cached_station_remote() - get connected peer's info
5301 * @hdd_ctx: hdd context
5302 * @adapter: hostapd interface
5303 * @mac_addr: mac address of requested peer
5304 *
5305 * This function collect and indicate the connected peer's info
5306 *
5307 * Return: 0 on success, otherwise error value
5308 */
5309static int hdd_get_connected_station_info(struct hdd_context *hdd_ctx,
5310 struct hdd_adapter *adapter,
5311 struct qdf_mac_addr mac_addr,
5312 struct hdd_station_info *stainfo)
5313{
5314 struct sk_buff *skb = NULL;
5315 uint32_t nl_buf_len;
5316 struct sir_peer_info_ext peer_info;
5317 bool txrx_rate = true;
5318
Will Huang496b36c2017-07-11 16:38:50 +08005319 nl_buf_len = NLMSG_HDRLEN;
5320 nl_buf_len += (sizeof(stainfo->max_phy_rate) + NLA_HDRLEN) +
5321 (sizeof(stainfo->tx_packets) + NLA_HDRLEN) +
5322 (sizeof(stainfo->tx_bytes) + NLA_HDRLEN) +
5323 (sizeof(stainfo->rx_packets) + NLA_HDRLEN) +
5324 (sizeof(stainfo->rx_bytes) + NLA_HDRLEN) +
Jeff Johnson65fda112017-10-21 13:46:10 -07005325 (sizeof(stainfo->is_qos_enabled) + NLA_HDRLEN) +
Will Huang496b36c2017-07-11 16:38:50 +08005326 (sizeof(stainfo->mode) + NLA_HDRLEN);
5327
5328 if (!hdd_ctx->config->sap_get_peer_info ||
5329 wlan_hdd_get_peer_info(adapter, mac_addr, &peer_info)) {
5330 hdd_err("fail to get tx/rx rate");
5331 txrx_rate = false;
5332 } else {
5333 stainfo->tx_rate = peer_info.tx_rate;
5334 stainfo->rx_rate = peer_info.rx_rate;
5335 nl_buf_len += (sizeof(stainfo->tx_rate) + NLA_HDRLEN) +
5336 (sizeof(stainfo->rx_rate) + NLA_HDRLEN);
5337 }
5338
5339 /* below info is only valid for HT/VHT mode */
5340 if (stainfo->mode > SIR_SME_PHY_MODE_LEGACY)
5341 nl_buf_len += (sizeof(stainfo->ampdu) + NLA_HDRLEN) +
5342 (sizeof(stainfo->tx_stbc) + NLA_HDRLEN) +
5343 (sizeof(stainfo->rx_stbc) + NLA_HDRLEN) +
5344 (sizeof(stainfo->ch_width) + NLA_HDRLEN) +
5345 (sizeof(stainfo->sgi_enable) + NLA_HDRLEN);
5346
5347 hdd_info("buflen %d hdrlen %d", nl_buf_len, NLMSG_HDRLEN);
5348
5349 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
5350 nl_buf_len);
5351 if (!skb) {
5352 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
5353 goto fail;
5354 }
5355
5356 hdd_info("stainfo");
5357 hdd_info("maxrate %x tx_pkts %x tx_bytes %llx",
5358 stainfo->max_phy_rate, stainfo->tx_packets,
5359 stainfo->tx_bytes);
5360 hdd_info("rx_pkts %x rx_bytes %llx mode %x",
5361 stainfo->rx_packets, stainfo->rx_bytes,
5362 stainfo->mode);
5363 if (stainfo->mode > SIR_SME_PHY_MODE_LEGACY) {
5364 hdd_info("ampdu %d tx_stbc %d rx_stbc %d",
5365 stainfo->ampdu, stainfo->tx_stbc,
5366 stainfo->rx_stbc);
5367 hdd_info("wmm %d chwidth %d sgi %d",
Jeff Johnson65fda112017-10-21 13:46:10 -07005368 stainfo->is_qos_enabled,
Will Huang496b36c2017-07-11 16:38:50 +08005369 stainfo->ch_width,
5370 stainfo->sgi_enable);
5371 }
5372
5373 if (nla_put_u32(skb, REMOTE_MAX_PHY_RATE, stainfo->max_phy_rate) ||
5374 nla_put_u32(skb, REMOTE_TX_PACKETS, stainfo->tx_packets) ||
5375 remote_station_put_u64(skb, REMOTE_TX_BYTES, stainfo->tx_bytes) ||
5376 nla_put_u32(skb, REMOTE_RX_PACKETS, stainfo->rx_packets) ||
5377 remote_station_put_u64(skb, REMOTE_RX_BYTES, stainfo->rx_bytes) ||
Jeff Johnson65fda112017-10-21 13:46:10 -07005378 nla_put_u8(skb, REMOTE_WMM, stainfo->is_qos_enabled) ||
Will Huang496b36c2017-07-11 16:38:50 +08005379 nla_put_u8(skb, REMOTE_SUPPORTED_MODE, stainfo->mode)) {
5380 hdd_err("put fail");
5381 goto fail;
5382 }
5383
5384 if (txrx_rate) {
5385 if (nla_put_u32(skb, REMOTE_LAST_TX_RATE, stainfo->tx_rate) ||
5386 nla_put_u32(skb, REMOTE_LAST_RX_RATE, stainfo->rx_rate)) {
5387 hdd_err("put fail");
5388 goto fail;
5389 } else {
5390 hdd_info("tx_rate %x rx_rate %x",
5391 stainfo->tx_rate, stainfo->rx_rate);
5392 }
5393 }
5394
5395 if (stainfo->mode > SIR_SME_PHY_MODE_LEGACY) {
5396 if (nla_put_u8(skb, REMOTE_AMPDU, stainfo->ampdu) ||
5397 nla_put_u8(skb, REMOTE_TX_STBC, stainfo->tx_stbc) ||
5398 nla_put_u8(skb, REMOTE_RX_STBC, stainfo->rx_stbc) ||
5399 nla_put_u8(skb, REMOTE_CH_WIDTH, stainfo->ch_width) ||
5400 nla_put_u8(skb, REMOTE_SGI_ENABLE, stainfo->sgi_enable)) {
5401 hdd_err("put fail");
5402 goto fail;
5403 }
5404 }
5405
5406 return cfg80211_vendor_cmd_reply(skb);
5407
5408fail:
5409 if (skb)
5410 kfree_skb(skb);
5411
5412 return -EINVAL;
5413}
5414
5415/**
Hanumanth Reddy Pothulaf79fbdf2017-10-23 20:10:46 +05305416 * hdd_get_station_remote() - get remote peer's info
5417 * @hdd_ctx: hdd context
5418 * @adapter: hostapd interface
5419 * @mac_addr: mac address of requested peer
5420 *
5421 * This function collect and indicate the remote peer's info
5422 *
5423 * Return: 0 on success, otherwise error value
5424 */
5425static int hdd_get_station_remote(struct hdd_context *hdd_ctx,
5426 struct hdd_adapter *adapter,
5427 struct qdf_mac_addr mac_addr)
5428{
5429 struct hdd_station_info *stainfo = hdd_get_stainfo(adapter->sta_info,
5430 mac_addr);
5431 int status = 0;
5432 bool is_associated = false;
5433
5434 if (!stainfo) {
5435 status = hdd_get_cached_station_remote(hdd_ctx, adapter,
5436 mac_addr);
5437 return status;
5438 }
5439
5440 is_associated = hdd_is_peer_associated(adapter, &mac_addr);
5441 if (!is_associated) {
5442 status = hdd_get_cached_station_remote(hdd_ctx, adapter,
5443 mac_addr);
5444 return status;
5445 }
5446
5447 status = hdd_get_connected_station_info(hdd_ctx, adapter,
5448 mac_addr, stainfo);
5449 return status;
5450}
5451
5452/**
Anurag Chouhan96919482016-07-13 16:36:57 +05305453 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
5454 * @wiphy: corestack handler
5455 * @wdev: wireless device
5456 * @data: data
5457 * @data_len: data length
5458 *
5459 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
5460 * Validate cmd attributes and send the station info to upper layers.
5461 *
5462 * Return: Success(0) or reason code for failure
5463 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05305464static int
Anurag Chouhan96919482016-07-13 16:36:57 +05305465__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
5466 struct wireless_dev *wdev,
5467 const void *data,
5468 int data_len)
5469{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005470 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Anurag Chouhan96919482016-07-13 16:36:57 +05305471 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07005472 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Anurag Chouhan96919482016-07-13 16:36:57 +05305473 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
5474 int32_t status;
5475
Dustin Brownfdf17c12018-03-14 12:55:34 -07005476 hdd_enter_dev(dev);
Anurag Chouhan96919482016-07-13 16:36:57 +05305477 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5478 hdd_err("Command not allowed in FTM mode");
5479 status = -EPERM;
5480 goto out;
5481 }
5482
5483 status = wlan_hdd_validate_context(hdd_ctx);
5484 if (0 != status)
5485 goto out;
5486
5487
Dustin Brown4ea21db2018-01-05 14:13:17 -08005488 status = wlan_cfg80211_nla_parse(tb,
5489 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
5490 data, data_len,
5491 hdd_get_station_policy);
Anurag Chouhan96919482016-07-13 16:36:57 +05305492 if (status) {
5493 hdd_err("Invalid ATTR");
5494 goto out;
5495 }
5496
5497 /* Parse and fetch Command Type*/
5498 if (tb[STATION_INFO]) {
5499 status = hdd_get_station_info(hdd_ctx, adapter);
5500 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
5501 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
Will Huang496b36c2017-07-11 16:38:50 +08005502 } else if (tb[STATION_REMOTE]) {
5503 struct qdf_mac_addr mac_addr;
5504
5505 if (adapter->device_mode != QDF_SAP_MODE &&
5506 adapter->device_mode != QDF_P2P_GO_MODE) {
5507 hdd_err("invalid device_mode:%d", adapter->device_mode);
5508 status = -EINVAL;
5509 goto out;
5510 }
5511
5512 nla_memcpy(mac_addr.bytes, tb[STATION_REMOTE],
5513 QDF_MAC_ADDR_SIZE);
5514
5515 hdd_debug("STATION_REMOTE " MAC_ADDRESS_STR,
5516 MAC_ADDR_ARRAY(mac_addr.bytes));
5517
5518 status = hdd_get_station_remote(hdd_ctx, adapter, mac_addr);
Anurag Chouhan96919482016-07-13 16:36:57 +05305519 } else {
5520 hdd_err("get station info cmd type failed");
5521 status = -EINVAL;
5522 goto out;
5523 }
Dustin Browne74003f2018-03-14 12:51:58 -07005524 hdd_exit();
Anurag Chouhan96919482016-07-13 16:36:57 +05305525out:
5526 return status;
5527}
5528
5529/**
5530 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
5531 * @wiphy: corestack handler
5532 * @wdev: wireless device
5533 * @data: data
5534 * @data_len: data length
5535 *
5536 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
5537 * Validate cmd attributes and send the station info to upper layers.
5538 *
5539 * Return: Success(0) or reason code for failure
5540 */
5541static int32_t
5542hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
5543 struct wireless_dev *wdev,
5544 const void *data,
5545 int data_len)
5546{
5547 int ret;
5548
5549 cds_ssr_protect(__func__);
5550 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
5551 cds_ssr_unprotect(__func__);
5552
5553 return ret;
5554}
5555
5556/*
5557 * undef short names defined for get station command
5558 * used by __wlan_hdd_cfg80211_get_station_cmd()
5559 */
5560#undef STATION_INVALID
5561#undef STATION_INFO
5562#undef STATION_ASSOC_FAIL_REASON
Will Huang496b36c2017-07-11 16:38:50 +08005563#undef STATION_REMOTE
Anurag Chouhan96919482016-07-13 16:36:57 +05305564#undef STATION_MAX
Will Huang496b36c2017-07-11 16:38:50 +08005565#undef LINK_INFO_STANDARD_NL80211_ATTR
5566#undef AP_INFO_STANDARD_NL80211_ATTR
5567#undef INFO_ROAM_COUNT
5568#undef INFO_AKM
5569#undef WLAN802_11_MODE
5570#undef AP_INFO_HS20_INDICATION
5571#undef HT_OPERATION
5572#undef VHT_OPERATION
5573#undef INFO_ASSOC_FAIL_REASON
5574#undef REMOTE_MAX_PHY_RATE
5575#undef REMOTE_TX_PACKETS
5576#undef REMOTE_TX_BYTES
5577#undef REMOTE_RX_PACKETS
5578#undef REMOTE_RX_BYTES
5579#undef REMOTE_LAST_TX_RATE
5580#undef REMOTE_LAST_RX_RATE
5581#undef REMOTE_WMM
5582#undef REMOTE_SUPPORTED_MODE
5583#undef REMOTE_AMPDU
5584#undef REMOTE_TX_STBC
5585#undef REMOTE_RX_STBC
5586#undef REMOTE_CH_WIDTH
5587#undef REMOTE_SGI_ENABLE
5588#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
5589#undef REMOTE_PAD
5590#endif
Anurag Chouhan96919482016-07-13 16:36:57 +05305591
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005592#ifdef WLAN_FEATURE_ROAM_OFFLOAD
5593/**
5594 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
5595 * @wiphy: pointer to wireless wiphy structure.
5596 * @wdev: pointer to wireless_dev structure.
5597 * @data: Pointer to the Key data
5598 * @data_len:Length of the data passed
5599 *
5600 * This is called when wlan driver needs to save the keys received via
5601 * vendor specific command.
5602 *
5603 * Return: Return the Success or Failure code.
5604 */
5605static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
5606 struct wireless_dev *wdev,
5607 const void *data, int data_len)
5608{
5609 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
5610 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07005611 struct hdd_adapter *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005612 struct hdd_context *hdd_ctx_ptr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005613 int status;
Deepak Dhamdhere828f1892017-02-09 11:51:19 -08005614 struct pmkid_mode_bits pmkid_modes;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005615
Dustin Brownfdf17c12018-03-14 12:55:34 -07005616 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08005617
Anurag Chouhan6d760662016-02-20 16:05:43 +05305618 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005619 hdd_err("Command not allowed in FTM mode");
5620 return -EPERM;
5621 }
5622
Hanumanth Reddy Pothula53874852018-03-08 19:57:49 +05305623 if ((data == NULL) || (data_len <= 0) ||
5624 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07005625 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005626 return -EINVAL;
5627 }
5628
5629 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
5630 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07005631 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005632 return -EINVAL;
5633 }
5634
5635 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305636 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005637 return status;
Deepak Dhamdhere828f1892017-02-09 11:51:19 -08005638
5639 hdd_get_pmkid_modes(hdd_ctx_ptr, &pmkid_modes);
5640
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005641 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
Jeff Johnson1b780e42017-10-31 14:11:45 -07005642 hdd_adapter_ptr->session_id,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07005643 true,
Deepak Dhamdhere828f1892017-02-09 11:51:19 -08005644 &pmkid_modes);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305645 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
5646 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005647 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
Jeff Johnson1b780e42017-10-31 14:11:45 -07005648 hdd_adapter_ptr->session_id, local_pmk, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005649 return 0;
5650}
5651
5652/**
5653 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
5654 * @wiphy: pointer to wireless wiphy structure.
5655 * @wdev: pointer to wireless_dev structure.
5656 * @data: Pointer to the Key data
5657 * @data_len:Length of the data passed
5658 *
5659 * This is called when wlan driver needs to save the keys received via
5660 * vendor specific command.
5661 *
5662 * Return: Return the Success or Failure code.
5663 */
5664static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
5665 struct wireless_dev *wdev,
5666 const void *data, int data_len)
5667{
5668 int ret;
5669
5670 cds_ssr_protect(__func__);
5671 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
5672 cds_ssr_unprotect(__func__);
5673
5674 return ret;
5675}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08005676#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005677
5678static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
5679 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
5680 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
5681 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07005682 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005683};
5684
5685/**
5686 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
5687 * @wiphy: pointer to wireless wiphy structure.
5688 * @wdev: pointer to wireless_dev structure.
5689 * @data: Pointer to the data to be passed via vendor interface
5690 * @data_len:Length of the data to be passed
5691 *
5692 * This is called when wlan driver needs to send wifi driver related info
5693 * (driver/fw version) to the user space application upon request.
5694 *
5695 * Return: Return the Success or Failure code.
5696 */
5697static int
5698__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
5699 struct wireless_dev *wdev,
5700 const void *data, int data_len)
5701{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005702 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005703 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07005704 tSirVersionString driver_version;
5705 tSirVersionString firmware_version;
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07005706 const char *hw_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005707 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07005708 uint32_t sub_id = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005709 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07005710 struct sk_buff *reply_skb;
5711 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005712
Dustin Brownfdf17c12018-03-14 12:55:34 -07005713 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08005714
Anurag Chouhan6d760662016-02-20 16:05:43 +05305715 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005716 hdd_err("Command not allowed in FTM mode");
5717 return -EPERM;
5718 }
5719
5720 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305721 if (status)
5722 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005723
Dustin Brown4ea21db2018-01-05 14:13:17 -08005724 if (wlan_cfg80211_nla_parse(tb_vendor,
5725 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX,
5726 data, data_len,
5727 qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07005728 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005729 return -EINVAL;
5730 }
5731
5732 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08005733 hdd_debug("Rcvd req for Driver version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07005734 strlcpy(driver_version, QWLAN_VERSIONSTR,
5735 sizeof(driver_version));
5736 skb_len += strlen(driver_version) + 1;
5737 count++;
5738 }
5739
5740 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005741 hdd_debug("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005742 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
5743 &crmid);
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07005744 sub_id = (hdd_ctx->target_fw_vers_ext & 0xf0000000) >> 28;
5745 hw_version = hdd_ctx->target_hw_name;
Ryan Hsu7ac88852016-04-28 10:20:34 -07005746 snprintf(firmware_version, sizeof(firmware_version),
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07005747 "FW:%d.%d.%d.%d.%d HW:%s", major_spid, minor_spid,
5748 siid, crmid, sub_id, hw_version);
Ryan Hsu7ac88852016-04-28 10:20:34 -07005749 skb_len += strlen(firmware_version) + 1;
5750 count++;
5751 }
5752
Rajeev Kumar Sirasanagandla551613d2018-05-16 17:21:01 +05305753 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
5754 hdd_debug("Rcvd req for Radio index");
5755 skb_len += sizeof(uint32_t);
5756 count++;
5757 }
5758
Ryan Hsu7ac88852016-04-28 10:20:34 -07005759 if (count == 0) {
5760 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005761 return -EINVAL;
5762 }
5763
Ryan Hsu7ac88852016-04-28 10:20:34 -07005764 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
5765 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
5766
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005767 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07005768 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005769 return -ENOMEM;
5770 }
5771
Ryan Hsu7ac88852016-04-28 10:20:34 -07005772 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
5773 if (nla_put_string(reply_skb,
5774 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
5775 driver_version))
5776 goto error_nla_fail;
5777 }
5778
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05305779 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07005780 if (nla_put_string(reply_skb,
5781 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
5782 firmware_version))
5783 goto error_nla_fail;
5784 }
5785
5786 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
5787 if (nla_put_u32(reply_skb,
5788 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
5789 hdd_ctx->radio_index))
5790 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005791 }
5792
5793 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07005794
5795error_nla_fail:
5796 hdd_err("nla put fail");
5797 kfree_skb(reply_skb);
5798 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005799}
5800
5801/**
5802 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
5803 * @wiphy: pointer to wireless wiphy structure.
5804 * @wdev: pointer to wireless_dev structure.
5805 * @data: Pointer to the data to be passed via vendor interface
5806 * @data_len:Length of the data to be passed
5807 *
5808 * This is called when wlan driver needs to send wifi driver related info
5809 * (driver/fw version) to the user space application upon request.
5810 *
5811 * Return: Return the Success or Failure code.
5812 */
5813static int
5814wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
5815 struct wireless_dev *wdev,
5816 const void *data, int data_len)
5817{
5818 int ret;
5819
5820 cds_ssr_protect(__func__);
5821 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
5822 cds_ssr_unprotect(__func__);
5823
5824 return ret;
5825}
5826
5827/**
5828 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
5829 * @wiphy: pointer to wireless wiphy structure.
5830 * @wdev: pointer to wireless_dev structure.
5831 * @data: Pointer to the data to be passed via vendor interface
5832 * @data_len:Length of the data to be passed
5833 *
5834 * This is called by userspace to know the supported logger features
5835 *
5836 * Return: Return the Success or Failure code.
5837 */
5838static int
5839__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
5840 struct wireless_dev *wdev,
5841 const void *data, int data_len)
5842{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005843 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005844 int status;
5845 uint32_t features;
5846 struct sk_buff *reply_skb = NULL;
5847
Dustin Brownfdf17c12018-03-14 12:55:34 -07005848 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08005849
Anurag Chouhan6d760662016-02-20 16:05:43 +05305850 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005851 hdd_err("Command not allowed in FTM mode");
5852 return -EPERM;
5853 }
5854
5855 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305856 if (status)
5857 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005858
5859 features = 0;
5860
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005861 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
5862 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
5863 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
Srinivas Girigowdaa26eac02018-01-23 12:49:20 -08005864 features |= WIFI_LOGGER_DRIVER_DUMP_SUPPORTED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005865
5866 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5867 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
5868 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07005869 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005870 return -ENOMEM;
5871 }
5872
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005873 hdd_debug("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005874 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
5875 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07005876 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005877 kfree_skb(reply_skb);
5878 return -EINVAL;
5879 }
5880
5881 return cfg80211_vendor_cmd_reply(reply_skb);
5882}
5883
5884/**
5885 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
5886 * @wiphy: pointer to wireless wiphy structure.
5887 * @wdev: pointer to wireless_dev structure.
5888 * @data: Pointer to the data to be passed via vendor interface
5889 * @data_len:Length of the data to be passed
5890 *
5891 * This is called by userspace to know the supported logger features
5892 *
5893 * Return: Return the Success or Failure code.
5894 */
5895static int
5896wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
5897 struct wireless_dev *wdev,
5898 const void *data, int data_len)
5899{
5900 int ret;
5901
5902 cds_ssr_protect(__func__);
5903 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
5904 data, data_len);
5905 cds_ssr_unprotect(__func__);
5906
5907 return ret;
5908}
5909
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305910#ifdef WLAN_FEATURE_GTK_OFFLOAD
5911void wlan_hdd_save_gtk_offload_params(struct hdd_adapter *adapter,
5912 uint8_t *kck_ptr, uint8_t *kek_ptr,
5913 uint32_t kek_len, uint8_t *replay_ctr,
5914 bool big_endian)
5915{
5916 struct hdd_station_ctx *hdd_sta_ctx;
5917 uint8_t *buf;
5918 int i;
5919 struct pmo_gtk_req *gtk_req = NULL;
5920 QDF_STATUS status = QDF_STATUS_E_FAILURE;
5921
5922 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
5923 if (!gtk_req) {
5924 hdd_err("cannot allocate gtk_req");
5925 return;
5926 }
5927
5928 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
5929 if (kck_ptr)
5930 qdf_mem_copy(gtk_req->kck, kck_ptr, NL80211_KCK_LEN);
5931
Jeff Johnsone1f2b0e2017-11-14 14:42:55 -08005932 if (kek_ptr) {
5933 /* paranoia */
5934 if (kek_len > sizeof(gtk_req->kek)) {
5935 kek_len = sizeof(gtk_req->kek);
5936 QDF_ASSERT(0);
5937 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305938 qdf_mem_copy(gtk_req->kek, kek_ptr, kek_len);
Jeff Johnsone1f2b0e2017-11-14 14:42:55 -08005939 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305940
5941 qdf_copy_macaddr(&gtk_req->bssid, &hdd_sta_ctx->conn_info.bssId);
5942
5943 gtk_req->kek_len = kek_len;
5944
5945 /* convert big to little endian since driver work on little endian */
5946 buf = (uint8_t *)&gtk_req->replay_counter;
5947 for (i = 0; i < 8; i++)
5948 buf[7 - i] = replay_ctr[i];
5949
5950 status = pmo_ucfg_cache_gtk_offload_req(adapter->hdd_vdev, gtk_req);
5951 if (status != QDF_STATUS_SUCCESS)
5952 hdd_err("Failed to cache GTK Offload");
5953
5954 qdf_mem_free(gtk_req);
5955}
5956#else
5957void wlan_hdd_save_gtk_offload_params(struct hdd_adapter *adapter,
5958 uint8_t *kck_ptr,
5959 uint8_t *kek_ptr,
5960 uint32_t kek_len,
5961 uint8_t *replay_ctr,
5962 bool big_endian)
5963{
5964}
5965#endif
5966
Sridhar Selvaraje5260442017-08-19 10:12:03 +05305967#if defined(WLAN_FEATURE_FILS_SK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305968/**
5969 * wlan_hdd_add_fils_params_roam_auth_event() - Adds FILS params in roam auth
5970 * @skb: SK buffer
5971 * @roam_info: Roam info
5972 *
5973 * API adds fils params[pmk, pmkid, next sequence number] to roam auth event
5974 *
5975 * Return: zero on success, error code on failure
5976 */
Jeff Johnson172237b2017-11-07 15:32:59 -08005977static int
5978wlan_hdd_add_fils_params_roam_auth_event(struct sk_buff *skb,
5979 struct csr_roam_info *roam_info)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305980{
5981 if (roam_info->pmk_len &&
5982 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMK,
5983 roam_info->pmk_len, roam_info->pmk)) {
5984 hdd_err("pmk send fail");
5985 return -EINVAL;
5986 }
5987
5988 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMKID,
5989 SIR_PMKID_LEN, roam_info->pmkid)) {
5990 hdd_err("pmkid send fail");
5991 return -EINVAL;
5992 }
5993
Vignesh Viswanathan8da68cf2017-09-07 14:00:04 +05305994 hdd_debug("Update ERP Seq Num %d, Next ERP Seq Num %d",
5995 roam_info->update_erp_next_seq_num,
5996 roam_info->next_erp_seq_num);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305997 if (roam_info->update_erp_next_seq_num &&
5998 nla_put_u16(skb,
5999 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_FILS_ERP_NEXT_SEQ_NUM,
6000 roam_info->next_erp_seq_num)) {
6001 hdd_err("ERP seq num send fail");
6002 return -EINVAL;
6003 }
6004
6005 return 0;
6006}
6007#else
Jeff Johnson172237b2017-11-07 15:32:59 -08006008static inline int
6009wlan_hdd_add_fils_params_roam_auth_event(struct sk_buff *skb,
6010 struct csr_roam_info *roam_info)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306011{
6012 return 0;
6013}
6014#endif
6015
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08006016#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006017/**
6018 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05306019 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006020 * @bssid: pointer to bssid of roamed AP.
6021 * @req_rsn_ie: Pointer to request RSN IE
6022 * @req_rsn_len: Length of the request RSN IE
6023 * @rsp_rsn_ie: Pointer to response RSN IE
6024 * @rsp_rsn_len: Length of the response RSN IE
6025 * @roam_info_ptr: Pointer to the roaming related information
6026 *
6027 * This is called when wlan driver needs to send the roaming and
6028 * authorization information after roaming.
6029 *
6030 * The information that would be sent is the request RSN IE, response
6031 * RSN IE and BSSID of the newly roamed AP.
6032 *
6033 * If the Authorized status is authenticated, then additional parameters
6034 * like PTK's KCK and KEK and Replay Counter would also be passed to the
6035 * supplicant.
6036 *
6037 * The supplicant upon receiving this event would ignore the legacy
6038 * cfg80211_roamed call and use the entire information from this event.
6039 * The cfg80211_roamed should still co-exist since the kernel will
6040 * make use of the parameters even if the supplicant ignores it.
6041 *
6042 * Return: Return the Success or Failure code.
6043 */
Jeff Johnsone5006672017-08-29 14:39:02 -07006044int wlan_hdd_send_roam_auth_event(struct hdd_adapter *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006045 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
Jeff Johnson172237b2017-11-07 15:32:59 -08006046 uint32_t rsp_rsn_len, struct csr_roam_info *roam_info_ptr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006047{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006048 struct hdd_context *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006049 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08006050 eCsrAuthType auth_type;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306051 uint32_t fils_params_len;
6052 int status;
Jeff Johnson4f7f7c62017-10-05 08:53:41 -07006053
Dustin Brown491d54b2018-03-14 12:39:11 -07006054 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006055
Abhishek Singh23edd1c2016-05-05 11:56:06 +05306056 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006057 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006058
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07006059 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08006060 !roam_info_ptr->roamSynchInProgress)
6061 return 0;
6062
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306063 /*
6064 * PMK is sent from FW in Roam Synch Event for FILS Roaming.
6065 * In that case, add three more NL attributes.ie. PMK, PMKID
6066 * and ERP next sequence number. Add corresponding lengths
6067 * with 3 extra NL message headers for each of the
6068 * aforementioned params.
6069 */
6070 fils_params_len = roam_info_ptr->pmk_len + SIR_PMKID_LEN +
6071 sizeof(uint16_t) + (3 * NLMSG_HDRLEN);
6072
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006073 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05306074 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006075 ETH_ALEN + req_rsn_len + rsp_rsn_len +
6076 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306077 SIR_KCK_KEY_LEN + roam_info_ptr->kek_len +
6078 sizeof(uint8_t) + (8 * NLMSG_HDRLEN) +
6079 fils_params_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006080 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
6081 GFP_KERNEL);
6082
6083 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07006084 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006085 return -EINVAL;
6086 }
6087
6088 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
6089 ETH_ALEN, bssid) ||
6090 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
6091 req_rsn_len, req_rsn_ie) ||
6092 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
6093 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07006094 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006095 goto nla_put_failure;
6096 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006097 if (roam_info_ptr->synchAuthStatus ==
6098 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07006099 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08006100 if (nla_put_u8(skb,
6101 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
6102 hdd_err("nla put fail");
6103 goto nla_put_failure;
6104 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08006105 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
6106 /* if FT or CCKM connection: dont send replay counter */
6107 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
6108 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
6109 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
6110 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
6111 nla_put(skb,
6112 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
6113 SIR_REPLAY_CTR_LEN,
6114 roam_info_ptr->replay_ctr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006115 hdd_err("non FT/non CCKM connection");
6116 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08006117 goto nla_put_failure;
6118 }
Vignesh Viswanathan62d98992017-11-30 12:30:37 +05306119 if (roam_info_ptr->kek_len > SIR_KEK_KEY_LEN_FILS ||
6120 nla_put(skb,
Naveen Rawat14298b92015-11-25 16:27:41 -08006121 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
6122 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
6123 nla_put(skb,
6124 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306125 roam_info_ptr->kek_len, roam_info_ptr->kek)) {
Vignesh Viswanathan62d98992017-11-30 12:30:37 +05306126 hdd_err("nla put fail, kek_len %d",
6127 roam_info_ptr->kek_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006128 goto nla_put_failure;
6129 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306130
6131 status = wlan_hdd_add_fils_params_roam_auth_event(skb,
6132 roam_info_ptr);
6133 if (status)
6134 goto nla_put_failure;
6135
6136 /*
6137 * Save the gtk rekey parameters in HDD STA context. They will
6138 * be used next time when host enables GTK offload and goes
6139 * into power save state.
6140 */
6141 wlan_hdd_save_gtk_offload_params(adapter, roam_info_ptr->kck,
6142 roam_info_ptr->kek,
6143 roam_info_ptr->kek_len,
6144 roam_info_ptr->replay_ctr,
6145 true);
6146 hdd_debug("roam_info_ptr->replay_ctr 0x%llx",
6147 *((uint64_t *)roam_info_ptr->replay_ctr));
6148
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006149 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07006150 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006151 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
6152 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07006153 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006154 goto nla_put_failure;
6155 }
6156 }
6157
Selvaraj, Sridhard1225e62017-03-17 12:56:58 +05306158 hdd_debug("Auth Status = %d Subnet Change Status = %d",
6159 roam_info_ptr->synchAuthStatus,
6160 roam_info_ptr->subnet_change_status);
Ravi Joshi277ae9b2015-11-13 11:30:43 -08006161
6162 /*
6163 * Add subnet change status if subnet has changed
6164 * 0 = unchanged
6165 * 1 = changed
6166 * 2 = unknown
6167 */
6168 if (roam_info_ptr->subnet_change_status) {
6169 if (nla_put_u8(skb,
6170 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
6171 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07006172 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08006173 goto nla_put_failure;
6174 }
6175 }
6176
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006177 cfg80211_vendor_event(skb, GFP_KERNEL);
6178 return 0;
6179
6180nla_put_failure:
6181 kfree_skb(skb);
6182 return -EINVAL;
6183}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08006184#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006185
lifeng907edd62017-05-12 10:10:36 +08006186#define ANT_DIV_PROBE_PERIOD \
6187 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD
6188#define ANT_DIV_STAY_PERIOD \
6189 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD
6190#define ANT_DIV_SNR_DIFF \
6191 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF
6192#define ANT_DIV_PROBE_DWELL_TIME \
6193 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME
6194#define ANT_DIV_MGMT_SNR_WEIGHT \
6195 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT
6196#define ANT_DIV_DATA_SNR_WEIGHT \
6197 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT
6198#define ANT_DIV_ACK_SNR_WEIGHT \
6199 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT
lifeng66831662017-05-19 16:01:35 +08006200#define RX_REORDER_TIMEOUT_VOICE \
6201 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VOICE
6202#define RX_REORDER_TIMEOUT_VIDEO \
6203 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VIDEO
6204#define RX_REORDER_TIMEOUT_BESTEFFORT \
6205 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BESTEFFORT
6206#define RX_REORDER_TIMEOUT_BACKGROUND \
6207 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BACKGROUND
6208#define RX_BLOCKSIZE_PEER_MAC \
6209 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_PEER_MAC
6210#define RX_BLOCKSIZE_WINLIMIT \
6211 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_WINLIMIT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006212static const struct nla_policy
6213wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
6214
6215 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
6216 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
6217 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Jeff Johnson79f6a602017-06-15 09:48:25 -07006218 [QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT] = {.type = NLA_U32},
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05306219 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05306220 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
6221 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08006222 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
6223 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
6224 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
6225 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
6226 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05306227 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
lifeng907edd62017-05-12 10:10:36 +08006228 [ANT_DIV_PROBE_PERIOD] = {.type = NLA_U32},
6229 [ANT_DIV_STAY_PERIOD] = {.type = NLA_U32},
6230 [ANT_DIV_SNR_DIFF] = {.type = NLA_U32},
6231 [ANT_DIV_PROBE_DWELL_TIME] = {.type = NLA_U32},
6232 [ANT_DIV_MGMT_SNR_WEIGHT] = {.type = NLA_U32},
6233 [ANT_DIV_DATA_SNR_WEIGHT] = {.type = NLA_U32},
6234 [ANT_DIV_ACK_SNR_WEIGHT] = {.type = NLA_U32},
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306235 [QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL] = {.type = NLA_U8},
lifeng66831662017-05-19 16:01:35 +08006236 [RX_REORDER_TIMEOUT_VOICE] = {.type = NLA_U32},
6237 [RX_REORDER_TIMEOUT_VIDEO] = {.type = NLA_U32},
6238 [RX_REORDER_TIMEOUT_BESTEFFORT] = {.type = NLA_U32},
6239 [RX_REORDER_TIMEOUT_BACKGROUND] = {.type = NLA_U32},
Jeff Johnson19a5a7e2017-06-15 14:51:26 -07006240 [RX_BLOCKSIZE_PEER_MAC] = {
6241 .type = NLA_UNSPEC,
6242 .len = QDF_MAC_ADDR_SIZE},
lifeng66831662017-05-19 16:01:35 +08006243 [RX_BLOCKSIZE_WINLIMIT] = {.type = NLA_U32},
Mukul Sharma6398b252017-05-01 17:58:12 +05306244 [QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL] = {.type = NLA_U32 },
Poddar, Siddarth4b3f7312017-11-02 17:00:20 +05306245 [QCA_WLAN_VENDOR_ATTR_CONFIG_LRO] = {.type = NLA_U8 },
lifengd217d192017-05-09 19:44:16 +08006246 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA] = {.type = NLA_U32 },
6247 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN] = {.type = NLA_U32 },
6248 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST] = {.type = NLA_U32 },
6249 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL] = {.type = NLA_U32 },
Paul Zhang99fe8842017-12-08 14:43:46 +08006250 [QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL] = {.type = NLA_U16 },
Nachiket Kukadeaaf8a712017-07-27 19:15:36 +05306251 [QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT] = {.type = NLA_U8},
Sandeep Puligilla24b7aa72017-10-13 18:05:14 -07006252 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE] = {.type = NLA_U8 },
Abhishek Singh6454ad32017-12-20 10:42:21 +05306253 [QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE] = {.type = NLA_U8},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006254};
6255
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006256static const struct nla_policy
6257wlan_hdd_wifi_test_config_policy[
6258 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX + 1] = {
6259 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE] = {
6260 .type = NLA_U8},
6261 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ] = {
6262 .type = NLA_U8},
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08006263 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS] = {
6264 .type = NLA_U8},
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08006265 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ] = {
6266 .type = NLA_U8},
Kiran Kumar Lokere5cc2f0d2018-02-08 17:10:05 -08006267 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION] = {
6268 .type = NLA_U8},
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08006269 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE] = {
6270 .type = NLA_U8},
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006271 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION] = {
6272 .type = NLA_U8},
6273 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID] = {
6274 .type = NLA_U8},
6275 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE] = {
6276 .type = NLA_U8},
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08006277 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK] = {
6278 .type = NLA_U8},
6279 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC] = {
6280 .type = NLA_U8},
Kiran Kumar Lokerea006a302018-03-07 20:58:13 -08006281 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF] = {
6282 .type = NLA_U8},
Kiran Kumar Lokere6c7f3fa2018-05-14 18:12:27 -07006283 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE] = {
6284 .type = NLA_U8},
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006285};
6286
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006287/**
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306288 * wlan_hdd_add_qcn_ie() - Add QCN IE to a given IE buffer
6289 * @ie_data: IE buffer
6290 * @ie_len: length of the @ie_data
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306291 *
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306292 * Return: QDF_STATUS
6293 */
6294static QDF_STATUS wlan_hdd_add_qcn_ie(uint8_t *ie_data, uint16_t *ie_len)
6295{
6296 tDot11fIEQCN_IE qcn_ie;
6297 uint8_t qcn_ie_hdr[QCN_IE_HDR_LEN]
6298 = {IE_EID_VENDOR, DOT11F_IE_QCN_IE_MAX_LEN,
6299 0x8C, 0xFD, 0xF0, 0x1};
6300
6301 if (((*ie_len) + QCN_IE_HDR_LEN +
6302 QCN_IE_VERSION_SUBATTR_DATA_LEN) > MAX_DEFAULT_SCAN_IE_LEN) {
6303 hdd_err("IE buffer not enough for QCN IE");
6304 return QDF_STATUS_E_FAILURE;
6305 }
6306
6307 /* Add QCN IE header */
6308 qdf_mem_copy(ie_data + (*ie_len), qcn_ie_hdr, QCN_IE_HDR_LEN);
6309 (*ie_len) += QCN_IE_HDR_LEN;
6310
6311 /* Retrieve Version sub-attribute data */
6312 populate_dot11f_qcn_ie(&qcn_ie);
6313
6314 /* Add QCN IE data[version sub attribute] */
6315 qdf_mem_copy(ie_data + (*ie_len), qcn_ie.version,
6316 (QCN_IE_VERSION_SUBATTR_LEN));
6317 (*ie_len) += (QCN_IE_VERSION_SUBATTR_LEN);
6318
6319 return QDF_STATUS_SUCCESS;
6320}
6321
6322/**
6323 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
6324 * @hdd_ctx: HDD context
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306325 * @adapter: Pointer to HDD adapter
6326 * @ie_data: Pointer to Scan IEs buffer
6327 * @ie_len: Length of Scan IEs
6328 *
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306329 * This API is used to store the default scan ies received from
6330 * supplicant. Also saves QCN IE if g_qcn_ie_support INI is enabled
6331 *
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306332 * Return: 0 on success; error number otherwise
6333 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006334static int wlan_hdd_save_default_scan_ies(struct hdd_context *hdd_ctx,
Jeff Johnsone5006672017-08-29 14:39:02 -07006335 struct hdd_adapter *adapter,
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306336 uint8_t *ie_data, uint16_t ie_len)
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306337{
Jeff Johnson37588942017-08-15 16:11:41 -07006338 struct hdd_scan_info *scan_info = &adapter->scan_info;
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306339 bool add_qcn_ie = hdd_ctx->config->qcn_ie_support;
6340
6341 if (!scan_info)
6342 return -EINVAL;
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306343
6344 if (scan_info->default_scan_ies) {
6345 qdf_mem_free(scan_info->default_scan_ies);
6346 scan_info->default_scan_ies = NULL;
6347 }
6348
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05306349 scan_info->default_scan_ies_len = ie_len;
6350
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306351 if (add_qcn_ie)
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05306352 ie_len += (QCN_IE_HDR_LEN + QCN_IE_VERSION_SUBATTR_LEN);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306353
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306354 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05306355 if (!scan_info->default_scan_ies) {
6356 scan_info->default_scan_ies_len = 0;
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306357 return -ENOMEM;
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05306358 }
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306359
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05306360 qdf_mem_copy(scan_info->default_scan_ies, ie_data,
6361 scan_info->default_scan_ies_len);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306362
6363 /* Add QCN IE if g_qcn_ie_support INI is enabled */
6364 if (add_qcn_ie)
6365 wlan_hdd_add_qcn_ie(scan_info->default_scan_ies,
6366 &(scan_info->default_scan_ies_len));
6367
6368 hdd_debug("Saved default scan IE:");
6369 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
6370 (uint8_t *) scan_info->default_scan_ies,
6371 scan_info->default_scan_ies_len);
6372
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306373 return 0;
6374}
6375
6376/**
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306377 * wlan_hdd_handle_restrict_offchan_config() -
6378 * Handle wifi configuration attribute :
6379 * QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL
6380 * @adapter: Pointer to HDD adapter
6381 * @restrict_offchan: Restrict offchannel setting done by
6382 * application
6383 *
6384 * Return: 0 on success; error number otherwise
6385 */
Jeff Johnsone5006672017-08-29 14:39:02 -07006386static int wlan_hdd_handle_restrict_offchan_config(struct hdd_adapter *adapter,
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306387 u8 restrict_offchan)
6388{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006389 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonc1e62782017-11-09 09:50:17 -08006390 enum QDF_OPMODE dev_mode = adapter->device_mode;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306391 int ret_val = 0;
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006392 QDF_STATUS status;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306393
6394 if (!(dev_mode == QDF_SAP_MODE || dev_mode == QDF_P2P_GO_MODE)) {
6395 hdd_err("Invalid interface type:%d", dev_mode);
6396 return -EINVAL;
6397 }
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006398 status = wlan_objmgr_vdev_try_get_ref(adapter->hdd_vdev, WLAN_OSIF_ID);
6399 if (status != QDF_STATUS_SUCCESS) {
6400 hdd_err("Access hdd_vdev failed: %d", status);
6401 return -EINVAL;
6402 }
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306403 if (restrict_offchan == 1) {
6404 enum policy_mgr_con_mode pmode =
6405 policy_mgr_convert_device_mode_to_qdf_type(dev_mode);
6406 int chan;
6407
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006408 u32 vdev_id = wlan_vdev_get_id(adapter->hdd_vdev);
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306409
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006410 wlan_vdev_obj_lock(adapter->hdd_vdev);
6411 wlan_vdev_mlme_cap_set(adapter->hdd_vdev,
6412 WLAN_VDEV_C_RESTRICT_OFFCHAN);
6413 wlan_vdev_obj_unlock(adapter->hdd_vdev);
6414 chan = policy_mgr_get_channel(hdd_ctx->hdd_psoc, pmode,
6415 &vdev_id);
6416 if (!chan ||
6417 wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, chan)) {
6418 hdd_err("unable to send avoid_freq");
6419 ret_val = -EINVAL;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306420 }
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006421 hdd_info("vdev %d mode %d dnbs enabled", vdev_id, dev_mode);
6422 } else if (restrict_offchan == 0) {
6423 wlan_vdev_obj_lock(adapter->hdd_vdev);
6424 wlan_vdev_mlme_cap_clear(adapter->hdd_vdev,
6425 WLAN_VDEV_C_RESTRICT_OFFCHAN);
6426 wlan_vdev_obj_unlock(adapter->hdd_vdev);
6427 if (wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, 0)) {
6428 hdd_err("unable to clear avoid_freq");
6429 ret_val = -EINVAL;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306430 }
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006431 hdd_info("vdev mode %d dnbs disabled", dev_mode);
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306432 } else {
6433 ret_val = -EINVAL;
6434 hdd_err("Invalid RESTRICT_OFFCHAN setting");
6435 }
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006436 wlan_objmgr_vdev_release_ref(adapter->hdd_vdev, WLAN_OSIF_ID);
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306437 return ret_val;
6438}
6439
6440/**
lifeng66831662017-05-19 16:01:35 +08006441 * wlan_hdd_cfg80211_wifi_set_reorder_timeout - set reorder timeout
6442 *
6443 * @hdd_ctx: hdd context
6444 * @tb: array of pointer to struct nlattr
6445 *
6446 * Return: 0 on success; error number otherwise
6447 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006448static int wlan_hdd_cfg80211_wifi_set_reorder_timeout(struct hdd_context *hdd_ctx,
lifeng66831662017-05-19 16:01:35 +08006449 struct nlattr *tb[])
6450{
Min Liuab6ed4f2018-01-09 13:13:57 +08006451 int ret_val = 0;
lifeng66831662017-05-19 16:01:35 +08006452 QDF_STATUS qdf_status;
6453 struct sir_set_rx_reorder_timeout_val reorder_timeout;
6454
6455#define RX_TIMEOUT_VAL_MIN 10
6456#define RX_TIMEOUT_VAL_MAX 1000
6457
6458 if (tb[RX_REORDER_TIMEOUT_VOICE] ||
6459 tb[RX_REORDER_TIMEOUT_VIDEO] ||
6460 tb[RX_REORDER_TIMEOUT_BESTEFFORT] ||
6461 tb[RX_REORDER_TIMEOUT_BACKGROUND]) {
6462
6463 /* if one is specified, all must be specified */
6464 if (!tb[RX_REORDER_TIMEOUT_VOICE] ||
6465 !tb[RX_REORDER_TIMEOUT_VIDEO] ||
6466 !tb[RX_REORDER_TIMEOUT_BESTEFFORT] ||
6467 !tb[RX_REORDER_TIMEOUT_BACKGROUND]) {
6468 hdd_err("four AC timeout val are required MAC");
6469 return -EINVAL;
6470 }
6471
6472 reorder_timeout.rx_timeout_pri[0] = nla_get_u32(
6473 tb[RX_REORDER_TIMEOUT_VOICE]);
6474 reorder_timeout.rx_timeout_pri[1] = nla_get_u32(
6475 tb[RX_REORDER_TIMEOUT_VIDEO]);
6476 reorder_timeout.rx_timeout_pri[2] = nla_get_u32(
6477 tb[RX_REORDER_TIMEOUT_BESTEFFORT]);
6478 reorder_timeout.rx_timeout_pri[3] = nla_get_u32(
6479 tb[RX_REORDER_TIMEOUT_BACKGROUND]);
6480 /* timeout value is required to be in the rang 10 to 1000ms */
6481 if (reorder_timeout.rx_timeout_pri[0] >= RX_TIMEOUT_VAL_MIN &&
6482 reorder_timeout.rx_timeout_pri[0] <= RX_TIMEOUT_VAL_MAX &&
6483 reorder_timeout.rx_timeout_pri[1] >= RX_TIMEOUT_VAL_MIN &&
6484 reorder_timeout.rx_timeout_pri[1] <= RX_TIMEOUT_VAL_MAX &&
6485 reorder_timeout.rx_timeout_pri[2] >= RX_TIMEOUT_VAL_MIN &&
6486 reorder_timeout.rx_timeout_pri[2] <= RX_TIMEOUT_VAL_MAX &&
6487 reorder_timeout.rx_timeout_pri[3] >= RX_TIMEOUT_VAL_MIN &&
6488 reorder_timeout.rx_timeout_pri[3] <= RX_TIMEOUT_VAL_MAX) {
6489 qdf_status = sme_set_reorder_timeout(hdd_ctx->hHal,
6490 &reorder_timeout);
6491 if (qdf_status != QDF_STATUS_SUCCESS) {
6492 hdd_err("failed to set reorder timeout err %d",
6493 qdf_status);
6494 ret_val = -EPERM;
6495 }
6496 } else {
6497 hdd_err("one of the timeout value is not in range");
6498 ret_val = -EINVAL;
6499 }
6500 }
6501
6502 return ret_val;
6503}
6504
6505/**
6506 * wlan_hdd_cfg80211_wifi_set_rx_blocksize - set rx blocksize
6507 *
6508 * @hdd_ctx: hdd context
6509 * @adapter: hdd adapter
6510 * @tb: array of pointer to struct nlattr
6511 *
6512 * Return: 0 on success; error number otherwise
6513 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006514static int wlan_hdd_cfg80211_wifi_set_rx_blocksize(struct hdd_context *hdd_ctx,
Jeff Johnsone5006672017-08-29 14:39:02 -07006515 struct hdd_adapter *adapter,
lifeng66831662017-05-19 16:01:35 +08006516 struct nlattr *tb[])
6517{
Min Liuab6ed4f2018-01-09 13:13:57 +08006518 int ret_val = 0;
lifeng66831662017-05-19 16:01:35 +08006519 uint32_t set_value;
6520 QDF_STATUS qdf_status;
6521 struct sir_peer_set_rx_blocksize rx_blocksize;
6522
6523#define WINDOW_SIZE_VAL_MIN 1
6524#define WINDOW_SIZE_VAL_MAX 64
6525
6526 if (tb[RX_BLOCKSIZE_PEER_MAC] ||
6527 tb[RX_BLOCKSIZE_WINLIMIT]) {
6528
6529 /* if one is specified, both must be specified */
6530 if (!tb[RX_BLOCKSIZE_PEER_MAC] ||
6531 !tb[RX_BLOCKSIZE_WINLIMIT]) {
Dustin Brownbacc48f2018-03-14 14:48:44 -07006532 hdd_err("Both Peer MAC and windows limit required");
lifeng66831662017-05-19 16:01:35 +08006533 return -EINVAL;
6534 }
6535
6536 memcpy(&rx_blocksize.peer_macaddr,
6537 nla_data(tb[RX_BLOCKSIZE_PEER_MAC]),
6538 sizeof(rx_blocksize.peer_macaddr)),
6539
Jeff Johnson1b780e42017-10-31 14:11:45 -07006540 rx_blocksize.vdev_id = adapter->session_id;
lifeng66831662017-05-19 16:01:35 +08006541 set_value = nla_get_u32(tb[RX_BLOCKSIZE_WINLIMIT]);
6542 /* maximum window size is 64 */
6543 if (set_value >= WINDOW_SIZE_VAL_MIN &&
6544 set_value <= WINDOW_SIZE_VAL_MAX) {
6545 rx_blocksize.rx_block_ack_win_limit = set_value;
6546 qdf_status = sme_set_rx_set_blocksize(hdd_ctx->hHal,
6547 &rx_blocksize);
6548 if (qdf_status != QDF_STATUS_SUCCESS) {
6549 hdd_err("failed to set aggr sizes err %d",
6550 qdf_status);
6551 ret_val = -EPERM;
6552 }
6553 } else {
6554 hdd_err("window size val is not in range");
6555 ret_val = -EINVAL;
6556 }
6557 }
6558
6559 return ret_val;
6560}
6561
Jeff Johnson3b2abe92017-12-15 09:03:47 -08006562static int hdd_config_scan_default_ies(struct hdd_adapter *adapter,
6563 const struct nlattr *attr)
6564{
6565 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6566 uint8_t *scan_ie;
6567 uint16_t scan_ie_len;
6568 QDF_STATUS status;
6569
6570 if (!attr)
6571 return 0;
6572
6573 scan_ie_len = nla_len(attr);
6574 hdd_debug("IE len %d session %d device mode %d",
6575 scan_ie_len, adapter->session_id, adapter->device_mode);
6576
6577 if (!scan_ie_len) {
6578 hdd_err("zero-length IE prohibited");
6579 return -EINVAL;
6580 }
6581
6582 if (scan_ie_len > MAX_DEFAULT_SCAN_IE_LEN) {
6583 hdd_err("IE length %d exceeds max of %d",
6584 scan_ie_len, MAX_DEFAULT_SCAN_IE_LEN);
6585 return -EINVAL;
6586 }
6587
6588 scan_ie = nla_data(attr);
Jeff Johnson4933c3a2018-01-10 19:33:33 -08006589 if (!wlan_is_ie_valid(scan_ie, scan_ie_len)) {
Jeff Johnson3b2abe92017-12-15 09:03:47 -08006590 hdd_err("Invalid default scan IEs");
6591 return -EINVAL;
6592 }
6593
6594 if (wlan_hdd_save_default_scan_ies(hdd_ctx, adapter,
6595 scan_ie, scan_ie_len))
6596 hdd_err("Failed to save default scan IEs");
6597
6598 if (adapter->device_mode == QDF_STA_MODE) {
6599 status = sme_set_default_scan_ie(hdd_ctx->hHal,
6600 adapter->session_id, scan_ie,
6601 scan_ie_len);
6602 if (QDF_STATUS_SUCCESS != status) {
6603 hdd_err("failed to set default scan IEs in sme: %d",
6604 status);
6605 return -EPERM;
6606 }
6607 }
6608
6609 return 0;
6610}
6611
lifeng66831662017-05-19 16:01:35 +08006612/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006613 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
6614 * vendor command
6615 *
6616 * @wiphy: wiphy device pointer
6617 * @wdev: wireless device pointer
6618 * @data: Vendor command data buffer
6619 * @data_len: Buffer length
6620 *
6621 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
6622 *
6623 * Return: Error code.
6624 */
6625static int
6626__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
6627 struct wireless_dev *wdev,
6628 const void *data,
6629 int data_len)
6630{
6631 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07006632 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006633 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006634 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
Jeff Johnson3b2abe92017-12-15 09:03:47 -08006635 const struct nlattr *attr;
6636 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006637 int ret_val = 0;
Mukul Sharma6398b252017-05-01 17:58:12 +05306638 u32 modulated_dtim, override_li;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006639 u16 stats_avg_factor;
6640 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05306641 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07006642 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07006643 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306644 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05306645 int attr_len;
6646 int access_policy = 0;
6647 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
6648 bool vendor_ie_present = false, access_policy_present = false;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05306649 struct sir_set_tx_rx_aggregation_size request;
6650 QDF_STATUS qdf_status;
Sandeep Puligilla24b7aa72017-10-13 18:05:14 -07006651 uint8_t retry, delay, enable_flag;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08006652 uint32_t abs_delay;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08006653 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05306654 uint32_t tx_fail_count;
lifeng907edd62017-05-12 10:10:36 +08006655 uint32_t ant_div_usrcfg;
lifengd217d192017-05-09 19:44:16 +08006656 uint32_t antdiv_enable, antdiv_chain;
6657 uint32_t antdiv_selftest, antdiv_selftest_intvl;
Nachiket Kukadeaaf8a712017-07-27 19:15:36 +05306658 uint8_t bmiss_bcnt;
Paul Zhang99fe8842017-12-08 14:43:46 +08006659 uint16_t latency_level;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05306660
Dustin Brownfdf17c12018-03-14 12:55:34 -07006661 hdd_enter_dev(dev);
Arif Hussain0e246802018-05-01 18:13:44 -07006662 qdf_mem_zero(&request, sizeof(request));
Jeff Johnson1f61b612016-02-12 16:28:33 -08006663
Anurag Chouhan6d760662016-02-20 16:05:43 +05306664 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006665 hdd_err("Command not allowed in FTM mode");
6666 return -EPERM;
6667 }
6668
6669 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05306670 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006671 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006672
Dustin Brown4ea21db2018-01-05 14:13:17 -08006673 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX, data,
6674 data_len, wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006675 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006676 return -EINVAL;
6677 }
6678
Krunal Sonie3531942016-04-12 17:43:53 -07006679 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
6680 ftm_capab = nla_get_u32(tb[
6681 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
6682 hdd_ctx->config->fine_time_meas_cap =
6683 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
6684 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Jeff Johnson1b780e42017-10-31 14:11:45 -07006685 adapter->session_id,
Krunal Sonie3531942016-04-12 17:43:53 -07006686 hdd_ctx->config->fine_time_meas_cap);
Naveen Rawatd2657be2017-10-10 14:31:23 -07006687 ucfg_wifi_pos_set_ftm_cap(hdd_ctx->hdd_psoc,
Naveen Rawat5f040ba2017-03-06 12:20:25 -08006688 hdd_ctx->config->fine_time_meas_cap);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006689 hdd_debug("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
Krunal Sonie3531942016-04-12 17:43:53 -07006690 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
6691 hdd_ctx->config->fine_time_meas_cap);
6692 }
6693
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006694 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
6695 modulated_dtim = nla_get_u32(
6696 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
6697
6698 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
Jeff Johnson1b780e42017-10-31 14:11:45 -07006699 adapter->session_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006700 modulated_dtim);
6701
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306702 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006703 ret_val = -EPERM;
6704 }
6705
Mukul Sharma6398b252017-05-01 17:58:12 +05306706 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL]) {
6707 override_li = nla_get_u32(
6708 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL]);
6709
6710 status = sme_override_listen_interval(hdd_ctx->hHal,
Jeff Johnson1b780e42017-10-31 14:11:45 -07006711 adapter->session_id,
Mukul Sharma6398b252017-05-01 17:58:12 +05306712 override_li);
6713
6714 if (status != QDF_STATUS_SUCCESS)
6715 ret_val = -EPERM;
6716 }
Poddar, Siddarth4b3f7312017-11-02 17:00:20 +05306717
6718 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_LRO]) {
6719 enable_flag = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_LRO]);
6720 ret_val = hdd_lro_set_reset(hdd_ctx, adapter,
6721 enable_flag);
6722 }
6723
Sandeep Puligilla24b7aa72017-10-13 18:05:14 -07006724 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE]) {
6725 enable_flag =
6726 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE]);
6727 sme_set_scan_disable(hdd_ctx->hHal, !enable_flag);
6728 }
Mukul Sharma6398b252017-05-01 17:58:12 +05306729
Kapil Gupta6213c012016-09-02 19:39:09 +05306730 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
6731 qpower = nla_get_u8(
6732 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
6733 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
6734 ret_val = -EINVAL;
6735 }
6736
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006737 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
6738 stats_avg_factor = nla_get_u16(
6739 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
6740 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
Jeff Johnson1b780e42017-10-31 14:11:45 -07006741 adapter->session_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006742 stats_avg_factor);
6743
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306744 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006745 ret_val = -EPERM;
6746 }
6747
6748
6749 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
6750 guard_time = nla_get_u32(
6751 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
6752 status = sme_configure_guard_time(hdd_ctx->hHal,
Jeff Johnson1b780e42017-10-31 14:11:45 -07006753 adapter->session_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006754 guard_time);
6755
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306756 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006757 ret_val = -EPERM;
6758 }
6759
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05306760 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
6761 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
6762 attr_len = nla_len(
6763 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
6764 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006765 hdd_err("Invalid value. attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05306766 attr_len);
6767 return -EINVAL;
6768 }
6769
6770 nla_memcpy(&vendor_ie,
6771 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
6772 attr_len);
6773 vendor_ie_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006774 hdd_debug("Access policy vendor ie present.attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05306775 attr_len);
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05306776 }
6777
6778 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
6779 access_policy = (int) nla_get_u32(
6780 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
6781 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
6782 (access_policy >
6783 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006784 hdd_err("Invalid value. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05306785 access_policy);
6786 return -EINVAL;
6787 }
6788 access_policy_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006789 hdd_debug("Access policy present. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05306790 access_policy);
6791 }
6792
Zhang Qiana3bcbe02016-08-12 16:20:36 +08006793 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
6794 retry = nla_get_u8(tb[
6795 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
6796 retry = retry > CFG_NON_AGG_RETRY_MAX ?
6797 CFG_NON_AGG_RETRY_MAX : retry;
6798 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
Jeff Johnson1b780e42017-10-31 14:11:45 -07006799 ret_val = wma_cli_set_command(adapter->session_id, param_id,
Zhang Qiana3bcbe02016-08-12 16:20:36 +08006800 retry, PDEV_CMD);
6801 }
6802
6803 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
6804 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
6805 retry = retry > CFG_AGG_RETRY_MAX ?
6806 CFG_AGG_RETRY_MAX : retry;
6807
6808 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
6809 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
6810 CFG_AGG_RETRY_MIN : retry;
6811 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
Jeff Johnson1b780e42017-10-31 14:11:45 -07006812 ret_val = wma_cli_set_command(adapter->session_id, param_id,
Zhang Qiana3bcbe02016-08-12 16:20:36 +08006813 retry, PDEV_CMD);
6814 }
6815
6816 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
6817 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
6818 retry = retry > CFG_MGMT_RETRY_MAX ?
6819 CFG_MGMT_RETRY_MAX : retry;
6820 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
Jeff Johnson1b780e42017-10-31 14:11:45 -07006821 ret_val = wma_cli_set_command(adapter->session_id, param_id,
Zhang Qiana3bcbe02016-08-12 16:20:36 +08006822 retry, PDEV_CMD);
6823 }
6824
6825 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
6826 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
6827 retry = retry > CFG_CTRL_RETRY_MAX ?
6828 CFG_CTRL_RETRY_MAX : retry;
6829 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
Jeff Johnson1b780e42017-10-31 14:11:45 -07006830 ret_val = wma_cli_set_command(adapter->session_id, param_id,
Zhang Qiana3bcbe02016-08-12 16:20:36 +08006831 retry, PDEV_CMD);
6832 }
6833
6834 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
6835 delay = nla_get_u8(tb[
6836 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
6837 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
6838 CFG_PROPAGATION_DELAY_MAX : delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08006839 abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08006840 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
Jeff Johnson1b780e42017-10-31 14:11:45 -07006841 ret_val = wma_cli_set_command(adapter->session_id, param_id,
Zhang Qiane9fd14b2017-03-08 11:29:00 +08006842 abs_delay, PDEV_CMD);
6843 }
6844
6845 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]) {
6846 abs_delay = nla_get_u8(tb[
6847 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]);
6848 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
Jeff Johnson1b780e42017-10-31 14:11:45 -07006849 ret_val = wma_cli_set_command(adapter->session_id, param_id,
Zhang Qiane9fd14b2017-03-08 11:29:00 +08006850 abs_delay, PDEV_CMD);
Zhang Qiana3bcbe02016-08-12 16:20:36 +08006851 }
6852
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05306853 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
6854 tx_fail_count = nla_get_u32(
6855 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
6856 if (tx_fail_count) {
6857 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
Jeff Johnson1b780e42017-10-31 14:11:45 -07006858 adapter->session_id, tx_fail_count);
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05306859 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006860 hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05306861 status);
6862 return -EINVAL;
6863 }
6864 }
6865 }
6866
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05306867 if (vendor_ie_present && access_policy_present) {
6868 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
6869 access_policy =
6870 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05306871 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05306872 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05306873 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05306874
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006875 hdd_debug("calling sme_update_access_policy_vendor_ie");
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05306876 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
Jeff Johnson1b780e42017-10-31 14:11:45 -07006877 adapter->session_id, &vendor_ie[0],
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05306878 access_policy);
6879 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006880 hdd_err("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05306881 return -EINVAL;
6882 }
6883 }
6884
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05306885 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
6886 set_value = nla_get_u8(
6887 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006888 hdd_debug("set_value: %d", set_value);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05306889 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
6890 }
6891
Jeff Johnson3b2abe92017-12-15 09:03:47 -08006892 attr = tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES];
6893 ret = hdd_config_scan_default_ies(adapter, attr);
6894 if (ret)
6895 ret_val = ret;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05306896
6897 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
6898 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
6899 /* if one is specified, both must be specified */
6900 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
6901 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
6902 hdd_err("Both TX and RX MPDU Aggregation required");
6903 return -EINVAL;
6904 }
6905
6906 request.tx_aggregation_size = nla_get_u8(
6907 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
6908 request.rx_aggregation_size = nla_get_u8(
6909 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
Jeff Johnson1b780e42017-10-31 14:11:45 -07006910 request.vdev_id = adapter->session_id;
Arif Hussain0e246802018-05-01 18:13:44 -07006911 request.aggr_type = WMI_VDEV_CUSTOM_AGGR_TYPE_AMPDU;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05306912
6913 if (request.tx_aggregation_size >=
6914 CFG_TX_AGGREGATION_SIZE_MIN &&
6915 request.tx_aggregation_size <=
6916 CFG_TX_AGGREGATION_SIZE_MAX &&
6917 request.rx_aggregation_size >=
6918 CFG_RX_AGGREGATION_SIZE_MIN &&
6919 request.rx_aggregation_size <=
6920 CFG_RX_AGGREGATION_SIZE_MAX) {
6921 qdf_status = wma_set_tx_rx_aggregation_size(&request);
6922 if (qdf_status != QDF_STATUS_SUCCESS) {
6923 hdd_err("failed to set aggr sizes err %d",
6924 qdf_status);
6925 ret_val = -EPERM;
6926 }
6927 } else {
6928 hdd_err("TX %d RX %d MPDU aggr size not in range",
6929 request.tx_aggregation_size,
6930 request.rx_aggregation_size);
6931 ret_val = -EINVAL;
6932 }
6933 }
6934
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05306935 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
6936 uint8_t ignore_assoc_disallowed;
6937
6938 ignore_assoc_disallowed
6939 = nla_get_u8(tb[
6940 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006941 hdd_debug("Set ignore_assoc_disallowed value - %d",
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05306942 ignore_assoc_disallowed);
6943 if ((ignore_assoc_disallowed <
6944 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
6945 (ignore_assoc_disallowed >
6946 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
6947 return -EPERM;
6948
6949 sme_update_session_param(hdd_ctx->hHal,
Jeff Johnson1b780e42017-10-31 14:11:45 -07006950 adapter->session_id,
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05306951 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
6952 ignore_assoc_disallowed);
6953 }
6954
lifeng907edd62017-05-12 10:10:36 +08006955#define ANT_DIV_SET_PERIOD(probe_period, stay_period) \
6956 ((1<<26)|((probe_period&0x1fff)<<13)|(stay_period&0x1fff))
6957
6958#define ANT_DIV_SET_SNR_DIFF(snr_diff) \
6959 ((1<<27)|(snr_diff&0x1fff))
6960
6961#define ANT_DIV_SET_PROBE_DWELL_TIME(probe_dwell_time) \
6962 ((1<<28)|(probe_dwell_time&0x1fff))
6963
6964#define ANT_DIV_SET_WEIGHT(mgmt_snr_weight, data_snr_weight, ack_snr_weight) \
6965 ((1<<29)|((mgmt_snr_weight&0xff)<<16)|((data_snr_weight&0xff)<<8)| \
6966 (ack_snr_weight&0xff))
6967
6968 if (tb[ANT_DIV_PROBE_PERIOD] ||
6969 tb[ANT_DIV_STAY_PERIOD]) {
6970
6971 if (!tb[ANT_DIV_PROBE_PERIOD] ||
6972 !tb[ANT_DIV_STAY_PERIOD]) {
6973 hdd_err("Both probe and stay period required");
6974 return -EINVAL;
6975 }
6976
6977 ant_div_usrcfg = ANT_DIV_SET_PERIOD(
6978 nla_get_u32(tb[ANT_DIV_PROBE_PERIOD]),
6979 nla_get_u32(tb[ANT_DIV_STAY_PERIOD]));
6980 hdd_debug("ant div set period: %x", ant_div_usrcfg);
Jeff Johnson1b780e42017-10-31 14:11:45 -07006981 ret_val = wma_cli_set_command((int)adapter->session_id,
lifeng907edd62017-05-12 10:10:36 +08006982 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
6983 ant_div_usrcfg, PDEV_CMD);
6984 if (ret_val) {
6985 hdd_err("Failed to set ant div period");
6986 return ret_val;
6987 }
6988 }
6989
6990 if (tb[ANT_DIV_SNR_DIFF]) {
6991 ant_div_usrcfg = ANT_DIV_SET_SNR_DIFF(
6992 nla_get_u32(tb[ANT_DIV_SNR_DIFF]));
6993 hdd_debug("ant div set snr diff: %x", ant_div_usrcfg);
Jeff Johnson1b780e42017-10-31 14:11:45 -07006994 ret_val = wma_cli_set_command((int)adapter->session_id,
lifeng907edd62017-05-12 10:10:36 +08006995 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
6996 ant_div_usrcfg, PDEV_CMD);
6997 if (ret_val) {
6998 hdd_err("Failed to set ant snr diff");
6999 return ret_val;
7000 }
7001 }
7002
7003 if (tb[ANT_DIV_PROBE_DWELL_TIME]) {
7004 ant_div_usrcfg = ANT_DIV_SET_PROBE_DWELL_TIME(
7005 nla_get_u32(tb[ANT_DIV_PROBE_DWELL_TIME]));
7006 hdd_debug("ant div set probe dewll time: %x",
7007 ant_div_usrcfg);
Jeff Johnson1b780e42017-10-31 14:11:45 -07007008 ret_val = wma_cli_set_command((int)adapter->session_id,
lifeng907edd62017-05-12 10:10:36 +08007009 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
7010 ant_div_usrcfg, PDEV_CMD);
7011 if (ret_val) {
7012 hdd_err("Failed to set ant div probe dewll time");
7013 return ret_val;
7014 }
7015 }
7016
7017 if (tb[ANT_DIV_MGMT_SNR_WEIGHT] ||
7018 tb[ANT_DIV_DATA_SNR_WEIGHT] ||
7019 tb[ANT_DIV_ACK_SNR_WEIGHT]) {
7020
7021 if (!tb[ANT_DIV_MGMT_SNR_WEIGHT] ||
7022 !tb[ANT_DIV_DATA_SNR_WEIGHT] ||
7023 !tb[ANT_DIV_ACK_SNR_WEIGHT]) {
7024 hdd_err("Mgmt snr, data snr and ack snr weight are required");
7025 return -EINVAL;
7026 }
7027
7028 ant_div_usrcfg = ANT_DIV_SET_WEIGHT(
7029 nla_get_u32(tb[ANT_DIV_MGMT_SNR_WEIGHT]),
7030 nla_get_u32(tb[ANT_DIV_DATA_SNR_WEIGHT]),
7031 nla_get_u32(tb[ANT_DIV_ACK_SNR_WEIGHT]));
7032 hdd_debug("ant div set weight: %x", ant_div_usrcfg);
Jeff Johnson1b780e42017-10-31 14:11:45 -07007033 ret_val = wma_cli_set_command((int)adapter->session_id,
lifeng907edd62017-05-12 10:10:36 +08007034 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
7035 ant_div_usrcfg, PDEV_CMD);
7036 if (ret_val) {
7037 hdd_err("Failed to set ant div weight");
7038 return ret_val;
7039 }
7040 }
7041
Ajit Pal Singh747b6802017-05-24 15:42:03 +05307042 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL]) {
7043 u8 restrict_offchan = nla_get_u8(
7044 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL]);
7045
7046 hdd_debug("Restrict offchannel:%d", restrict_offchan);
7047 if (restrict_offchan <= 1)
7048 ret_val =
7049 wlan_hdd_handle_restrict_offchan_config(adapter,
7050 restrict_offchan);
7051 else {
7052 ret_val = -EINVAL;
7053 hdd_err("Invalid RESTRICT_OFFCHAN setting");
7054 }
7055 }
lifeng66831662017-05-19 16:01:35 +08007056
7057 ret_val =
7058 wlan_hdd_cfg80211_wifi_set_reorder_timeout(hdd_ctx, tb);
7059 if (ret_val != 0)
7060 return ret_val;
7061
7062 ret_val =
7063 wlan_hdd_cfg80211_wifi_set_rx_blocksize(hdd_ctx, adapter, tb);
7064 if (ret_val != 0)
7065 return ret_val;
7066
lifengd217d192017-05-09 19:44:16 +08007067 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA]) {
7068 antdiv_enable = nla_get_u32(
7069 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA]);
7070 hdd_debug("antdiv_enable: %d", antdiv_enable);
Jeff Johnson1b780e42017-10-31 14:11:45 -07007071 ret_val = wma_cli_set_command((int)adapter->session_id,
lifengd217d192017-05-09 19:44:16 +08007072 (int)WMI_PDEV_PARAM_ENA_ANT_DIV,
7073 antdiv_enable, PDEV_CMD);
7074 if (ret_val) {
7075 hdd_err("Failed to set antdiv_enable");
7076 return ret_val;
7077 }
7078 }
7079
7080 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN]) {
7081 antdiv_chain = nla_get_u32(
7082 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN]);
7083 hdd_debug("antdiv_chain: %d", antdiv_chain);
Jeff Johnson1b780e42017-10-31 14:11:45 -07007084 ret_val = wma_cli_set_command((int)adapter->session_id,
lifengd217d192017-05-09 19:44:16 +08007085 (int)WMI_PDEV_PARAM_FORCE_CHAIN_ANT,
7086 antdiv_chain, PDEV_CMD);
7087 if (ret_val) {
7088 hdd_err("Failed to set antdiv_chain");
7089 return ret_val;
7090 }
7091 }
7092
7093 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST]) {
7094 antdiv_selftest = nla_get_u32(
7095 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST]);
7096 hdd_debug("antdiv_selftest: %d", antdiv_selftest);
Jeff Johnson1b780e42017-10-31 14:11:45 -07007097 ret_val = wma_cli_set_command((int)adapter->session_id,
lifengd217d192017-05-09 19:44:16 +08007098 (int)WMI_PDEV_PARAM_ANT_DIV_SELFTEST,
7099 antdiv_selftest, PDEV_CMD);
7100 if (ret_val) {
7101 hdd_err("Failed to set antdiv_selftest");
7102 return ret_val;
7103 }
7104 }
7105
7106 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL]) {
7107 antdiv_selftest_intvl = nla_get_u32(
7108 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL]);
7109 hdd_debug("antdiv_selftest_intvl: %d",
7110 antdiv_selftest_intvl);
Jeff Johnson1b780e42017-10-31 14:11:45 -07007111 ret_val = wma_cli_set_command((int)adapter->session_id,
lifengd217d192017-05-09 19:44:16 +08007112 (int)WMI_PDEV_PARAM_ANT_DIV_SELFTEST_INTVL,
7113 antdiv_selftest_intvl, PDEV_CMD);
7114 if (ret_val) {
7115 hdd_err("Failed to set antdiv_selftest_intvl");
7116 return ret_val;
7117 }
7118 }
7119
Nachiket Kukadeaaf8a712017-07-27 19:15:36 +05307120 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT]) {
7121 bmiss_bcnt = nla_get_u8(
7122 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT]);
7123 if (hdd_ctx->config->nRoamBmissFirstBcnt < bmiss_bcnt) {
7124 hdd_ctx->config->nRoamBmissFinalBcnt = bmiss_bcnt
7125 - hdd_ctx->config->nRoamBmissFirstBcnt;
7126 hdd_debug("Bmiss first cnt(%d), Bmiss final cnt(%d)",
7127 hdd_ctx->config->nRoamBmissFirstBcnt,
7128 hdd_ctx->config->nRoamBmissFinalBcnt);
7129 ret_val = sme_set_roam_bmiss_final_bcnt(hdd_ctx->hHal,
7130 0, hdd_ctx->config->nRoamBmissFinalBcnt);
7131
7132 if (ret_val) {
7133 hdd_err("Failed to set bmiss final Bcnt");
7134 return ret_val;
7135 }
7136
Jeff Johnson1b780e42017-10-31 14:11:45 -07007137 ret_val = sme_set_bmiss_bcnt(adapter->session_id,
Nachiket Kukadeaaf8a712017-07-27 19:15:36 +05307138 hdd_ctx->config->nRoamBmissFirstBcnt,
7139 hdd_ctx->config->nRoamBmissFinalBcnt);
7140 if (ret_val) {
7141 hdd_err("Failed to set bmiss Bcnt");
7142 return ret_val;
7143 }
7144 } else {
7145 hdd_err("Bcnt(%d) needs to exceed BmissFirstBcnt(%d)",
7146 bmiss_bcnt,
7147 hdd_ctx->config->nRoamBmissFirstBcnt);
7148 return -EINVAL;
7149 }
7150 }
Paul Zhang99fe8842017-12-08 14:43:46 +08007151
7152 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL]) {
7153 latency_level = nla_get_u16(
7154 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL]);
7155
7156 if ((latency_level >
7157 QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MAX) ||
7158 (latency_level ==
7159 QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_INVALID)) {
7160 hdd_err("Invalid Wlan latency level value");
7161 return -EINVAL;
7162 }
7163
7164 /* Mapping the latency value to the level which fw expected
7165 * 0 - normal, 1 - moderate, 2 - low, 3 - ultralow
7166 */
7167 latency_level = latency_level - 1;
7168 qdf_status = sme_set_wlm_latency_level(hdd_ctx->hHal,
7169 adapter->session_id,
7170 latency_level);
7171 if (qdf_status != QDF_STATUS_SUCCESS) {
7172 hdd_err("set Wlan latency level failed");
7173 ret_val = -EINVAL;
7174 }
7175 }
7176
Vignesh Viswanathan32761e42017-09-25 17:10:54 +05307177 if (adapter->device_mode == QDF_STA_MODE &&
7178 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_DISABLE_FILS]) {
7179 uint8_t disable_fils;
7180
7181 disable_fils = nla_get_u8(tb[
7182 QCA_WLAN_VENDOR_ATTR_CONFIG_DISABLE_FILS]);
7183 hdd_debug("Set disable_fils - %d", disable_fils);
7184
7185 qdf_status = sme_update_fils_setting(hdd_ctx->hHal,
7186 adapter->session_id,
7187 disable_fils);
7188 if (qdf_status != QDF_STATUS_SUCCESS) {
7189 hdd_err("set disable_fils failed");
7190 ret_val = -EINVAL;
7191 }
7192 }
Nachiket Kukadeaaf8a712017-07-27 19:15:36 +05307193
Abhishek Singh6454ad32017-12-20 10:42:21 +05307194 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE] &&
7195 hdd_ctx->config->force_rsne_override) {
7196 uint8_t force_rsne_override;
7197
7198 force_rsne_override =
7199 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE]);
7200 if (force_rsne_override > 1) {
7201 hdd_err("Invalid test_mode %d", force_rsne_override);
7202 ret_val = -EINVAL;
7203 }
7204
7205 hdd_ctx->force_rsne_override = force_rsne_override;
7206 hdd_debug("force_rsne_override - %d",
7207 hdd_ctx->force_rsne_override);
7208 }
7209
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007210 return ret_val;
7211}
7212
7213/**
7214 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
7215 * vendor command
7216 *
7217 * @wiphy: wiphy device pointer
7218 * @wdev: wireless device pointer
7219 * @data: Vendor command data buffer
7220 * @data_len: Buffer length
7221 *
7222 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
7223 *
7224 * Return: EOK or other error codes.
7225 */
7226static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
7227 struct wireless_dev *wdev,
7228 const void *data,
7229 int data_len)
7230{
7231 int ret;
7232
7233 cds_ssr_protect(__func__);
7234 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
7235 data, data_len);
7236 cds_ssr_unprotect(__func__);
7237
7238 return ret;
7239}
7240
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007241/**
7242 * __wlan_hdd_cfg80211_set_wifi_test_config() - Wifi test configuration
7243 * vendor command
7244 *
7245 * @wiphy: wiphy device pointer
7246 * @wdev: wireless device pointer
7247 * @data: Vendor command data buffer
7248 * @data_len: Buffer length
7249 *
7250 * Handles QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX
7251 *
7252 * Return: Error code.
7253 */
7254static int
7255__wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
7256 struct wireless_dev *wdev, const void *data, int data_len) {
7257
7258 struct net_device *dev = wdev->netdev;
7259 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7260 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
7261 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX + 1];
7262 int ret_val = 0;
7263 uint8_t cfg_val = 0;
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08007264 uint8_t set_val = 0;
Krunal Soni707eb782018-01-18 12:04:19 -08007265 tSmeConfigParams *sme_config;
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08007266 bool update_sme_cfg = false;
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08007267 uint8_t tid = 0, ac;
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007268 uint16_t buff_size = 0;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007269
Dustin Brownfdf17c12018-03-14 12:55:34 -07007270 hdd_enter_dev(dev);
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007271
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08007272 sme_config = qdf_mem_malloc(sizeof(*sme_config));
7273 if (!sme_config) {
7274 hdd_err("mem alloc failed for sme_config");
7275 return -ENOMEM;
7276 }
7277 sme_get_config_param(hdd_ctx->hHal, sme_config);
7278
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007279 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7280 hdd_err("Command not allowed in FTM mode");
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007281 ret_val = -EPERM;
7282 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007283 }
7284
7285 ret_val = wlan_hdd_validate_context(hdd_ctx);
7286 if (ret_val)
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007287 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007288
7289 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
7290 hdd_err("Driver Modules are closed, can not start logger");
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007291 ret_val = -EINVAL;
7292 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007293 }
7294
7295 if (wlan_cfg80211_nla_parse(tb,
7296 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX,
7297 data, data_len, wlan_hdd_wifi_test_config_policy)) {
7298 hdd_err("invalid attr");
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007299 ret_val = -EINVAL;
7300 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007301 }
7302
7303 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ]) {
7304 cfg_val = nla_get_u8(tb[
7305 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ]
7306 );
7307 hdd_debug("set addba accept req from peer value %d", cfg_val);
7308 ret_val = sme_set_addba_accept(hdd_ctx->hHal,
7309 adapter->session_id, cfg_val);
7310 if (ret_val)
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007311 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007312 }
7313
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08007314 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS]) {
7315 cfg_val = nla_get_u8(tb[
7316 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS]);
7317 hdd_debug("set HE MCS value 0x%0X", cfg_val);
7318 ret_val = sme_update_he_mcs(hdd_ctx->hHal, adapter->session_id,
7319 cfg_val);
7320 if (ret_val)
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007321 goto send_err;
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08007322 }
7323
Krunal Soni707eb782018-01-18 12:04:19 -08007324 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE]) {
7325 cfg_val = nla_get_u8(tb[
7326 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE]);
Krunal Soni707eb782018-01-18 12:04:19 -08007327 if (!cfg_val) {
7328 sme_config->csrConfig.WMMSupportMode =
7329 hdd_to_csr_wmm_mode(HDD_WMM_USER_MODE_NO_QOS);
7330 hdd_debug("wmm is disabled");
7331 } else {
7332 sme_config->csrConfig.WMMSupportMode =
7333 hdd_to_csr_wmm_mode(hdd_ctx->config->WmmMode);
7334 hdd_debug("using wmm default value");
7335 }
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08007336 update_sme_cfg = true;
Krunal Soni707eb782018-01-18 12:04:19 -08007337 }
7338
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08007339 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ]) {
7340 cfg_val = nla_get_u8(tb[
7341 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ]);
7342 if (cfg_val) {
7343 /*Auto BA mode*/
7344 set_val = 0;
7345 hdd_debug("BA operating mode is set to auto");
7346 } else {
7347 /*Manual BA mode*/
7348 set_val = 1;
7349 hdd_debug("BA operating mode is set to Manual");
7350 }
7351
7352 ret_val = wma_cli_set_command(adapter->session_id,
7353 WMI_VDEV_PARAM_BA_MODE, set_val, VDEV_CMD);
Kiran Kumar Lokere015f77f2018-04-24 18:25:28 -07007354 if (ret_val) {
7355 hdd_err("Set BA operating mode failed");
7356 goto send_err;
7357 }
7358 if (!cfg_val) {
7359 ret_val = wma_cli_set_command(adapter->session_id,
7360 WMI_VDEV_PARAM_AMSDU_AGGREGATION_SIZE_OPTIMIZATION,
7361 0, VDEV_CMD);
7362 }
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08007363 }
7364
Kiran Kumar Lokere5cc2f0d2018-02-08 17:10:05 -08007365 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION]) {
7366 cfg_val = nla_get_u8(tb[
7367 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION]
7368 );
7369 if (cfg_val > HE_FRAG_LEVEL1)
7370 set_val = HE_FRAG_LEVEL1;
7371 else
7372 set_val = cfg_val;
7373
7374 hdd_debug("set HE fragmention to %d", set_val);
7375 ret_val = sme_update_he_frag_supp(hdd_ctx->hHal,
7376 adapter->session_id, set_val);
7377 }
7378
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08007379 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE]) {
7380 cfg_val = nla_get_u8(tb[
7381 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE]);
7382 sme_config->csrConfig.wep_tkip_in_he = cfg_val;
7383 hdd_debug("Set WEP/TKIP allow in HE %d", cfg_val);
7384
7385 update_sme_cfg = true;
7386 }
7387
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007388 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION]) {
7389 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID]) {
7390 tid = nla_get_u8(tb[
7391 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID]);
7392 } else {
7393 hdd_err("TID is not set for ADD/DEL BA cfg");
7394 ret_val = -EINVAL;
7395 goto send_err;
7396 }
7397 cfg_val = nla_get_u8(tb[
7398 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION]);
7399 if (cfg_val == QCA_WLAN_ADD_BA) {
7400 if (tb[
7401 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE])
7402 buff_size = nla_get_u8(tb[
7403 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]);
7404 ret_val = sme_send_addba_req(hdd_ctx->hHal,
7405 adapter->session_id, tid, buff_size);
7406 } else if (cfg_val == QCA_WLAN_DELETE_BA) {
7407 } else {
7408 hdd_err("Invalid BA session cfg");
7409 ret_val = -EINVAL;
7410 goto send_err;
7411 }
7412 } else if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]) {
7413 buff_size = nla_get_u8(tb[
7414 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]);
7415 hdd_debug("set buff size to %d for all tids", buff_size);
7416 ret_val = sme_set_ba_buff_size(hdd_ctx->hHal,
7417 adapter->session_id, buff_size);
7418 if (ret_val)
7419 goto send_err;
7420 if (buff_size > 64)
7421 /* Configure ADDBA req buffer size to 256 */
7422 set_val = 3;
7423 else
7424 /* Configure ADDBA req buffer size to 64 */
7425 set_val = 2;
7426 ret_val = wma_cli_set_command(adapter->session_id,
7427 WMI_VDEV_PARAM_BA_MODE, set_val, VDEV_CMD);
7428 }
7429
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08007430 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK]) {
Kiran Kumar Lokere30313a32018-04-30 18:20:06 -07007431 int he_mcs_val;
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08007432 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC]) {
7433 ac = nla_get_u8(tb[
7434 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC]);
7435 } else {
7436 hdd_err("AC is not set for NO ACK policy config");
7437 ret_val = -EINVAL;
7438 goto send_err;
7439 }
7440 cfg_val = nla_get_u8(tb[
7441 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK]);
7442 hdd_debug("Set NO_ACK to %d for ac %d", cfg_val, ac);
7443 ret_val = sme_set_no_ack_policy(hdd_ctx->hHal,
7444 adapter->session_id, cfg_val, ac);
Kiran Kumar Lokere30313a32018-04-30 18:20:06 -07007445 if (cfg_val) {
7446 if (sme_config->csrConfig.enable2x2)
7447 /*2x2 MCS 5 value*/
7448 he_mcs_val = 0x45;
7449 else
7450 /*1x1 MCS 5 value*/
7451 he_mcs_val = 0x25;
7452
7453 if (hdd_set_11ax_rate(adapter, he_mcs_val, NULL))
7454 hdd_err("HE MCS set failed, MCS val %0x",
7455 he_mcs_val);
7456 } else {
7457 if (hdd_set_11ax_rate(adapter, 0xFF, NULL))
7458 hdd_err("disable fixed rate failed");
7459 }
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08007460 }
7461
Kiran Kumar Lokerea006a302018-03-07 20:58:13 -08007462 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF]) {
7463 cfg_val = nla_get_u8(tb[
7464 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF]);
7465 hdd_debug("Set HE LTF to %d", cfg_val);
7466 ret_val = sme_set_auto_rate_he_ltf(hdd_ctx->hHal,
7467 adapter->session_id,
7468 cfg_val);
7469 if (ret_val)
7470 sme_err("Failed to set auto rate HE LTF");
7471
7472 ret_val = wma_cli_set_command(adapter->session_id,
7473 WMI_VDEV_PARAM_HE_LTF,
7474 cfg_val, VDEV_CMD);
7475 if (ret_val)
7476 goto send_err;
7477 }
7478
Kiran Kumar Lokere6c7f3fa2018-05-14 18:12:27 -07007479 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE]) {
7480 cfg_val = nla_get_u8(tb[
7481 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE]);
7482 hdd_debug("Set Tx beamformee to %d", cfg_val);
7483 ret_val = sme_update_tx_bfee_supp(hdd_ctx->hHal,
7484 adapter->session_id,
7485 cfg_val);
7486 if (ret_val)
7487 sme_err("Failed to set Tx beamformee cap");
7488
7489 }
7490
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08007491 if (update_sme_cfg)
7492 sme_update_config(hdd_ctx->hHal, sme_config);
7493
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007494send_err:
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08007495 qdf_mem_free(sme_config);
7496
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007497 return ret_val;
7498}
7499
7500/**
7501 * wlan_hdd_cfg80211_set_wifi_test_config() - Wifi test configuration
7502 * vendor command
7503 *
7504 * @wiphy: wiphy device pointer
7505 * @wdev: wireless device pointer
7506 * @data: Vendor command data buffer
7507 * @data_len: Buffer length
7508 *
7509 * Handles QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX
7510 *
7511 * Return: EOK or other error codes.
7512 */
7513static int wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
7514 struct wireless_dev *wdev, const void *data, int data_len)
7515{
7516 int ret;
7517
7518 cds_ssr_protect(__func__);
7519 ret = __wlan_hdd_cfg80211_set_wifi_test_config(wiphy, wdev,
7520 data, data_len);
7521 cds_ssr_unprotect(__func__);
7522
7523 return ret;
7524}
7525
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007526static const struct
7527nla_policy
7528qca_wlan_vendor_wifi_logger_start_policy
7529[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
7530 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
7531 = {.type = NLA_U32 },
7532 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
7533 = {.type = NLA_U32 },
7534 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
7535 = {.type = NLA_U32 },
7536};
7537
7538/**
7539 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
7540 * or disable the collection of packet statistics from the firmware
7541 * @wiphy: WIPHY structure pointer
7542 * @wdev: Wireless device structure pointer
7543 * @data: Pointer to the data received
7544 * @data_len: Length of the data received
7545 *
7546 * This function enables or disables the collection of packet statistics from
7547 * the firmware
7548 *
7549 * Return: 0 on success and errno on failure
7550 */
7551static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
7552 struct wireless_dev *wdev,
7553 const void *data,
7554 int data_len)
7555{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307556 QDF_STATUS status;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07007557 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007558 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
7559 struct sir_wifi_start_log start_log;
7560
Dustin Brownfdf17c12018-03-14 12:55:34 -07007561 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08007562
Anurag Chouhan6d760662016-02-20 16:05:43 +05307563 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007564 hdd_err("Command not allowed in FTM mode");
7565 return -EPERM;
7566 }
7567
7568 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05307569 if (status)
7570 return status;
7571
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05307572 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
7573 hdd_err("Driver Modules are closed, can not start logger");
7574 return -EINVAL;
7575 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007576
Dustin Brown4ea21db2018-01-05 14:13:17 -08007577 if (wlan_cfg80211_nla_parse(tb,
7578 QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
7579 data, data_len,
7580 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007581 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007582 return -EINVAL;
7583 }
7584
7585 /* Parse and fetch ring id */
7586 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007587 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007588 return -EINVAL;
7589 }
7590 start_log.ring_id = nla_get_u32(
7591 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007592 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007593
7594 /* Parse and fetch verbose level */
7595 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007596 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007597 return -EINVAL;
7598 }
7599 start_log.verbose_level = nla_get_u32(
7600 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007601 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007602
7603 /* Parse and fetch flag */
7604 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007605 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007606 return -EINVAL;
7607 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05307608 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007609 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007610
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307611 /* size is buff size which can be set using iwpriv command*/
7612 start_log.size = 0;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05307613 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307614
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007615 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
7616
7617 if (start_log.ring_id == RING_ID_WAKELOCK) {
7618 /* Start/stop wakelock events */
7619 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
7620 cds_set_wakelock_logging(true);
7621 else
7622 cds_set_wakelock_logging(false);
7623 return 0;
7624 }
7625
7626 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307627 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007628 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007629 status);
7630 return -EINVAL;
7631 }
7632 return 0;
7633}
7634
7635/**
7636 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
7637 * or disable the collection of packet statistics from the firmware
7638 * @wiphy: WIPHY structure pointer
7639 * @wdev: Wireless device structure pointer
7640 * @data: Pointer to the data received
7641 * @data_len: Length of the data received
7642 *
7643 * This function is used to enable or disable the collection of packet
7644 * statistics from the firmware
7645 *
7646 * Return: 0 on success and errno on failure
7647 */
7648static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
7649 struct wireless_dev *wdev,
7650 const void *data,
7651 int data_len)
7652{
7653 int ret = 0;
7654
7655 cds_ssr_protect(__func__);
7656 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
7657 wdev, data, data_len);
7658 cds_ssr_unprotect(__func__);
7659
7660 return ret;
7661}
7662
7663static const struct
7664nla_policy
7665qca_wlan_vendor_wifi_logger_get_ring_data_policy
7666[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
7667 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
7668 = {.type = NLA_U32 },
7669};
7670
7671/**
7672 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
7673 * @wiphy: WIPHY structure pointer
7674 * @wdev: Wireless device structure pointer
7675 * @data: Pointer to the data received
7676 * @data_len: Length of the data received
7677 *
7678 * This function is used to flush or retrieve the per packet statistics from
7679 * the driver
7680 *
7681 * Return: 0 on success and errno on failure
7682 */
7683static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
7684 struct wireless_dev *wdev,
7685 const void *data,
7686 int data_len)
7687{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307688 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007689 uint32_t ring_id;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07007690 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007691 struct nlattr *tb
7692 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
7693
Dustin Brownfdf17c12018-03-14 12:55:34 -07007694 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08007695
Anurag Chouhan6d760662016-02-20 16:05:43 +05307696 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007697 hdd_err("Command not allowed in FTM mode");
7698 return -EPERM;
7699 }
7700
7701 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05307702 if (status)
7703 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007704
Dustin Brown4ea21db2018-01-05 14:13:17 -08007705 if (wlan_cfg80211_nla_parse(tb,
7706 QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
7707 data, data_len,
7708 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007709 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007710 return -EINVAL;
7711 }
7712
7713 /* Parse and fetch ring id */
7714 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007715 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007716 return -EINVAL;
7717 }
7718
7719 ring_id = nla_get_u32(
7720 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
7721
7722 if (ring_id == RING_ID_PER_PACKET_STATS) {
7723 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007724 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05307725 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
7726 /*
7727 * As part of DRIVER ring ID, flush both driver and fw logs.
7728 * For other Ring ID's driver doesn't have any rings to flush
7729 */
Dustin Brown5e89ef82018-03-14 11:50:23 -07007730 hdd_info("Bug report triggered by framework");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05307731
7732 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
7733 WLAN_LOG_INDICATOR_FRAMEWORK,
7734 WLAN_LOG_REASON_CODE_UNUSED,
7735 true, false);
7736 if (QDF_STATUS_SUCCESS != status) {
7737 hdd_err("Failed to trigger bug report");
7738 return -EINVAL;
7739 }
7740 } else {
7741 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
7742 WLAN_LOG_INDICATOR_FRAMEWORK,
Agrawal Ashishaff28982017-05-30 15:25:47 +05307743 WLAN_LOG_REASON_CODE_UNUSED,
7744 ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007745 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007746 return 0;
7747}
7748
7749/**
7750 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
7751 * @wiphy: WIPHY structure pointer
7752 * @wdev: Wireless device structure pointer
7753 * @data: Pointer to the data received
7754 * @data_len: Length of the data received
7755 *
7756 * This function is used to flush or retrieve the per packet statistics from
7757 * the driver
7758 *
7759 * Return: 0 on success and errno on failure
7760 */
7761static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
7762 struct wireless_dev *wdev,
7763 const void *data,
7764 int data_len)
7765{
7766 int ret = 0;
7767
7768 cds_ssr_protect(__func__);
7769 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
7770 wdev, data, data_len);
7771 cds_ssr_unprotect(__func__);
7772
7773 return ret;
7774}
7775
7776#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
7777/**
7778 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
7779 * @hdd_ctx: HDD context
7780 * @request_id: [input] request id
7781 * @pattern_id: [output] pattern id
7782 *
7783 * This function loops through request id to pattern id array
7784 * if the slot is available, store the request id and return pattern id
7785 * if entry exists, return the pattern id
7786 *
7787 * Return: 0 on success and errno on failure
7788 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07007789static int hdd_map_req_id_to_pattern_id(struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007790 uint32_t request_id,
7791 uint8_t *pattern_id)
7792{
7793 uint32_t i;
7794
7795 mutex_lock(&hdd_ctx->op_ctx.op_lock);
7796 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
7797 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
7798 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
7799 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
7800 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
7801 return 0;
7802 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
7803 request_id) {
7804 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
7805 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
7806 return 0;
7807 }
7808 }
7809 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
7810 return -EINVAL;
7811}
7812
7813/**
7814 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
7815 * @hdd_ctx: HDD context
7816 * @request_id: [input] request id
7817 * @pattern_id: [output] pattern id
7818 *
7819 * This function loops through request id to pattern id array
7820 * reset request id to 0 (slot available again) and
7821 * return pattern id
7822 *
7823 * Return: 0 on success and errno on failure
7824 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07007825static int hdd_unmap_req_id_to_pattern_id(struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007826 uint32_t request_id,
7827 uint8_t *pattern_id)
7828{
7829 uint32_t i;
7830
7831 mutex_lock(&hdd_ctx->op_ctx.op_lock);
7832 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
7833 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
7834 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
7835 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
7836 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
7837 return 0;
7838 }
7839 }
7840 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
7841 return -EINVAL;
7842}
7843
7844
7845/*
7846 * define short names for the global vendor params
7847 * used by __wlan_hdd_cfg80211_offloaded_packets()
7848 */
7849#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
7850#define PARAM_REQUEST_ID \
7851 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
7852#define PARAM_CONTROL \
7853 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
7854#define PARAM_IP_PACKET \
7855 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
7856#define PARAM_SRC_MAC_ADDR \
7857 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
7858#define PARAM_DST_MAC_ADDR \
7859 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
7860#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
7861
7862/**
7863 * wlan_hdd_add_tx_ptrn() - add tx pattern
7864 * @adapter: adapter pointer
7865 * @hdd_ctx: hdd context
7866 * @tb: nl attributes
7867 *
7868 * This function reads the NL attributes and forms a AddTxPtrn message
7869 * posts it to SME.
7870 *
7871 */
7872static int
Jeff Johnsone5006672017-08-29 14:39:02 -07007873wlan_hdd_add_tx_ptrn(struct hdd_adapter *adapter, struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007874 struct nlattr **tb)
7875{
7876 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307877 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007878 uint32_t request_id, ret, len;
7879 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05307880 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007881 uint16_t eth_type = htons(ETH_P_IP);
7882
7883 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07007884 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007885 return -ENOTSUPP;
7886 }
7887
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307888 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007889 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07007890 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007891 return -ENOMEM;
7892 }
7893
7894 /* Parse and fetch request Id */
7895 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007896 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007897 goto fail;
7898 }
7899
7900 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
7901 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07007902 hdd_err("request_id cannot be MAX");
SaidiReddy Yenuga466b3ce2017-05-02 18:50:25 +05307903 goto fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007904 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007905 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007906
7907 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007908 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007909 goto fail;
7910 }
7911 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007912 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007913 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07007914 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007915 goto fail;
7916 }
7917
7918 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007919 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007920 goto fail;
7921 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08007922 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05307923 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007924 hdd_debug("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08007925 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007926
Anurag Chouhanc5548422016-02-24 18:33:27 +05307927 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Jeff Johnson1e851a12017-10-28 14:36:12 -07007928 &adapter->mac_addr)) {
Srinivas Girigowda31896552015-11-18 22:59:52 -08007929 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007930 goto fail;
7931 }
7932
7933 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007934 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007935 goto fail;
7936 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05307937 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007938 hdd_debug("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007939 MAC_ADDR_ARRAY(dst_addr.bytes));
7940
7941 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007942 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007943 goto fail;
7944 }
7945 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007946 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007947
7948 if (add_req->ucPtrnSize < 0 ||
7949 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
7950 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007951 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007952 add_req->ucPtrnSize);
7953 goto fail;
7954 }
7955
7956 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307957 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05307958 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307959 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307960 QDF_MAC_ADDR_SIZE);
7961 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307962 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007963 len += 2;
7964
7965 /*
7966 * This is the IP packet, add 14 bytes Ethernet (802.3) header
7967 * ------------------------------------------------------------
7968 * | 14 bytes Ethernet (802.3) header | IP header and payload |
7969 * ------------------------------------------------------------
7970 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307971 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007972 nla_data(tb[PARAM_IP_PACKET]),
7973 add_req->ucPtrnSize);
7974 add_req->ucPtrnSize += len;
7975
7976 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
7977 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007978 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007979 goto fail;
7980 }
7981 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007982 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007983
7984 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307985 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007986 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007987 goto fail;
7988 }
7989
Dustin Browne74003f2018-03-14 12:51:58 -07007990 hdd_exit();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307991 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007992 return 0;
7993
7994fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307995 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007996 return -EINVAL;
7997}
7998
7999/**
8000 * wlan_hdd_del_tx_ptrn() - delete tx pattern
8001 * @adapter: adapter pointer
8002 * @hdd_ctx: hdd context
8003 * @tb: nl attributes
8004 *
8005 * This function reads the NL attributes and forms a DelTxPtrn message
8006 * posts it to SME.
8007 *
8008 */
8009static int
Jeff Johnsone5006672017-08-29 14:39:02 -07008010wlan_hdd_del_tx_ptrn(struct hdd_adapter *adapter, struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008011 struct nlattr **tb)
8012{
8013 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308014 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008015 uint32_t request_id, ret;
8016 uint8_t pattern_id = 0;
8017
8018 /* Parse and fetch request Id */
8019 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07008020 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008021 return -EINVAL;
8022 }
8023 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
8024 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07008025 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008026 return -EINVAL;
8027 }
8028
8029 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
8030 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008031 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008032 return -EINVAL;
8033 }
8034
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308035 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008036 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07008037 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008038 return -ENOMEM;
8039 }
8040
Jeff Johnson1e851a12017-10-28 14:36:12 -07008041 qdf_copy_macaddr(&del_req->mac_address, &adapter->mac_addr);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008042 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008043 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008044 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008045 request_id, del_req->ucPtrnId);
8046
8047 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308048 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008049 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008050 goto fail;
8051 }
8052
Dustin Browne74003f2018-03-14 12:51:58 -07008053 hdd_exit();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308054 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008055 return 0;
8056
8057fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308058 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008059 return -EINVAL;
8060}
8061
8062
8063/**
8064 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
8065 * @wiphy: Pointer to wireless phy
8066 * @wdev: Pointer to wireless device
8067 * @data: Pointer to data
8068 * @data_len: Data length
8069 *
8070 * Return: 0 on success, negative errno on failure
8071 */
8072static int
8073__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
8074 struct wireless_dev *wdev,
8075 const void *data,
8076 int data_len)
8077{
8078 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07008079 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008080 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008081 struct nlattr *tb[PARAM_MAX + 1];
8082 uint8_t control;
8083 int ret;
8084 static const struct nla_policy policy[PARAM_MAX + 1] = {
8085 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
8086 [PARAM_CONTROL] = { .type = NLA_U32 },
8087 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05308088 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008089 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05308090 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008091 [PARAM_PERIOD] = { .type = NLA_U32 },
8092 };
8093
Dustin Brownfdf17c12018-03-14 12:55:34 -07008094 hdd_enter_dev(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008095
Anurag Chouhan6d760662016-02-20 16:05:43 +05308096 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008097 hdd_err("Command not allowed in FTM mode");
8098 return -EPERM;
8099 }
8100
8101 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308102 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008103 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008104
8105 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008106 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008107 return -ENOTSUPP;
8108 }
8109
Dustin Brown4ea21db2018-01-05 14:13:17 -08008110 if (wlan_cfg80211_nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008111 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008112 return -EINVAL;
8113 }
8114
8115 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07008116 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008117 return -EINVAL;
8118 }
8119 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008120 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008121
8122 if (control == WLAN_START_OFFLOADED_PACKETS)
8123 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08008124 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008125 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08008126
8127 hdd_err("Invalid control: %d", control);
Jeff Johnson68755312017-02-10 11:46:55 -08008128 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008129}
8130
8131/*
8132 * done with short names for the global vendor params
8133 * used by __wlan_hdd_cfg80211_offloaded_packets()
8134 */
8135#undef PARAM_MAX
8136#undef PARAM_REQUEST_ID
8137#undef PARAM_CONTROL
8138#undef PARAM_IP_PACKET
8139#undef PARAM_SRC_MAC_ADDR
8140#undef PARAM_DST_MAC_ADDR
8141#undef PARAM_PERIOD
8142
8143/**
8144 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
8145 * @wiphy: wiphy structure pointer
8146 * @wdev: Wireless device structure pointer
8147 * @data: Pointer to the data received
8148 * @data_len: Length of @data
8149 *
8150 * Return: 0 on success; errno on failure
8151 */
8152static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
8153 struct wireless_dev *wdev,
8154 const void *data,
8155 int data_len)
8156{
8157 int ret = 0;
8158
8159 cds_ssr_protect(__func__);
8160 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
8161 wdev, data, data_len);
8162 cds_ssr_unprotect(__func__);
8163
8164 return ret;
8165}
8166#endif
8167
8168/*
8169 * define short names for the global vendor params
8170 * used by __wlan_hdd_cfg80211_monitor_rssi()
8171 */
8172#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
8173#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
8174#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
8175#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
8176#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
8177
8178/**
8179 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
8180 * @wiphy: Pointer to wireless phy
8181 * @wdev: Pointer to wireless device
8182 * @data: Pointer to data
8183 * @data_len: Data length
8184 *
8185 * Return: 0 on success, negative errno on failure
8186 */
8187static int
8188__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
8189 struct wireless_dev *wdev,
8190 const void *data,
8191 int data_len)
8192{
8193 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07008194 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008195 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008196 struct nlattr *tb[PARAM_MAX + 1];
8197 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308198 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008199 int ret;
8200 uint32_t control;
8201 static const struct nla_policy policy[PARAM_MAX + 1] = {
8202 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
8203 [PARAM_CONTROL] = { .type = NLA_U32 },
8204 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
8205 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
8206 };
8207
Dustin Brownfdf17c12018-03-14 12:55:34 -07008208 hdd_enter_dev(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008209
Jeff Johnson1b780e42017-10-31 14:11:45 -07008210 if (wlan_hdd_validate_session_id(adapter->session_id)) {
8211 hdd_err("invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05308212 return -EINVAL;
8213 }
8214
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008215 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308216 if (ret)
8217 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008218
8219 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07008220 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008221 return -ENOTSUPP;
8222 }
8223
Dustin Brown4ea21db2018-01-05 14:13:17 -08008224 if (wlan_cfg80211_nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008225 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008226 return -EINVAL;
8227 }
8228
8229 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07008230 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008231 return -EINVAL;
8232 }
8233
8234 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07008235 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008236 return -EINVAL;
8237 }
8238
8239 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
Jeff Johnson1b780e42017-10-31 14:11:45 -07008240 req.session_id = adapter->session_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008241 control = nla_get_u32(tb[PARAM_CONTROL]);
8242
8243 if (control == QCA_WLAN_RSSI_MONITORING_START) {
8244 req.control = true;
8245 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07008246 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008247 return -EINVAL;
8248 }
8249
8250 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07008251 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008252 return -EINVAL;
8253 }
8254
8255 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
8256 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
8257
8258 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008259 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008260 req.min_rssi, req.max_rssi);
8261 return -EINVAL;
8262 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008263 hdd_debug("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008264 req.min_rssi, req.max_rssi);
8265
8266 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
8267 req.control = false;
8268 else {
Jeff Johnson77848112016-06-29 14:52:06 -07008269 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008270 return -EINVAL;
8271 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008272 hdd_debug("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008273 req.request_id, req.session_id, req.control);
8274
8275 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308276 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008277 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008278 return -EINVAL;
8279 }
8280
8281 return 0;
8282}
8283
8284/*
8285 * done with short names for the global vendor params
8286 * used by __wlan_hdd_cfg80211_monitor_rssi()
8287 */
8288#undef PARAM_MAX
8289#undef PARAM_CONTROL
8290#undef PARAM_REQUEST_ID
8291#undef PARAM_MAX_RSSI
8292#undef PARAM_MIN_RSSI
8293
8294/**
8295 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
8296 * @wiphy: wiphy structure pointer
8297 * @wdev: Wireless device structure pointer
8298 * @data: Pointer to the data received
8299 * @data_len: Length of @data
8300 *
8301 * Return: 0 on success; errno on failure
8302 */
8303static int
8304wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
8305 const void *data, int data_len)
8306{
8307 int ret;
8308
8309 cds_ssr_protect(__func__);
8310 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
8311 cds_ssr_unprotect(__func__);
8312
8313 return ret;
8314}
8315
8316/**
8317 * hdd_rssi_threshold_breached() - rssi breached NL event
8318 * @hddctx: HDD context
8319 * @data: rssi breached event data
8320 *
8321 * This function reads the rssi breached event %data and fill in the skb with
8322 * NL attributes and send up the NL event.
8323 *
8324 * Return: none
8325 */
8326void hdd_rssi_threshold_breached(void *hddctx,
8327 struct rssi_breach_event *data)
8328{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008329 struct hdd_context *hdd_ctx = hddctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008330 struct sk_buff *skb;
8331
Dustin Brown491d54b2018-03-14 12:39:11 -07008332 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008333
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05308334 if (wlan_hdd_validate_context(hdd_ctx))
8335 return;
8336 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07008337 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008338 return;
8339 }
8340
8341 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
8342 NULL,
8343 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
8344 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
8345 GFP_KERNEL);
8346
8347 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07008348 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008349 return;
8350 }
8351
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008352 hdd_debug("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008353 data->request_id, data->curr_rssi);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008354 hdd_debug("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008355 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
8356
8357 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
8358 data->request_id) ||
8359 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
8360 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
8361 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
8362 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008363 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008364 goto fail;
8365 }
8366
8367 cfg80211_vendor_event(skb, GFP_KERNEL);
8368 return;
8369
8370fail:
8371 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008372}
8373
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308374static const struct nla_policy
8375ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
8376 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
8377};
8378
8379/**
8380 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
8381 * @wiphy: Pointer to wireless phy
8382 * @wdev: Pointer to wireless device
8383 * @data: Pointer to data
8384 * @data_len: Length of @data
8385 *
8386 * Return: 0 on success, negative errno on failure
8387 */
8388static int
8389__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
8390 struct wireless_dev *wdev,
8391 const void *data, int data_len)
8392{
8393 int status;
8394 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
Jeff Johnsonb8944722017-09-03 09:03:19 -07008395 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07008396 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07008397 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308398
Dustin Brownfdf17c12018-03-14 12:55:34 -07008399 hdd_enter_dev(wdev->netdev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308400
Jeff Johnsonb8944722017-09-03 09:03:19 -07008401 status = wlan_hdd_validate_context(hdd_ctx);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308402 if (0 != status)
8403 return status;
Jeff Johnsonb8944722017-09-03 09:03:19 -07008404 if (!hdd_ctx->config->fhostNSOffload) {
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308405 hdd_err("ND Offload not supported");
8406 return -EINVAL;
8407 }
8408
Mukul Sharma495df602017-09-25 14:52:18 +05308409 if (!hdd_ctx->config->active_mode_offload) {
8410 hdd_warn("Active mode offload is disabled");
8411 return -EINVAL;
8412 }
8413
Dustin Brown4ea21db2018-01-05 14:13:17 -08008414 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
8415 (struct nlattr *)data, data_len,
8416 ns_offload_set_policy)) {
8417 hdd_err("nla_parse failed");
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308418 return -EINVAL;
8419 }
8420
8421 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
8422 hdd_err("ND Offload flag attribute not present");
8423 return -EINVAL;
8424 }
8425
Jeff Johnsonb8944722017-09-03 09:03:19 -07008426 hdd_ctx->ns_offload_enable =
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308427 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
8428
Nachiket Kukadedbffab82017-04-25 19:26:02 +05308429 if (QDF_IBSS_MODE == adapter->device_mode) {
8430 hdd_debug("NS Offload is not supported in IBSS mode");
8431 return -EINVAL;
8432 }
8433
Dustin Brownd8279d22016-09-07 14:52:57 -07008434 /* update ns offload in case it is already enabled/disabled */
Jeff Johnsonb8944722017-09-03 09:03:19 -07008435 if (hdd_ctx->ns_offload_enable)
Mukul Sharma3ba26b82017-01-12 21:59:41 +05308436 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
8437 else
8438 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07008439
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308440 return 0;
8441}
8442
8443/**
8444 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
8445 * @wiphy: pointer to wireless wiphy structure.
8446 * @wdev: pointer to wireless_dev structure.
8447 * @data: Pointer to the data to be passed via vendor interface
8448 * @data_len:Length of the data to be passed
8449 *
8450 * Return: Return the Success or Failure code.
8451 */
8452static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
8453 struct wireless_dev *wdev,
8454 const void *data, int data_len)
8455{
8456 int ret;
8457
8458 cds_ssr_protect(__func__);
8459 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
8460 cds_ssr_unprotect(__func__);
8461
8462 return ret;
8463}
8464
Jeff Johnsondd7bd3e2017-06-05 13:25:24 -07008465static const struct nla_policy get_preferred_freq_list_policy
8466 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1] = {
8467 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE] = {
8468 .type = NLA_U32},
8469};
8470
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008471/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
8472 * @wiphy: Pointer to wireless phy
8473 * @wdev: Pointer to wireless device
8474 * @data: Pointer to data
8475 * @data_len: Data length
8476 *
8477 * This function return the preferred frequency list generated by the policy
8478 * manager.
8479 *
8480 * Return: success or failure code
8481 */
8482static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
8483 struct wireless_dev
8484 *wdev, const void *data,
8485 int data_len)
8486{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008487 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008488 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308489 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308490 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008491 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308492 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008493 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008494 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
8495 struct sk_buff *reply_skb;
8496
Dustin Brownfdf17c12018-03-14 12:55:34 -07008497 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08008498
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008499 ret = wlan_hdd_validate_context(hdd_ctx);
8500 if (ret)
8501 return -EINVAL;
8502
Dustin Brown4ea21db2018-01-05 14:13:17 -08008503 if (wlan_cfg80211_nla_parse(tb,
8504 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
8505 data, data_len,
8506 get_preferred_freq_list_policy)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008507 hdd_err("Invalid ATTR");
8508 return -EINVAL;
8509 }
8510
8511 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
8512 hdd_err("attr interface type failed");
8513 return -EINVAL;
8514 }
8515
8516 intf_mode = nla_get_u32(tb
8517 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
8518
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008519 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008520 hdd_err("Invalid interface type");
8521 return -EINVAL;
8522 }
8523
8524 hdd_debug("Userspace requested pref freq list");
8525
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008526 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc,
8527 intf_mode, pcl, &pcl_len,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05308528 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308529 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008530 hdd_err("Get pcl failed");
8531 return -EINVAL;
8532 }
8533
8534 /* convert channel number to frequency */
8535 for (i = 0; i < pcl_len; i++) {
8536 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
8537 freq_list[i] =
8538 ieee80211_channel_to_frequency(pcl[i],
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -07008539 HDD_NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008540 else
8541 freq_list[i] =
8542 ieee80211_channel_to_frequency(pcl[i],
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -07008543 HDD_NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008544 }
8545
8546 /* send the freq_list back to supplicant */
8547 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
8548 sizeof(u32) *
8549 pcl_len +
8550 NLMSG_HDRLEN);
8551
8552 if (!reply_skb) {
8553 hdd_err("Allocate reply_skb failed");
8554 return -EINVAL;
8555 }
8556
8557 if (nla_put_u32(reply_skb,
8558 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
8559 intf_mode) ||
8560 nla_put(reply_skb,
8561 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
8562 sizeof(uint32_t) * pcl_len,
8563 freq_list)) {
8564 hdd_err("nla put fail");
8565 kfree_skb(reply_skb);
8566 return -EINVAL;
8567 }
8568
8569 return cfg80211_vendor_cmd_reply(reply_skb);
8570}
8571
8572/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
8573 * @wiphy: Pointer to wireless phy
8574 * @wdev: Pointer to wireless device
8575 * @data: Pointer to data
8576 * @data_len: Data length
8577 *
8578 * This function return the preferred frequency list generated by the policy
8579 * manager.
8580 *
8581 * Return: success or failure code
8582 */
8583static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
8584 struct wireless_dev
8585 *wdev, const void *data,
8586 int data_len)
8587{
8588 int ret = 0;
8589
8590 cds_ssr_protect(__func__);
8591 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
8592 data, data_len);
8593 cds_ssr_unprotect(__func__);
8594
8595 return ret;
8596}
8597
Jeff Johnsone5f33ba2017-06-05 14:48:48 -07008598static const struct nla_policy set_probable_oper_channel_policy
8599 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX + 1] = {
8600 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE] = {
8601 .type = NLA_U32},
8602 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ] = {
8603 .type = NLA_U32},
8604};
8605
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008606/**
8607 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
8608 * @wiphy: Pointer to wireless phy
8609 * @wdev: Pointer to wireless device
8610 * @data: Pointer to data
8611 * @data_len: Data length
8612 *
8613 * Return: 0 on success, negative errno on failure
8614 */
8615static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
8616 struct wireless_dev *wdev,
8617 const void *data,
8618 int data_len)
8619{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05308620 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07008621 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008622 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008623 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008624 enum policy_mgr_con_mode intf_mode;
Jeff Johnsone5f33ba2017-06-05 14:48:48 -07008625 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX + 1];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008626 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008627
Dustin Brownfdf17c12018-03-14 12:55:34 -07008628 hdd_enter_dev(ndev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08008629
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008630 ret = wlan_hdd_validate_context(hdd_ctx);
8631 if (ret)
8632 return ret;
8633
Dustin Brown4ea21db2018-01-05 14:13:17 -08008634 if (wlan_cfg80211_nla_parse(tb,
8635 QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
8636 data, data_len,
8637 set_probable_oper_channel_policy)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008638 hdd_err("Invalid ATTR");
8639 return -EINVAL;
8640 }
8641
8642 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
8643 hdd_err("attr interface type failed");
8644 return -EINVAL;
8645 }
8646
8647 intf_mode = nla_get_u32(tb
8648 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
8649
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008650 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008651 hdd_err("Invalid interface type");
8652 return -EINVAL;
8653 }
8654
8655 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
8656 hdd_err("attr probable freq failed");
8657 return -EINVAL;
8658 }
8659
8660 channel_hint = cds_freq_to_chan(nla_get_u32(tb
8661 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
8662
8663 /* check pcl table */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008664 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc, intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008665 channel_hint, HW_MODE_20_MHZ)) {
8666 hdd_err("Set channel hint failed due to concurrency check");
8667 return -EINVAL;
8668 }
8669
Krunal Soni09e55032016-06-07 10:06:55 -07008670 if (0 != wlan_hdd_check_remain_on_channel(adapter))
8671 hdd_warn("Remain On Channel Pending");
8672
Krunal Sonied3bc8e2018-01-26 12:13:34 -08008673 if (wlan_hdd_change_hw_mode_for_given_chnl(adapter, channel_hint,
8674 POLICY_MGR_UPDATE_REASON_SET_OPER_CHAN)) {
8675 hdd_err("Failed to change hw mode");
Krunal Soni3091bcc2016-06-23 12:28:21 -07008676 return -EINVAL;
8677 }
8678
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008679 return 0;
8680}
8681
8682/**
8683 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
8684 * @wiphy: Pointer to wireless phy
8685 * @wdev: Pointer to wireless device
8686 * @data: Pointer to data
8687 * @data_len: Data length
8688 *
8689 * Return: 0 on success, negative errno on failure
8690 */
8691static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
8692 struct wireless_dev *wdev,
8693 const void *data,
8694 int data_len)
8695{
8696 int ret = 0;
8697
8698 cds_ssr_protect(__func__);
8699 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
8700 data, data_len);
8701 cds_ssr_unprotect(__func__);
8702
8703 return ret;
8704}
8705
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308706static const struct
8707nla_policy
8708qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
Ashish Kumar Dhanotiya81e2acc2017-06-21 12:30:32 +05308709 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {
8710 .type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308711};
8712
8713/**
8714 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
8715 * @wiphy: WIPHY structure pointer
8716 * @wdev: Wireless device structure pointer
8717 * @data: Pointer to the data received
8718 * @data_len: Length of the data received
8719 *
8720 * This function is used to get link properties like nss, rate flags and
8721 * operating frequency for the active connection with the given peer.
8722 *
8723 * Return: 0 on success and errno on failure
8724 */
8725static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
8726 struct wireless_dev *wdev,
8727 const void *data,
8728 int data_len)
8729{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008730 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308731 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07008732 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson40dae4e2017-08-29 14:00:25 -07008733 struct hdd_station_ctx *hdd_sta_ctx;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308734 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05308735 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308736 uint32_t sta_id;
8737 struct sk_buff *reply_skb;
8738 uint32_t rate_flags = 0;
8739 uint8_t nss;
8740 uint8_t final_rate_flags = 0;
8741 uint32_t freq;
8742
Dustin Brownfdf17c12018-03-14 12:55:34 -07008743 hdd_enter_dev(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308744
Anurag Chouhan6d760662016-02-20 16:05:43 +05308745 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308746 hdd_err("Command not allowed in FTM mode");
8747 return -EPERM;
8748 }
8749
8750 if (0 != wlan_hdd_validate_context(hdd_ctx))
8751 return -EINVAL;
8752
Dustin Brown4ea21db2018-01-05 14:13:17 -08008753 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data,
8754 data_len, qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008755 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308756 return -EINVAL;
8757 }
8758
8759 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07008760 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308761 adapter->device_mode);
8762 return -EINVAL;
8763 }
8764
Ashish Kumar Dhanotiya81e2acc2017-06-21 12:30:32 +05308765 if (nla_len(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) < QDF_MAC_ADDR_SIZE) {
8766 hdd_err("Attribute peerMac is invalid for mode=%d",
8767 adapter->device_mode);
8768 return -EINVAL;
8769 }
8770
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308771 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05308772 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008773 hdd_debug("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308774 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
8775
Krunal Sonib4326f22016-03-10 13:05:51 -08008776 if (adapter->device_mode == QDF_STA_MODE ||
8777 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308778 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
8779 if ((hdd_sta_ctx->conn_info.connState !=
8780 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308781 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05308782 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008783 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308784 MAC_ADDR_ARRAY(peer_mac));
8785 return -EINVAL;
8786 }
8787
8788 nss = hdd_sta_ctx->conn_info.nss;
8789 freq = cds_chan_to_freq(
8790 hdd_sta_ctx->conn_info.operationChannel);
8791 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08008792 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
8793 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308794
8795 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07008796 if (adapter->sta_info[sta_id].in_use &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05308797 !qdf_is_macaddr_broadcast(
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07008798 &adapter->sta_info[sta_id].sta_mac) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308799 !qdf_mem_cmp(
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07008800 &adapter->sta_info[sta_id].sta_mac.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05308801 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308802 break;
8803 }
8804
8805 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07008806 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308807 MAC_ADDR_ARRAY(peer_mac));
8808 return -EINVAL;
8809 }
8810
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07008811 nss = adapter->sta_info[sta_id].nss;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308812 freq = cds_chan_to_freq(
Jeff Johnson01206862017-10-27 20:55:59 -07008813 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operating_channel);
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07008814 rate_flags = adapter->sta_info[sta_id].rate_flags;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308815 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07008816 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308817 MAC_ADDR_ARRAY(peer_mac));
8818 return -EINVAL;
8819 }
8820
Naveen Rawatea1564b2018-05-17 15:56:11 -07008821 if (!(rate_flags & TX_RATE_LEGACY)) {
8822 if (rate_flags & TX_RATE_VHT80) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308823 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08008824#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308825 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08008826#endif
Naveen Rawatea1564b2018-05-17 15:56:11 -07008827 } else if (rate_flags & TX_RATE_VHT40) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308828 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08008829#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308830 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08008831#endif
Naveen Rawatea1564b2018-05-17 15:56:11 -07008832 } else if (rate_flags & TX_RATE_VHT20) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308833 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
8834 } else if (rate_flags &
Naveen Rawatea1564b2018-05-17 15:56:11 -07008835 (TX_RATE_HT20 | TX_RATE_HT40)) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308836 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08008837#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Naveen Rawatea1564b2018-05-17 15:56:11 -07008838 if (rate_flags & TX_RATE_HT40)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308839 final_rate_flags |=
8840 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08008841#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308842 }
8843
Naveen Rawatea1564b2018-05-17 15:56:11 -07008844 if (rate_flags & TX_RATE_SGI) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308845 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
8846 final_rate_flags |= RATE_INFO_FLAGS_MCS;
8847 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
8848 }
8849 }
8850
8851 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
8852 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
8853
8854 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07008855 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308856 return -EINVAL;
8857 }
8858
8859 if (nla_put_u8(reply_skb,
8860 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
8861 nss) ||
8862 nla_put_u8(reply_skb,
8863 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
8864 final_rate_flags) ||
8865 nla_put_u32(reply_skb,
8866 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
8867 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008868 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308869 kfree_skb(reply_skb);
8870 return -EINVAL;
8871 }
8872
8873 return cfg80211_vendor_cmd_reply(reply_skb);
8874}
8875
8876/**
8877 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
8878 * properties.
8879 * @wiphy: WIPHY structure pointer
8880 * @wdev: Wireless device structure pointer
8881 * @data: Pointer to the data received
8882 * @data_len: Length of the data received
8883 *
8884 * This function is used to get link properties like nss, rate flags and
8885 * operating frequency for the active connection with the given peer.
8886 *
8887 * Return: 0 on success and errno on failure
8888 */
8889static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
8890 struct wireless_dev *wdev,
8891 const void *data,
8892 int data_len)
8893{
8894 int ret = 0;
8895
8896 cds_ssr_protect(__func__);
8897 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
8898 wdev, data, data_len);
8899 cds_ssr_unprotect(__func__);
8900
8901 return ret;
8902}
8903
Peng Xu278d0122015-09-24 16:34:17 -07008904static const struct
8905nla_policy
8906qca_wlan_vendor_ota_test_policy
8907[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
8908 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
8909};
8910
8911/**
8912 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
8913 * @wiphy: Pointer to wireless phy
8914 * @wdev: Pointer to wireless device
8915 * @data: Pointer to data
8916 * @data_len: Data length
8917 *
8918 * Return: 0 on success, negative errno on failure
8919 */
8920static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
8921 struct wireless_dev *wdev,
8922 const void *data,
8923 int data_len)
8924{
8925 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07008926 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Peng Xu278d0122015-09-24 16:34:17 -07008927 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008928 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Peng Xu278d0122015-09-24 16:34:17 -07008929 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
8930 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308931 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07008932 uint32_t current_roam_state;
8933
Dustin Brownfdf17c12018-03-14 12:55:34 -07008934 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08008935
Anurag Chouhan6d760662016-02-20 16:05:43 +05308936 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07008937 hdd_err("Command not allowed in FTM mode");
8938 return -EPERM;
8939 }
8940
8941 if (0 != wlan_hdd_validate_context(hdd_ctx))
8942 return -EINVAL;
8943
Dustin Brown4ea21db2018-01-05 14:13:17 -08008944 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
8945 data, data_len,
8946 qca_wlan_vendor_ota_test_policy)) {
Peng Xu278d0122015-09-24 16:34:17 -07008947 hdd_err("invalid attr");
8948 return -EINVAL;
8949 }
8950
8951 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
8952 hdd_err("attr ota test failed");
8953 return -EINVAL;
8954 }
8955
8956 ota_enable = nla_get_u8(
8957 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
8958
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008959 hdd_debug(" OTA test enable = %d", ota_enable);
Peng Xu278d0122015-09-24 16:34:17 -07008960 if (ota_enable != 1) {
8961 hdd_err("Invalid value, only enable test mode is supported!");
8962 return -EINVAL;
8963 }
8964
8965 current_roam_state =
Jeff Johnson1b780e42017-10-31 14:11:45 -07008966 sme_get_current_roam_state(hal, adapter->session_id);
8967 status = sme_stop_roaming(hal, adapter->session_id,
Peng Xu278d0122015-09-24 16:34:17 -07008968 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308969 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07008970 hdd_err("Enable/Disable roaming failed");
8971 return -EINVAL;
8972 }
8973
Jeff Johnson1b780e42017-10-31 14:11:45 -07008974 status = sme_ps_enable_disable(hal, adapter->session_id,
Peng Xu278d0122015-09-24 16:34:17 -07008975 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308976 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07008977 hdd_err("Enable/Disable power save failed");
8978 /* restore previous roaming setting */
8979 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
8980 current_roam_state == eCSR_ROAMING_STATE_JOINED)
Jeff Johnson1b780e42017-10-31 14:11:45 -07008981 status = sme_start_roaming(hal, adapter->session_id,
Peng Xu278d0122015-09-24 16:34:17 -07008982 eCsrHddIssued);
8983 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
8984 current_roam_state == eCSR_ROAMING_STATE_IDLE)
Jeff Johnson1b780e42017-10-31 14:11:45 -07008985 status = sme_stop_roaming(hal, adapter->session_id,
Peng Xu278d0122015-09-24 16:34:17 -07008986 eCsrHddIssued);
8987
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308988 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07008989 hdd_err("Restoring roaming state failed");
8990
8991 return -EINVAL;
8992 }
8993
8994
8995 return 0;
8996}
8997
8998/**
8999 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
9000 * @wiphy: Pointer to wireless phy
9001 * @wdev: Pointer to wireless device
9002 * @data: Pointer to data
9003 * @data_len: Data length
9004 *
9005 * Return: 0 on success, negative errno on failure
9006 */
9007static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
9008 struct wireless_dev *wdev,
9009 const void *data,
9010 int data_len)
9011{
9012 int ret = 0;
9013
9014 cds_ssr_protect(__func__);
9015 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
9016 cds_ssr_unprotect(__func__);
9017
9018 return ret;
9019}
9020
Dustin Brown8f3b0562017-06-06 11:38:45 -07009021static const struct nla_policy
9022txpower_scale_policy[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1] = {
9023 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE] = { .type = NLA_U8 },
9024};
9025
Peng Xu4d67c8f2015-10-16 16:02:26 -07009026/**
9027 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
9028 * @wiphy: Pointer to wireless phy
9029 * @wdev: Pointer to wireless device
9030 * @data: Pointer to data
9031 * @data_len: Data length
9032 *
9033 * Return: 0 on success, negative errno on failure
9034 */
9035static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
9036 struct wireless_dev *wdev,
9037 const void *data,
9038 int data_len)
9039{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009040 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Peng Xu4d67c8f2015-10-16 16:02:26 -07009041 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07009042 struct hdd_adapter *adapter;
Peng Xu62c8c432016-05-09 15:23:02 -07009043 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07009044 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
9045 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07009046 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07009047
Dustin Brownfdf17c12018-03-14 12:55:34 -07009048 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08009049
Peng Xu4d67c8f2015-10-16 16:02:26 -07009050 ret = wlan_hdd_validate_context(hdd_ctx);
9051 if (ret)
9052 return ret;
9053
9054 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9055
Dustin Brown4ea21db2018-01-05 14:13:17 -08009056 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
9057 data, data_len, txpower_scale_policy)) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07009058 hdd_err("Invalid ATTR");
9059 return -EINVAL;
9060 }
9061
9062 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
9063 hdd_err("attr tx power scale failed");
9064 return -EINVAL;
9065 }
9066
9067 scale_value = nla_get_u8(tb
9068 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
9069
9070 if (scale_value > MAX_TXPOWER_SCALE) {
9071 hdd_err("Invalid tx power scale level");
9072 return -EINVAL;
9073 }
9074
Jeff Johnson1b780e42017-10-31 14:11:45 -07009075 status = wma_set_tx_power_scale(adapter->session_id, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07009076
Peng Xu62c8c432016-05-09 15:23:02 -07009077 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07009078 hdd_err("Set tx power scale failed");
9079 return -EINVAL;
9080 }
9081
9082 return 0;
9083}
9084
9085/**
9086 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
9087 * @wiphy: Pointer to wireless phy
9088 * @wdev: Pointer to wireless device
9089 * @data: Pointer to data
9090 * @data_len: Data length
9091 *
9092 * Return: 0 on success, negative errno on failure
9093 */
9094static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
9095 struct wireless_dev *wdev,
9096 const void *data,
9097 int data_len)
9098{
Peng Xu62c8c432016-05-09 15:23:02 -07009099 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07009100
9101 cds_ssr_protect(__func__);
9102 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
9103 data, data_len);
9104 cds_ssr_unprotect(__func__);
9105
9106 return ret;
9107}
9108
Dustin Brown498b11a2017-06-06 12:29:43 -07009109static const struct nla_policy txpower_scale_decr_db_policy
9110[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1] = {
9111 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB] = { .type = NLA_U8 },
9112};
9113
Peng Xu4d67c8f2015-10-16 16:02:26 -07009114/**
9115 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
9116 * @wiphy: Pointer to wireless phy
9117 * @wdev: Pointer to wireless device
9118 * @data: Pointer to data
9119 * @data_len: Data length
9120 *
9121 * Return: 0 on success, negative errno on failure
9122 */
9123static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
9124 struct wireless_dev *wdev,
9125 const void *data,
9126 int data_len)
9127{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009128 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Peng Xu4d67c8f2015-10-16 16:02:26 -07009129 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07009130 struct hdd_adapter *adapter;
Peng Xu62c8c432016-05-09 15:23:02 -07009131 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07009132 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
9133 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07009134 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07009135
Dustin Brownfdf17c12018-03-14 12:55:34 -07009136 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08009137
Peng Xu4d67c8f2015-10-16 16:02:26 -07009138 ret = wlan_hdd_validate_context(hdd_ctx);
9139 if (ret)
9140 return ret;
9141
9142 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9143
Dustin Brown4ea21db2018-01-05 14:13:17 -08009144 if (wlan_cfg80211_nla_parse(tb,
9145 QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
9146 data, data_len,
9147 txpower_scale_decr_db_policy)) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07009148 hdd_err("Invalid ATTR");
9149 return -EINVAL;
9150 }
9151
9152 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
9153 hdd_err("attr tx power decrease db value failed");
9154 return -EINVAL;
9155 }
9156
9157 scale_value = nla_get_u8(tb
9158 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
9159
Jeff Johnson1b780e42017-10-31 14:11:45 -07009160 status = wma_set_tx_power_scale_decr_db(adapter->session_id,
Peng Xu62c8c432016-05-09 15:23:02 -07009161 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07009162
Peng Xu62c8c432016-05-09 15:23:02 -07009163 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07009164 hdd_err("Set tx power decrease db failed");
9165 return -EINVAL;
9166 }
9167
9168 return 0;
9169}
9170
9171/**
9172 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
9173 * @wiphy: Pointer to wireless phy
9174 * @wdev: Pointer to wireless device
9175 * @data: Pointer to data
9176 * @data_len: Data length
9177 *
9178 * Return: 0 on success, negative errno on failure
9179 */
9180static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
9181 struct wireless_dev *wdev,
9182 const void *data,
9183 int data_len)
9184{
Peng Xu62c8c432016-05-09 15:23:02 -07009185 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07009186
9187 cds_ssr_protect(__func__);
9188 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
9189 data, data_len);
9190 cds_ssr_unprotect(__func__);
9191
9192 return ret;
9193}
Peng Xu8fdaa492016-06-22 10:20:47 -07009194
9195/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309196 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
9197 * @wiphy: Pointer to wireless phy
9198 * @wdev: Pointer to wireless device
9199 * @data: Pointer to data
9200 * @data_len: Data length
9201 *
9202 * Processes the conditional channel switch request and invokes the helper
9203 * APIs to process the channel switch request.
9204 *
9205 * Return: 0 on success, negative errno on failure
9206 */
9207static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
9208 struct wireless_dev *wdev,
9209 const void *data,
9210 int data_len)
9211{
9212 int ret;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009213 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309214 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07009215 struct hdd_adapter *adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309216 struct nlattr
9217 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
9218 uint32_t freq_len, i;
9219 uint32_t *freq;
SaidiReddy Yenugac0c34cf2017-02-13 17:44:40 +05309220 uint8_t chans[QDF_MAX_NUM_CHAN] = {0};
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309221
Dustin Brownfdf17c12018-03-14 12:55:34 -07009222 hdd_enter_dev(dev);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309223
9224 ret = wlan_hdd_validate_context(hdd_ctx);
9225 if (ret)
9226 return ret;
9227
9228 if (!hdd_ctx->config->enableDFSMasterCap) {
9229 hdd_err("DFS master capability is not present in the driver");
9230 return -EINVAL;
9231 }
9232
9233 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9234 hdd_err("Command not allowed in FTM mode");
9235 return -EPERM;
9236 }
9237
9238 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9239 if (adapter->device_mode != QDF_SAP_MODE) {
9240 hdd_err("Invalid device mode %d", adapter->device_mode);
9241 return -EINVAL;
9242 }
9243
Rajeev Kumar1c40f072017-06-05 15:24:05 -07009244 /*
9245 * audit note: it is ok to pass a NULL policy here since only
9246 * one attribute is parsed which is array of frequencies and
9247 * it is explicitly validated for both under read and over read
9248 */
Dustin Brown4ea21db2018-01-05 14:13:17 -08009249 if (wlan_cfg80211_nla_parse(tb,
9250 QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
9251 data, data_len, NULL)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309252 hdd_err("Invalid ATTR");
9253 return -EINVAL;
9254 }
9255
9256 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
9257 hdd_err("Frequency list is missing");
9258 return -EINVAL;
9259 }
9260
9261 freq_len = nla_len(
9262 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
9263 sizeof(uint32_t);
9264
9265 if (freq_len > QDF_MAX_NUM_CHAN) {
9266 hdd_err("insufficient space to hold channels");
9267 return -ENOMEM;
9268 }
9269
9270 hdd_debug("freq_len=%d", freq_len);
9271
9272 freq = nla_data(
9273 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
9274
9275
9276 for (i = 0; i < freq_len; i++) {
9277 if (freq[i] == 0)
9278 chans[i] = 0;
9279 else
9280 chans[i] = ieee80211_frequency_to_channel(freq[i]);
9281
9282 hdd_debug("freq[%d]=%d", i, freq[i]);
9283 }
9284
9285 /*
9286 * The input frequency list from user space is designed to be a
9287 * priority based frequency list. This is only to accommodate any
9288 * future request. But, current requirement is only to perform CAC
9289 * on a single channel. So, the first entry from the list is picked.
9290 *
9291 * If channel is zero, any channel in the available outdoor regulatory
9292 * domain will be selected.
9293 */
9294 ret = wlan_hdd_request_pre_cac(chans[0]);
9295 if (ret) {
9296 hdd_err("pre cac request failed with reason:%d", ret);
9297 return ret;
9298 }
9299
9300 return 0;
9301}
9302
Rajeev Kumar67f5b872017-06-06 13:26:57 -07009303/* P2P listen offload device types parameters length in bytes */
9304#define P2P_LO_MAX_REQ_DEV_TYPE_COUNT (10)
9305#define P2P_LO_WPS_DEV_TYPE_LEN (8)
9306#define P2P_LO_DEV_TYPE_MAX_LEN \
9307 (P2P_LO_MAX_REQ_DEV_TYPE_COUNT * P2P_LO_WPS_DEV_TYPE_LEN)
9308
9309static const struct nla_policy
9310p2p_listen_offload_policy[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1] = {
9311 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] = { .type = NLA_U32 },
9312 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] = { .type = NLA_U32 },
9313 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] = {
9314 .type = NLA_U32 },
9315 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] = { .type = NLA_U32 },
9316 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] = {
9317 .type = NLA_BINARY,
9318 .len = P2P_LO_DEV_TYPE_MAX_LEN },
9319 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE] = {
9320 .type = NLA_BINARY,
9321 .len = MAX_GENIE_LEN },
9322 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG] = {
9323 .type = NLA_U32 },
9324 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] = { .type = NLA_U32 },
9325 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON] = {
9326 .type = NLA_U8 },
9327};
9328
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309329/**
Peng Xu8fdaa492016-06-22 10:20:47 -07009330 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
9331 * @wiphy: Pointer to wireless phy
9332 * @wdev: Pointer to wireless device
9333 * @data: Pointer to data
9334 * @data_len: Data length
9335 *
9336 * This function is to process the p2p listen offload start vendor
9337 * command. It parses the input parameters and invoke WMA API to
9338 * send the command to firmware.
9339 *
9340 * Return: 0 on success, negative errno on failure
9341 */
9342static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
9343 struct wireless_dev *wdev,
9344 const void *data,
9345 int data_len)
9346{
9347 int ret;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009348 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Peng Xu8fdaa492016-06-22 10:20:47 -07009349 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07009350 struct hdd_adapter *adapter;
Peng Xu8fdaa492016-06-22 10:20:47 -07009351 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
9352 struct sir_p2p_lo_start params;
Peng Xu8fdaa492016-06-22 10:20:47 -07009353
Dustin Brownfdf17c12018-03-14 12:55:34 -07009354 hdd_enter_dev(dev);
Peng Xu8fdaa492016-06-22 10:20:47 -07009355
9356 ret = wlan_hdd_validate_context(hdd_ctx);
9357 if (ret)
9358 return ret;
9359
9360 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9361 hdd_err("Command not allowed in FTM mode");
9362 return -EPERM;
9363 }
9364
9365 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9366 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
9367 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
9368 (adapter->device_mode != QDF_P2P_GO_MODE)) {
9369 hdd_err("Invalid device mode %d", adapter->device_mode);
9370 return -EINVAL;
9371 }
9372
Dustin Brown4ea21db2018-01-05 14:13:17 -08009373 if (wlan_cfg80211_nla_parse(tb,
9374 QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
9375 data, data_len,
9376 p2p_listen_offload_policy)) {
Peng Xu8fdaa492016-06-22 10:20:47 -07009377 hdd_err("Invalid ATTR");
9378 return -EINVAL;
9379 }
9380
9381 memset(&params, 0, sizeof(params));
9382
9383 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
9384 params.ctl_flags = 1; /* set to default value */
9385 else
9386 params.ctl_flags = nla_get_u32(tb
9387 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
9388
9389 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
9390 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
9391 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
9392 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
9393 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
9394 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
9395 hdd_err("Attribute parsing failed");
9396 return -EINVAL;
9397 }
9398
Jeff Johnson1b780e42017-10-31 14:11:45 -07009399 params.vdev_id = adapter->session_id;
Peng Xu8fdaa492016-06-22 10:20:47 -07009400 params.freq = nla_get_u32(tb
9401 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
9402 if ((params.freq != 2412) && (params.freq != 2437) &&
9403 (params.freq != 2462)) {
9404 hdd_err("Invalid listening channel: %d", params.freq);
9405 return -EINVAL;
9406 }
9407
9408 params.period = nla_get_u32(tb
9409 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
9410 if (!((params.period > 0) && (params.period < UINT_MAX))) {
9411 hdd_err("Invalid period: %d", params.period);
9412 return -EINVAL;
9413 }
9414
9415 params.interval = nla_get_u32(tb
9416 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
9417 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
9418 hdd_err("Invalid interval: %d", params.interval);
9419 return -EINVAL;
9420 }
9421
9422 params.count = nla_get_u32(tb
9423 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08009424 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07009425 hdd_err("Invalid count: %d", params.count);
9426 return -EINVAL;
9427 }
9428
9429 params.device_types = nla_data(tb
9430 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
9431 if (params.device_types == NULL) {
9432 hdd_err("Invalid device types");
9433 return -EINVAL;
9434 }
9435
9436 params.dev_types_len = nla_len(tb
9437 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
Rajeev Kumar67f5b872017-06-06 13:26:57 -07009438 /* device type length has to be multiple of P2P_LO_WPS_DEV_TYPE_LEN */
9439 if (0 != (params.dev_types_len % P2P_LO_WPS_DEV_TYPE_LEN)) {
Peng Xu8fdaa492016-06-22 10:20:47 -07009440 hdd_err("Invalid device type length: %d", params.dev_types_len);
9441 return -EINVAL;
9442 }
9443
9444 params.probe_resp_tmplt = nla_data(tb
9445 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
9446 if (params.probe_resp_tmplt == NULL) {
9447 hdd_err("Invalid probe response template");
9448 return -EINVAL;
9449 }
9450
Rajeev Kumar67f5b872017-06-06 13:26:57 -07009451 /*
9452 * IEs minimum length should be 2 bytes: 1 byte for element id
9453 * and 1 byte for element id length.
9454 */
Peng Xu8fdaa492016-06-22 10:20:47 -07009455 params.probe_resp_len = nla_len(tb
9456 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
Rajeev Kumar67f5b872017-06-06 13:26:57 -07009457 if (params.probe_resp_len < MIN_GENIE_LEN) {
Peng Xu8fdaa492016-06-22 10:20:47 -07009458 hdd_err("Invalid probe resp template length: %d",
9459 params.probe_resp_len);
9460 return -EINVAL;
9461 }
9462
9463 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
9464 params.freq, params.period, params.interval, params.count);
9465
Wu Gao9a704f42017-03-10 18:42:11 +08009466 return wlan_hdd_listen_offload_start(adapter, &params);
Peng Xu8fdaa492016-06-22 10:20:47 -07009467}
9468
9469
9470/**
9471 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
9472 * @wiphy: Pointer to wireless phy
9473 * @wdev: Pointer to wireless device
9474 * @data: Pointer to data
9475 * @data_len: Data length
9476 *
9477 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
9478 * to process p2p listen offload start vendor command.
9479 *
9480 * Return: 0 on success, negative errno on failure
9481 */
9482static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
9483 struct wireless_dev *wdev,
9484 const void *data,
9485 int data_len)
9486{
9487 int ret = 0;
9488
9489 cds_ssr_protect(__func__);
9490 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
9491 data, data_len);
9492 cds_ssr_unprotect(__func__);
9493
9494 return ret;
9495}
9496
9497/**
9498 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
9499 * @wiphy: Pointer to wireless phy
9500 * @wdev: Pointer to wireless device
9501 * @data: Pointer to data
9502 * @data_len: Data length
9503 *
9504 * This function is to process the p2p listen offload stop vendor
9505 * command. It invokes WMA API to send command to firmware.
9506 *
9507 * Return: 0 on success, negative errno on failure
9508 */
9509static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
9510 struct wireless_dev *wdev,
9511 const void *data,
9512 int data_len)
9513{
Jeff Johnsone5006672017-08-29 14:39:02 -07009514 struct hdd_adapter *adapter;
Peng Xu8fdaa492016-06-22 10:20:47 -07009515 struct net_device *dev = wdev->netdev;
9516
9517 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9518 hdd_err("Command not allowed in FTM mode");
9519 return -EPERM;
9520 }
9521
9522 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9523 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
9524 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
9525 (adapter->device_mode != QDF_P2P_GO_MODE)) {
9526 hdd_err("Invalid device mode");
9527 return -EINVAL;
9528 }
9529
Wu Gao9a704f42017-03-10 18:42:11 +08009530 return wlan_hdd_listen_offload_stop(adapter);
Peng Xu8fdaa492016-06-22 10:20:47 -07009531}
9532
9533/**
9534 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
9535 * @wiphy: Pointer to wireless phy
9536 * @wdev: Pointer to wireless device
9537 * @data: Pointer to data
9538 * @data_len: Data length
9539 *
9540 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
9541 * to process p2p listen offload stop vendor command.
9542 *
9543 * Return: 0 on success, negative errno on failure
9544 */
9545static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
9546 struct wireless_dev *wdev,
9547 const void *data,
9548 int data_len)
9549{
9550 int ret = 0;
9551
9552 cds_ssr_protect(__func__);
9553 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
9554 data, data_len);
9555 cds_ssr_unprotect(__func__);
9556
9557 return ret;
9558}
9559
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309560/**
9561 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
9562 * @wiphy: Pointer to wireless phy
9563 * @wdev: Pointer to wireless device
9564 * @data: Pointer to data
9565 * @data_len: Data length
9566 *
9567 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
9568 * to process the conditional channel switch request.
9569 *
9570 * Return: 0 on success, negative errno on failure
9571 */
9572static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
9573 struct wireless_dev *wdev,
9574 const void *data,
9575 int data_len)
9576{
9577 int ret;
9578
9579 cds_ssr_protect(__func__);
9580 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
9581 data, data_len);
9582 cds_ssr_unprotect(__func__);
9583
9584 return ret;
9585}
9586
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309587/*
9588 * define short names for the global vendor params
9589 * used by __wlan_hdd_cfg80211_bpf_offload()
9590 */
9591#define BPF_INVALID \
9592 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
9593#define BPF_SET_RESET \
9594 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
9595#define BPF_VERSION \
9596 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
9597#define BPF_FILTER_ID \
9598 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
9599#define BPF_PACKET_SIZE \
9600 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
9601#define BPF_CURRENT_OFFSET \
9602 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
9603#define BPF_PROGRAM \
9604 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
9605#define BPF_MAX \
9606 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07009607
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309608static const struct nla_policy
9609wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
9610 [BPF_SET_RESET] = {.type = NLA_U32},
9611 [BPF_VERSION] = {.type = NLA_U32},
9612 [BPF_FILTER_ID] = {.type = NLA_U32},
9613 [BPF_PACKET_SIZE] = {.type = NLA_U32},
9614 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
9615 [BPF_PROGRAM] = {.type = NLA_U8},
9616};
9617
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009618struct bpf_offload_priv {
9619 struct sir_bpf_get_offload bpf_get_offload;
9620};
9621
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309622/**
9623 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009624 * @context: opaque context originally passed to SME. HDD always passes
9625 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309626 * @bpf_get_offload: struct for get offload
9627 *
9628 * This function receives the response/data from the lower layer and
9629 * checks to see if the thread is still waiting then post the results to
9630 * upper layer, if the request has timed out then ignore.
9631 *
9632 * Return: None
9633 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009634static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08009635 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309636{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009637 struct hdd_request *request;
9638 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309639
Dustin Brown491d54b2018-03-14 12:39:11 -07009640 hdd_enter();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309641
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009642 request = hdd_request_get(context);
9643 if (!request) {
9644 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309645 return;
9646 }
9647
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009648 priv = hdd_request_priv(request);
9649 priv->bpf_get_offload = *data;
9650 hdd_request_complete(request);
9651 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309652}
9653
9654/**
9655 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
9656 * @hdd_context: hdd_context
9657 * @bpf_get_offload: struct for get offload
9658 *
9659 * Return: 0 on success, error number otherwise.
9660 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009661static int hdd_post_get_bpf_capabilities_rsp(struct hdd_context *hdd_ctx,
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309662 struct sir_bpf_get_offload *bpf_get_offload)
9663{
9664 struct sk_buff *skb;
9665 uint32_t nl_buf_len;
9666
Dustin Brown491d54b2018-03-14 12:39:11 -07009667 hdd_enter();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309668
9669 nl_buf_len = NLMSG_HDRLEN;
9670 nl_buf_len +=
9671 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
9672 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
9673
9674 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
9675 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07009676 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309677 return -ENOMEM;
9678 }
9679
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009680 hdd_debug("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309681 bpf_get_offload->bpf_version,
9682 bpf_get_offload->max_bytes_for_bpf_inst);
9683
9684 if (nla_put_u32(skb, BPF_PACKET_SIZE,
9685 bpf_get_offload->max_bytes_for_bpf_inst) ||
9686 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009687 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309688 goto nla_put_failure;
9689 }
9690
9691 cfg80211_vendor_cmd_reply(skb);
Dustin Browne74003f2018-03-14 12:51:58 -07009692 hdd_exit();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309693 return 0;
9694
9695nla_put_failure:
9696 kfree_skb(skb);
9697 return -EINVAL;
9698}
9699
9700/**
9701 * hdd_get_bpf_offload - Get BPF offload Capabilities
9702 * @hdd_ctx: Hdd context
9703 *
9704 * Return: 0 on success, errno on failure
9705 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009706static int hdd_get_bpf_offload(struct hdd_context *hdd_ctx)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309707{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309708 QDF_STATUS status;
9709 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009710 void *cookie;
9711 struct hdd_request *request;
9712 struct bpf_offload_priv *priv;
9713 static const struct hdd_request_params params = {
9714 .priv_size = sizeof(*priv),
9715 .timeout_ms = WLAN_WAIT_TIME_BPF,
9716 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309717
Dustin Brown491d54b2018-03-14 12:39:11 -07009718 hdd_enter();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309719
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009720 request = hdd_request_alloc(&params);
9721 if (!request) {
9722 hdd_err("Unable to allocate request");
9723 return -EINVAL;
9724 }
9725 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309726
Jeff Johnsona867e0c2017-01-26 13:43:51 -08009727 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
9728 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009729 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309730 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009731 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009732 ret = qdf_status_to_os_return(status);
9733 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309734 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009735 ret = hdd_request_wait_for_response(request);
9736 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07009737 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009738 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309739 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009740 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309741 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009742 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309743 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07009744 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309745
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009746cleanup:
9747 /*
9748 * either we never sent a request to SME, we sent a request to
9749 * SME and timed out, or we sent a request to SME, received a
9750 * response from SME, and posted the response to userspace.
9751 * regardless we are done with the request.
9752 */
9753 hdd_request_put(request);
Dustin Browne74003f2018-03-14 12:51:58 -07009754 hdd_exit();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009755
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309756 return ret;
9757}
9758
9759/**
9760 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
9761 * @hdd_ctx: Hdd context
9762 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05309763 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309764 *
9765 * Return: 0 on success; errno on failure
9766 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009767static int hdd_set_reset_bpf_offload(struct hdd_context *hdd_ctx,
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309768 struct nlattr **tb,
Jeff Johnsone5006672017-08-29 14:39:02 -07009769 struct hdd_adapter *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309770{
9771 struct sir_bpf_set_offload *bpf_set_offload;
9772 QDF_STATUS status;
9773 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05309774 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309775
Dustin Brown491d54b2018-03-14 12:39:11 -07009776 hdd_enter();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309777
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05309778 if (adapter->device_mode == QDF_STA_MODE ||
9779 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
9780 if (!hdd_conn_is_connected(
9781 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
9782 hdd_err("Not in Connected state!");
9783 return -ENOTSUPP;
9784 }
9785 }
9786
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309787 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
9788 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07009789 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309790 return -ENOMEM;
9791 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309792
9793 /* Parse and fetch bpf packet size */
9794 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009795 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05309796 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309797 goto fail;
9798 }
9799 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
9800
9801 if (!bpf_set_offload->total_length) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009802 hdd_debug("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309803 goto post_sme;
9804 }
9805
9806 /* Parse and fetch bpf program */
9807 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009808 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05309809 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309810 goto fail;
9811 }
9812
9813 prog_len = nla_len(tb[BPF_PROGRAM]);
9814 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05309815
9816 if (bpf_set_offload->program == NULL) {
9817 hdd_err("qdf_mem_malloc failed for bpf offload program");
9818 ret = -ENOMEM;
9819 goto fail;
9820 }
9821
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309822 bpf_set_offload->current_length = prog_len;
9823 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Jeff Johnson1b780e42017-10-31 14:11:45 -07009824 bpf_set_offload->session_id = adapter->session_id;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309825
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009826 hdd_debug("BPF set instructions");
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08009827 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05309828 bpf_set_offload->program, prog_len);
9829
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309830 /* Parse and fetch filter Id */
9831 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009832 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05309833 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309834 goto fail;
9835 }
9836 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
9837
9838 /* Parse and fetch current offset */
9839 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009840 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05309841 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309842 goto fail;
9843 }
9844 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
9845
9846post_sme:
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009847 hdd_debug("Posting BPF SET/RESET to SME, session_id: %d Bpf Version: %d filter ID: %d total_length: %d current_length: %d current offset: %d",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309848 bpf_set_offload->session_id,
9849 bpf_set_offload->version,
9850 bpf_set_offload->filter_id,
9851 bpf_set_offload->total_length,
9852 bpf_set_offload->current_length,
9853 bpf_set_offload->current_offset);
9854
9855 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
9856 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009857 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05309858 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309859 goto fail;
9860 }
Dustin Browne74003f2018-03-14 12:51:58 -07009861 hdd_exit();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309862
9863fail:
9864 if (bpf_set_offload->current_length)
9865 qdf_mem_free(bpf_set_offload->program);
9866 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05309867 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309868}
9869
9870/**
9871 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
9872 * @wiphy: wiphy structure pointer
9873 * @wdev: Wireless device structure pointer
9874 * @data: Pointer to the data received
9875 * @data_len: Length of @data
9876 *
9877 * Return: 0 on success; errno on failure
9878 */
9879static int
9880__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
9881 struct wireless_dev *wdev,
9882 const void *data, int data_len)
9883{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009884 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309885 struct net_device *dev = wdev->netdev;
Jeff Johnsonce2ba702017-10-02 13:30:24 -07009886 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309887 struct nlattr *tb[BPF_MAX + 1];
9888 int ret_val, packet_filter_subcmd;
9889
Dustin Brown491d54b2018-03-14 12:39:11 -07009890 hdd_enter();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309891
9892 ret_val = wlan_hdd_validate_context(hdd_ctx);
9893 if (ret_val)
9894 return ret_val;
9895
9896 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009897 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309898 return -EINVAL;
9899 }
9900
9901 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07009902 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309903 return -ENOTSUPP;
9904 }
9905
Dustin Brown4ea21db2018-01-05 14:13:17 -08009906 if (wlan_cfg80211_nla_parse(tb, BPF_MAX, data, data_len,
9907 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009908 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309909 return -EINVAL;
9910 }
9911
9912 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009913 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309914 return -EINVAL;
9915 }
9916
9917 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
9918
9919 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
9920 return hdd_get_bpf_offload(hdd_ctx);
9921 else
9922 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Jeff Johnsonce2ba702017-10-02 13:30:24 -07009923 adapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309924}
9925
9926/**
9927 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
9928 * @wiphy: wiphy structure pointer
9929 * @wdev: Wireless device structure pointer
9930 * @data: Pointer to the data received
9931 * @data_len: Length of @data
9932 *
9933 * Return: 0 on success; errno on failure
9934 */
9935
9936static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
9937 struct wireless_dev *wdev,
9938 const void *data, int data_len)
9939{
9940 int ret;
9941
9942 cds_ssr_protect(__func__);
9943 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
9944 cds_ssr_unprotect(__func__);
9945
9946 return ret;
9947}
9948
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309949/**
9950 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
9951 * @pre_cac_adapter: AP adapter used for pre cac
9952 * @status: Status (true or false)
9953 * @handle: Global handle
9954 *
9955 * Sets the status of pre cac i.e., whether the pre cac is active or not
9956 *
9957 * Return: Zero on success, non-zero on failure
9958 */
Jeff Johnsone5006672017-08-29 14:39:02 -07009959static int wlan_hdd_set_pre_cac_status(struct hdd_adapter *pre_cac_adapter,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309960 bool status, tHalHandle handle)
9961{
9962 QDF_STATUS ret;
9963
9964 ret = wlan_sap_set_pre_cac_status(
9965 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
9966 if (QDF_IS_STATUS_ERROR(ret))
9967 return -EINVAL;
9968
9969 return 0;
9970}
9971
9972/**
9973 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
9974 * @ap_adapter: AP adapter
9975 * @chan_before_pre_cac: Channel
9976 *
9977 * Saves the channel which the AP was beaconing on before moving to the pre
9978 * cac channel. If radar is detected on the pre cac channel, this saved
9979 * channel will be used for AP operations.
9980 *
9981 * Return: Zero on success, non-zero on failure
9982 */
Jeff Johnsone5006672017-08-29 14:39:02 -07009983static int wlan_hdd_set_chan_before_pre_cac(struct hdd_adapter *ap_adapter,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309984 uint8_t chan_before_pre_cac)
9985{
9986 QDF_STATUS ret;
9987
9988 ret = wlan_sap_set_chan_before_pre_cac(
9989 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
9990 if (QDF_IS_STATUS_ERROR(ret))
9991 return -EINVAL;
9992
9993 return 0;
9994}
9995
Jeff Johnsone5006672017-08-29 14:39:02 -07009996int wlan_hdd_sap_get_valid_channellist(struct hdd_adapter *adapter,
Kapil Gupta94ca6f62016-12-11 18:43:12 +05309997 uint32_t *channel_count,
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05309998 uint8_t *channel_list,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08009999 enum band_info band)
Kapil Gupta94ca6f62016-12-11 18:43:12 +053010000{
Jeff Johnsone4c11db2018-05-05 23:22:32 -070010001 tsap_config_t *sap_config;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010002 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +053010003 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
10004 uint32_t chan_count;
10005 uint8_t i;
10006 QDF_STATUS status;
bingsd79e6062018-01-30 15:40:16 +080010007 struct wlan_objmgr_pdev *pdev = hdd_ctx->hdd_pdev;
10008 uint8_t tmp_chan;
Kapil Gupta94ca6f62016-12-11 18:43:12 +053010009
Jeff Johnsonb9424862017-10-30 08:49:35 -070010010 sap_config = &adapter->session.ap.sap_config;
Kapil Gupta94ca6f62016-12-11 18:43:12 +053010011
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +053010012 status =
10013 policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
10014 tmp_chan_list,
10015 &chan_count);
10016 if (QDF_IS_STATUS_ERROR(status)) {
10017 hdd_err("Failed to get channel list");
10018 return -EINVAL;
10019 }
Kapil Guptac1224bf2017-06-22 21:22:40 +053010020
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +053010021 for (i = 0; i < chan_count; i++) {
bingsd79e6062018-01-30 15:40:16 +080010022 tmp_chan = tmp_chan_list[i];
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +053010023 if (*channel_count < QDF_MAX_NUM_CHAN) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080010024 if ((BAND_2G == band) &&
bingsd79e6062018-01-30 15:40:16 +080010025 (WLAN_REG_IS_24GHZ_CH(tmp_chan)) &&
10026 (!wlan_reg_is_disable_ch(pdev, tmp_chan))) {
10027 channel_list[*channel_count] = tmp_chan;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +053010028 *channel_count += 1;
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080010029 } else if ((BAND_5G == band) &&
bingsd79e6062018-01-30 15:40:16 +080010030 (WLAN_REG_IS_5GHZ_CH(tmp_chan)) &&
10031 (!wlan_reg_is_disable_ch(pdev, tmp_chan))) {
10032 channel_list[*channel_count] = tmp_chan;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +053010033 *channel_count += 1;
10034 }
10035 } else {
10036 break;
10037 }
10038 }
bingsd79e6062018-01-30 15:40:16 +080010039
Kapil Gupta94ca6f62016-12-11 18:43:12 +053010040 if (*channel_count == 0) {
10041 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010042 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +053010043 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010044
10045 return 0;
10046}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010047
10048/**
10049 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
10050 * @hdd_ctx: HDD context
10051 * @ap_adapter: AP adapter
10052 * @channel: Channel requested by userspace
10053 * @pre_cac_chan: Pointer to the pre CAC channel
10054 *
10055 * Validates the channel provided by userspace. If user provided channel 0,
10056 * a valid outdoor channel must be selected from the regulatory channel.
10057 *
10058 * Return: Zero on success and non zero value on error
10059 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010060static int wlan_hdd_validate_and_get_pre_cac_ch(struct hdd_context *hdd_ctx,
Jeff Johnsone5006672017-08-29 14:39:02 -070010061 struct hdd_adapter *ap_adapter,
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010062 uint8_t channel,
10063 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010064{
bingsd79e6062018-01-30 15:40:16 +080010065 uint32_t i;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010066 QDF_STATUS status;
bingsd79e6062018-01-30 15:40:16 +080010067 uint32_t weight_len = 0;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010068 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10069 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
10070 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
10071
10072 if (0 == channel) {
10073 /* Channel is not obtained from PCL because PCL may not have
10074 * the entire channel list. For example: if SAP is up on
10075 * channel 6 and PCL is queried for the next SAP interface,
10076 * if SCC is preferred, the PCL will contain only the channel
10077 * 6. But, we are in need of a DFS channel. So, going with the
10078 * first channel from the valid channel list.
10079 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080010080 status = policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
10081 channel_list, &len);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010082 if (QDF_IS_STATUS_ERROR(status)) {
10083 hdd_err("Failed to get channel list");
10084 return -EINVAL;
10085 }
Tushnim Bhattacharyyaabc58852017-07-26 13:14:52 -070010086 policy_mgr_update_with_safe_channel_list(hdd_ctx->hdd_psoc,
10087 channel_list, &len, pcl_weights, weight_len);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010088 for (i = 0; i < len; i++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010089 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
10090 channel_list[i])) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010091 *pre_cac_chan = channel_list[i];
10092 break;
10093 }
10094 }
10095 if (*pre_cac_chan == 0) {
10096 hdd_err("unable to find outdoor channel");
10097 return -EINVAL;
10098 }
10099 } else {
10100 /* Only when driver selects a channel, check is done for
10101 * unnsafe and NOL channels. When user provides a fixed channel
10102 * the user is expected to take care of this.
10103 */
10104 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010105 !wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010106 hdd_err("Invalid channel for pre cac:%d", channel);
10107 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010108 }
Jeff Johnson68755312017-02-10 11:46:55 -080010109 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010110 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010111 hdd_debug("selected pre cac channel:%d", *pre_cac_chan);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010112 return 0;
10113}
10114
10115/**
10116 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
10117 * @channel: Channel option provided by userspace
10118 *
Jeff Johnsondd2f1fc2018-05-06 11:22:52 -070010119 * Sets the driver to the required hardware mode and start an adapter for
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010120 * pre CAC which will mimic an AP.
10121 *
10122 * Return: Zero on success, non-zero value on error
10123 */
10124int wlan_hdd_request_pre_cac(uint8_t channel)
10125{
Krunal Sonib37bb352016-12-20 14:12:21 -080010126 uint8_t pre_cac_chan = 0, *mac_addr;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010127 struct hdd_context *hdd_ctx;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010128 int ret;
Jeff Johnsone5006672017-08-29 14:39:02 -070010129 struct hdd_adapter *ap_adapter, *pre_cac_adapter;
Jeff Johnson87251032017-08-29 13:31:11 -070010130 struct hdd_ap_ctx *hdd_ap_ctx;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010131 QDF_STATUS status;
10132 struct wiphy *wiphy;
10133 struct net_device *dev;
10134 struct cfg80211_chan_def chandef;
10135 enum nl80211_channel_type channel_type;
10136 uint32_t freq;
10137 struct ieee80211_channel *chan;
10138 tHalHandle handle;
10139 bool val;
10140
10141 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10142 if (0 != wlan_hdd_validate_context(hdd_ctx))
10143 return -EINVAL;
10144
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080010145 if (policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) > 1) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010146 hdd_err("pre cac not allowed in concurrency");
10147 return -EINVAL;
10148 }
10149
10150 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
10151 if (!ap_adapter) {
10152 hdd_err("unable to get SAP adapter");
10153 return -EINVAL;
10154 }
10155
10156 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
10157 if (!handle) {
10158 hdd_err("Invalid handle");
10159 return -EINVAL;
10160 }
10161
10162 val = wlan_sap_is_pre_cac_active(handle);
10163 if (val) {
10164 hdd_err("pre cac is already in progress");
10165 return -EINVAL;
10166 }
10167
10168 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
10169 if (!hdd_ap_ctx) {
10170 hdd_err("SAP context is NULL");
10171 return -EINVAL;
10172 }
10173
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010174 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
Jeff Johnson01206862017-10-27 20:55:59 -070010175 hdd_ap_ctx->operating_channel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010176 hdd_err("SAP is already on DFS channel:%d",
Jeff Johnson01206862017-10-27 20:55:59 -070010177 hdd_ap_ctx->operating_channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010178 return -EINVAL;
10179 }
10180
Jeff Johnson01206862017-10-27 20:55:59 -070010181 if (!WLAN_REG_IS_24GHZ_CH(hdd_ap_ctx->operating_channel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010182 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
Jeff Johnson01206862017-10-27 20:55:59 -070010183 hdd_ap_ctx->operating_channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010184 return -EINVAL;
10185 }
10186
Krunal Sonib37bb352016-12-20 14:12:21 -080010187 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
10188 if (!mac_addr) {
10189 hdd_err("can't add virtual intf: Not getting valid mac addr");
10190 return -EINVAL;
10191 }
10192
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010193 hdd_debug("channel:%d", channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010194
10195 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
10196 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -080010197 if (ret != 0) {
10198 hdd_err("can't validate pre-cac channel");
10199 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010200 }
10201
10202 hdd_debug("starting pre cac SAP adapter");
10203
10204 /* Starting a SAP adapter:
10205 * Instead of opening an adapter, we could just do a SME open session
10206 * for AP type. But, start BSS would still need an adapter.
10207 * So, this option is not taken.
10208 *
10209 * hdd open adapter is going to register this precac interface with
10210 * user space. This interface though exposed to user space will be in
10211 * DOWN state. Consideration was done to avoid this registration to the
10212 * user space. But, as part of SAP operations multiple events are sent
10213 * to user space. Some of these events received from unregistered
10214 * interface was causing crashes. So, retaining the registration.
10215 *
10216 * So, this interface would remain registered and will remain in DOWN
10217 * state for the CAC duration. We will add notes in the feature
10218 * announcement to not use this temporary interface for any activity
10219 * from user space.
10220 */
10221 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -080010222 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010223 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +053010224 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -080010225 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010226 }
10227
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +053010228 /*
10229 * This interface is internally created by the driver. So, no interface
10230 * up comes for this interface from user space and hence starting
10231 * the adapter internally.
10232 */
10233 if (hdd_start_adapter(pre_cac_adapter)) {
10234 hdd_err("error starting the pre cac adapter");
10235 goto close_pre_cac_adapter;
10236 }
10237
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010238 hdd_debug("preparing for start ap/bss on the pre cac adapter");
10239
10240 wiphy = hdd_ctx->wiphy;
10241 dev = pre_cac_adapter->dev;
10242
10243 /* Since this is only a dummy interface lets us use the IEs from the
10244 * other active SAP interface. In regular scenarios, these IEs would
10245 * come from the user space entity
10246 */
Jeff Johnsonb9424862017-10-30 08:49:35 -070010247 pre_cac_adapter->session.ap.beacon = qdf_mem_malloc(
10248 sizeof(*ap_adapter->session.ap.beacon));
10249 if (!pre_cac_adapter->session.ap.beacon) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010250 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +053010251 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010252 }
Jeff Johnsonb9424862017-10-30 08:49:35 -070010253 qdf_mem_copy(pre_cac_adapter->session.ap.beacon,
10254 ap_adapter->session.ap.beacon,
10255 sizeof(*pre_cac_adapter->session.ap.beacon));
10256 pre_cac_adapter->session.ap.sap_config.ch_width_orig =
10257 ap_adapter->session.ap.sap_config.ch_width_orig;
10258 pre_cac_adapter->session.ap.sap_config.authType =
10259 ap_adapter->session.ap.sap_config.authType;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010260
10261 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
10262 * to operate on the same bandwidth as that of the 2.4GHz operations.
10263 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
10264 */
Jeff Johnsonb9424862017-10-30 08:49:35 -070010265 switch (ap_adapter->session.ap.sap_config.ch_width_orig) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010266 case CH_WIDTH_20MHZ:
10267 channel_type = NL80211_CHAN_HT20;
10268 break;
10269 case CH_WIDTH_40MHZ:
Jeff Johnsonb9424862017-10-30 08:49:35 -070010270 if (ap_adapter->session.ap.sap_config.sec_ch >
10271 ap_adapter->session.ap.sap_config.channel)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010272 channel_type = NL80211_CHAN_HT40PLUS;
10273 else
10274 channel_type = NL80211_CHAN_HT40MINUS;
10275 break;
10276 default:
10277 channel_type = NL80211_CHAN_NO_HT;
10278 break;
10279 }
10280
10281 freq = cds_chan_to_freq(pre_cac_chan);
Dustin Brown2eb1e452017-08-15 12:40:34 -070010282 chan = ieee80211_get_channel(wiphy, freq);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010283 if (!chan) {
10284 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +053010285 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010286 }
10287
10288 cfg80211_chandef_create(&chandef, chan, channel_type);
10289
10290 hdd_debug("orig width:%d channel_type:%d freq:%d",
Jeff Johnsonb9424862017-10-30 08:49:35 -070010291 ap_adapter->session.ap.sap_config.ch_width_orig,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010292 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -080010293 /*
10294 * Doing update after opening and starting pre-cac adapter will make
10295 * sure that driver won't do hardware mode change if there are any
10296 * initial hick-ups or issues in pre-cac adapter's configuration.
10297 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
10298 * connection update should result in DBS mode
10299 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080010300 status = policy_mgr_update_and_wait_for_connection_update(
Tushnim Bhattacharyya3b99f4b2018-03-26 14:19:24 -070010301 hdd_ctx->hdd_psoc,
10302 ap_adapter->session_id,
10303 pre_cac_chan,
10304 POLICY_MGR_UPDATE_REASON_PRE_CAC);
Krunal Sonib37bb352016-12-20 14:12:21 -080010305 if (QDF_IS_STATUS_ERROR(status)) {
10306 hdd_err("error in moving to DBS mode");
10307 goto stop_close_pre_cac_adapter;
10308 }
10309
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010310
10311 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
10312 if (0 != ret) {
10313 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +053010314 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010315 }
10316
10317 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
10318 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Mahesh Kumar Kalikot Veetilc637fc92017-09-27 16:06:21 -070010319 NL80211_HIDDEN_SSID_NOT_IN_USE, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010320 if (QDF_IS_STATUS_ERROR(status)) {
10321 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +053010322 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010323 }
10324
10325 /*
10326 * The pre cac status is set here. But, it would not be reset explicitly
10327 * anywhere, since after the pre cac success/failure, the pre cac
10328 * adapter itself would be removed.
10329 */
10330 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
10331 if (0 != ret) {
10332 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +053010333 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010334 }
10335
10336 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
Jeff Johnson01206862017-10-27 20:55:59 -070010337 hdd_ap_ctx->operating_channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010338 if (0 != ret) {
10339 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +053010340 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010341 }
10342
10343 ap_adapter->pre_cac_chan = pre_cac_chan;
10344
10345 return 0;
10346
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +053010347stop_close_pre_cac_adapter:
Dustin Browndb2a8be2017-12-20 11:49:56 -080010348 hdd_stop_adapter(hdd_ctx, pre_cac_adapter);
Jeff Johnsonb9424862017-10-30 08:49:35 -070010349 qdf_mem_free(pre_cac_adapter->session.ap.beacon);
10350 pre_cac_adapter->session.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +053010351close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010352 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -080010353release_intf_addr_and_return_failure:
10354 /*
10355 * Release the interface address as the adapter
10356 * failed to start, if you don't release then next
10357 * adapter which is trying to come wouldn't get valid
10358 * mac address. Remember we have limited pool of mac addresses
10359 */
10360 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010361 return -EINVAL;
10362}
10363
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010364static const struct nla_policy
10365wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
10366 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
Ganesh Kondabattini099e6e82017-06-28 12:24:20 +053010367 [QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST] = {
10368 .type = NLA_NESTED },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010369};
10370
Agrawal Ashish65634612016-08-18 13:24:32 +053010371static const struct nla_policy
10372wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
10373 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
10374 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
10375};
10376
Ganesh Kondabattinib1960e72017-09-01 09:09:50 +053010377static const struct nla_policy
10378wlan_hdd_set_limit_off_channel_param_policy
10379[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_MAX + 1] = {
10380 [QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS] = {.type = NLA_U8 },
10381 [QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_START] = {.type = NLA_U8 },
10382};
10383
Agrawal Ashish65634612016-08-18 13:24:32 +053010384/**
10385 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
10386 * @wiphy: Pointer to wireless phy
10387 * @wdev: Pointer to wireless device
10388 * @data: Pointer to data
10389 * @data_len: Length of @data
10390 *
10391 * This function parses the incoming NL vendor command data attributes and
10392 * updates the SAP context about channel_hint and DFS mode.
10393 * If channel_hint is set, SAP will choose that channel
10394 * as operating channel.
10395 *
10396 * If DFS mode is enabled, driver will include DFS channels
10397 * in ACS else driver will skip DFS channels.
10398 *
10399 * Return: 0 on success, negative errno on failure
10400 */
10401static int
10402__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
10403 struct wireless_dev *wdev,
10404 const void *data, int data_len)
10405{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010406 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashish65634612016-08-18 13:24:32 +053010407 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
10408 int ret;
10409 struct acs_dfs_policy *acs_policy;
10410 int mode = DFS_MODE_NONE;
10411 int channel_hint = 0;
10412
Dustin Brownfdf17c12018-03-14 12:55:34 -070010413 hdd_enter_dev(wdev->netdev);
Agrawal Ashish65634612016-08-18 13:24:32 +053010414
10415 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
10416 hdd_err("Command not allowed in FTM mode");
10417 return -EINVAL;
10418 }
10419
10420 ret = wlan_hdd_validate_context(hdd_ctx);
10421 if (0 != ret)
10422 return ret;
10423
Dustin Brown4ea21db2018-01-05 14:13:17 -080010424 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
10425 data, data_len,
10426 wlan_hdd_set_acs_dfs_config_policy)) {
Agrawal Ashish65634612016-08-18 13:24:32 +053010427 hdd_err("invalid attr");
10428 return -EINVAL;
10429 }
10430
10431 acs_policy = &hdd_ctx->acs_policy;
10432 /*
10433 * SCM sends this attribute to restrict SAP from choosing
10434 * DFS channels from ACS.
10435 */
10436 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
10437 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
10438
10439 if (!IS_DFS_MODE_VALID(mode)) {
10440 hdd_err("attr acs dfs mode is not valid");
10441 return -EINVAL;
10442 }
10443 acs_policy->acs_dfs_mode = mode;
10444
10445 /*
10446 * SCM sends this attribute to provide an active channel,
10447 * to skip redundant ACS between drivers, and save driver start up time
10448 */
10449 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
10450 channel_hint = nla_get_u8(
10451 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
10452
10453 if (!IS_CHANNEL_VALID(channel_hint)) {
10454 hdd_err("acs channel is not valid");
10455 return -EINVAL;
10456 }
10457 acs_policy->acs_channel = channel_hint;
10458
10459 return 0;
10460}
10461
10462/**
10463 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
10464 * @wiphy: wiphy structure pointer
10465 * @wdev: Wireless device structure pointer
10466 * @data: Pointer to the data received
10467 * @data_len: Length of @data
10468 *
10469 * This function parses the incoming NL vendor command data attributes and
10470 * updates the SAP context about channel_hint and DFS mode.
10471 *
10472 * Return: 0 on success; errno on failure
10473 */
10474static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
10475 struct wireless_dev *wdev,
10476 const void *data, int data_len)
10477{
10478 int ret;
10479
10480 cds_ssr_protect(__func__);
10481 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
10482 cds_ssr_unprotect(__func__);
10483
10484 return ret;
10485}
10486
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010487/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010488 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
10489 * @mode : cfg80211 dfs mode
10490 *
10491 * Return: return csr sta roam dfs mode else return NONE
10492 */
10493static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
10494 enum dfs_mode mode)
10495{
10496 switch (mode) {
10497 case DFS_MODE_ENABLE:
10498 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010499 case DFS_MODE_DISABLE:
10500 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010501 case DFS_MODE_DEPRIORITIZE:
10502 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010503 default:
10504 hdd_err("STA Roam policy dfs mode is NONE");
10505 return CSR_STA_ROAM_POLICY_NONE;
10506 }
10507}
10508
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010509/*
10510 * hdd_get_sap_operating_band: Get current operating channel
10511 * for sap.
10512 * @hdd_ctx: hdd context
10513 *
10514 * Return : Corresponding band for SAP operating channel
10515 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010516uint8_t hdd_get_sap_operating_band(struct hdd_context *hdd_ctx)
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010517{
Jeff Johnsone5006672017-08-29 14:39:02 -070010518 struct hdd_adapter *adapter;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010519 uint8_t operating_channel = 0;
10520 uint8_t sap_operating_band = 0;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070010521
Dustin Brown920397d2017-12-13 16:27:50 -080010522 hdd_for_each_adapter(hdd_ctx, adapter) {
10523 if (adapter->device_mode != QDF_SAP_MODE)
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010524 continue;
Dustin Brown920397d2017-12-13 16:27:50 -080010525
Jeff Johnsonb9424862017-10-30 08:49:35 -070010526 operating_channel = adapter->session.ap.operating_channel;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010527 if (IS_24G_CH(operating_channel))
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080010528 sap_operating_band = BAND_2G;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010529 else if (IS_5G_CH(operating_channel))
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080010530 sap_operating_band = BAND_5G;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010531 else
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080010532 sap_operating_band = BAND_ALL;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010533 }
Dustin Brown920397d2017-12-13 16:27:50 -080010534
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010535 return sap_operating_band;
10536}
10537
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010538static const struct nla_policy
10539wlan_hdd_set_sta_roam_config_policy[
10540QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
10541 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
10542 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
10543};
10544
10545/**
10546 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
10547 * for station connection or roaming.
10548 * @wiphy: Pointer to wireless phy
10549 * @wdev: Pointer to wireless device
10550 * @data: Pointer to data
10551 * @data_len: Length of @data
10552 *
10553 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
10554 * channels needs to be skipped in scanning or not.
10555 * If dfs_mode is disabled, driver will not scan DFS channels.
10556 * If skip_unsafe_channels is set, driver will skip unsafe channels
10557 * in Scanning.
10558 *
10559 * Return: 0 on success, negative errno on failure
10560 */
10561static int
10562__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
10563 struct wireless_dev *wdev,
10564 const void *data, int data_len)
10565{
10566 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -070010567 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010568 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010569 struct nlattr *tb[
10570 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
10571 int ret;
10572 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
10573 enum dfs_mode mode = DFS_MODE_NONE;
10574 bool skip_unsafe_channels = false;
10575 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010576 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010577
Dustin Brownfdf17c12018-03-14 12:55:34 -070010578 hdd_enter_dev(dev);
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010579
10580 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
10581 hdd_err("Command not allowed in FTM mode");
10582 return -EINVAL;
10583 }
10584
10585 ret = wlan_hdd_validate_context(hdd_ctx);
10586 if (0 != ret)
10587 return ret;
Dustin Brown4ea21db2018-01-05 14:13:17 -080010588 if (wlan_cfg80211_nla_parse(tb,
10589 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
10590 data, data_len,
10591 wlan_hdd_set_sta_roam_config_policy)) {
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010592 hdd_err("invalid attr");
10593 return -EINVAL;
10594 }
10595 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
10596 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
10597 if (!IS_DFS_MODE_VALID(mode)) {
10598 hdd_err("attr sta roam dfs mode policy is not valid");
10599 return -EINVAL;
10600 }
10601
10602 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
10603
10604 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
10605 skip_unsafe_channels = nla_get_u8(
10606 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010607 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010608 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Jeff Johnson1b780e42017-10-31 14:11:45 -070010609 skip_unsafe_channels, adapter->session_id,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010610 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010611
10612 if (!QDF_IS_STATUS_SUCCESS(status)) {
10613 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
10614 return -EINVAL;
10615 }
10616 return 0;
10617}
10618
10619/**
10620 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
10621 * connection and roaming for station.
10622 * @wiphy: wiphy structure pointer
10623 * @wdev: Wireless device structure pointer
10624 * @data: Pointer to the data received
10625 * @data_len: Length of @data
10626 *
10627 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
10628 * channels needs to be skipped in scanning or not.
10629 * If dfs_mode is disabled, driver will not scan DFS channels.
10630 * If skip_unsafe_channels is set, driver will skip unsafe channels
10631 * in Scanning.
10632 * Return: 0 on success; errno on failure
10633 */
10634static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
10635 struct wireless_dev *wdev,
10636 const void *data, int data_len)
10637{
10638 int ret;
10639
10640 cds_ssr_protect(__func__);
10641 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
10642 cds_ssr_unprotect(__func__);
10643
10644 return ret;
10645}
10646
Agrawal Ashish467dde42016-09-08 18:44:22 +053010647#ifdef FEATURE_WLAN_CH_AVOID
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010648
10649static int hdd_validate_avoid_freq_chanlist(
10650 struct hdd_context *hdd_ctx,
10651 struct ch_avoid_ind_type *channel_list)
10652{
10653 unsigned int range_idx, ch_idx;
10654 unsigned int unsafe_channel_index, unsafe_channel_count = 0;
10655 bool ch_found = false;
10656
10657 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
10658 (uint16_t)NUM_CHANNELS);
10659
10660 for (range_idx = 0; range_idx < channel_list->ch_avoid_range_cnt;
10661 range_idx++) {
10662 if ((channel_list->avoid_freq_range[range_idx].start_freq <
10663 CDS_24_GHZ_CHANNEL_1) ||
10664 (channel_list->avoid_freq_range[range_idx].end_freq >
10665 CDS_5_GHZ_CHANNEL_165) ||
10666 (channel_list->avoid_freq_range[range_idx].start_freq >
10667 channel_list->avoid_freq_range[range_idx].end_freq))
10668 continue;
10669
10670 for (ch_idx = channel_list->
10671 avoid_freq_range[range_idx].start_freq;
10672 ch_idx <= channel_list->
10673 avoid_freq_range[range_idx].end_freq;
10674 ch_idx++) {
10675 for (unsafe_channel_index = 0;
10676 unsafe_channel_index < unsafe_channel_count;
10677 unsafe_channel_index++) {
10678 if (ch_idx ==
10679 hdd_ctx->unsafe_channel_list[
10680 unsafe_channel_index]) {
Dustin Brown632af712018-03-14 15:03:55 -070010681 hdd_info("Duplicate channel %d",
10682 ch_idx);
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010683 ch_found = true;
10684 break;
10685 }
10686 }
10687 if (!ch_found) {
10688 hdd_ctx->unsafe_channel_list[
10689 unsafe_channel_count++] = ch_idx;
10690 }
10691 ch_found = false;
10692 }
10693 }
10694 return unsafe_channel_count;
10695}
10696
Agrawal Ashish467dde42016-09-08 18:44:22 +053010697/**
10698 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
10699 * is on unsafe channel.
10700 * @wiphy: wiphy structure pointer
10701 * @wdev: Wireless device structure pointer
10702 * @data: Pointer to the data received
10703 * @data_len: Length of @data
10704 *
10705 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
10706 * on any of unsafe channels.
10707 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
10708 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
10709 *
10710 * Return: 0 on success; errno on failure
10711 */
10712static int
10713__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
10714 struct wireless_dev *wdev,
10715 const void *data, int data_len)
10716{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010717 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashish467dde42016-09-08 18:44:22 +053010718 int ret;
Agrawal Ashish467dde42016-09-08 18:44:22 +053010719 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
Liangwei Dong6e1a2092017-08-30 16:29:06 +080010720 uint16_t *local_unsafe_list;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010721 uint16_t unsafe_channel_index, local_unsafe_list_count;
10722 struct ch_avoid_ind_type *channel_list;
Jeff Johnson2e60a142018-05-20 12:08:12 -070010723 enum QDF_GLOBAL_MODE curr_mode;
Agrawal Ashish467dde42016-09-08 18:44:22 +053010724
Dustin Brownfdf17c12018-03-14 12:55:34 -070010725 hdd_enter_dev(wdev->netdev);
Agrawal Ashish467dde42016-09-08 18:44:22 +053010726
10727 if (!qdf_ctx) {
Jeff Johnson6867ec32017-09-29 20:30:20 -070010728 hdd_err("qdf_ctx is NULL");
Agrawal Ashish467dde42016-09-08 18:44:22 +053010729 return -EINVAL;
10730 }
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010731 curr_mode = hdd_get_conparam();
10732 if (QDF_GLOBAL_FTM_MODE == curr_mode ||
10733 QDF_GLOBAL_MONITOR_MODE == curr_mode) {
10734 hdd_err("Command not allowed in FTM/MONITOR mode");
Agrawal Ashish467dde42016-09-08 18:44:22 +053010735 return -EINVAL;
10736 }
10737
10738 ret = wlan_hdd_validate_context(hdd_ctx);
10739 if (0 != ret)
10740 return ret;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010741
10742 channel_list = (struct ch_avoid_ind_type *)data;
10743 if (!channel_list) {
Dustin Brown632af712018-03-14 15:03:55 -070010744 hdd_err("Avoid frequency channel list empty");
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010745 return -EINVAL;
10746 }
10747
Liangwei Dong6e1a2092017-08-30 16:29:06 +080010748 ret = hdd_clone_local_unsafe_chan(hdd_ctx,
10749 &local_unsafe_list,
10750 &local_unsafe_list_count);
10751 if (0 != ret) {
10752 hdd_err("failed to clone the cur unsafe chan list");
10753 return ret;
10754 }
10755
Agrawal Ashish467dde42016-09-08 18:44:22 +053010756 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
10757 &(hdd_ctx->unsafe_channel_count),
10758 sizeof(hdd_ctx->unsafe_channel_list));
10759
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010760 hdd_ctx->unsafe_channel_count = hdd_validate_avoid_freq_chanlist(
10761 hdd_ctx,
10762 channel_list);
10763
10764 pld_set_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
10765 hdd_ctx->unsafe_channel_count);
10766
Agrawal Ashish467dde42016-09-08 18:44:22 +053010767 for (unsafe_channel_index = 0;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010768 unsafe_channel_index < hdd_ctx->unsafe_channel_count;
10769 unsafe_channel_index++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010770 hdd_debug("Channel %d is not safe",
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010771 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
Agrawal Ashish467dde42016-09-08 18:44:22 +053010772 }
Liangwei Dong6e1a2092017-08-30 16:29:06 +080010773 if (hdd_local_unsafe_channel_updated(hdd_ctx, local_unsafe_list,
10774 local_unsafe_list_count))
10775 hdd_unsafe_channel_restart_sap(hdd_ctx);
10776 qdf_mem_free(local_unsafe_list);
10777
Agrawal Ashish467dde42016-09-08 18:44:22 +053010778 return 0;
10779}
10780
10781/**
10782 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
10783 * is on unsafe channel.
10784 * @wiphy: wiphy structure pointer
10785 * @wdev: Wireless device structure pointer
10786 * @data: Pointer to the data received
10787 * @data_len: Length of @data
10788 *
10789 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
10790 * on any of unsafe channels.
10791 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
10792 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
10793 *
10794 * Return: 0 on success; errno on failure
10795 */
10796static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
10797 struct wireless_dev *wdev,
10798 const void *data, int data_len)
10799{
10800 int ret;
10801
10802 cds_ssr_protect(__func__);
10803 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
10804 cds_ssr_unprotect(__func__);
10805
10806 return ret;
10807}
10808
10809#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010810/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010811 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
10812 * SAP is on unsafe channel.
10813 * @wiphy: wiphy structure pointer
10814 * @wdev: Wireless device structure pointer
10815 * @data: Pointer to the data received
10816 * @data_len: Length of @data
10817 *
10818 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
10819 * driver.
10820 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
10821 * will initiate restart of sap.
10822 *
10823 * Return: 0 on success; errno on failure
10824 */
10825static int
10826__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
10827 struct wireless_dev *wdev,
10828 const void *data, int data_len)
10829{
10830 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -070010831 struct hdd_adapter *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010832 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010833 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
10834 uint8_t config_channel = 0;
Jeff Johnson87251032017-08-29 13:31:11 -070010835 struct hdd_ap_ctx *ap_ctx;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010836 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +053010837 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010838
Dustin Brown491d54b2018-03-14 12:39:11 -070010839 hdd_enter();
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010840
10841 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010842 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010843 return -EINVAL;
10844 }
10845
10846 ret = wlan_hdd_validate_context(hdd_ctx);
10847 if (0 != ret)
10848 return -EINVAL;
10849
Dustin Brown4ea21db2018-01-05 14:13:17 -080010850 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
10851 data, data_len,
10852 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010853 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010854 return -EINVAL;
10855 }
10856
10857 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
10858 if (!test_bit(SOFTAP_BSS_STARTED,
10859 &hostapd_adapter->event_flags)) {
10860 hdd_err("SAP is not started yet. Restart sap will be invalid");
10861 return -EINVAL;
10862 }
10863
10864 config_channel =
10865 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
10866
10867 if (!((IS_24G_CH(config_channel)) ||
10868 (IS_5G_CH(config_channel)))) {
10869 hdd_err("Channel %d is not valid to restart SAP",
10870 config_channel);
10871 return -ENOTSUPP;
10872 }
10873
10874 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
Jeff Johnson91df29d2017-10-27 19:29:50 -070010875 ap_ctx->sap_config.channel = config_channel;
10876 ap_ctx->sap_config.ch_params.ch_width =
10877 ap_ctx->sap_config.ch_width_orig;
hqu73bccf22017-10-28 15:34:17 +080010878 ap_ctx->bss_stop_reason = BSS_STOP_DUE_TO_VENDOR_CONFIG_CHAN;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010879
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010880 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev,
Jeff Johnson91df29d2017-10-27 19:29:50 -070010881 ap_ctx->sap_config.channel,
10882 ap_ctx->sap_config.sec_ch,
10883 &ap_ctx->sap_config.ch_params);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010884
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080010885 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010886 }
10887
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +053010888 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
10889 uint32_t freq_len, i;
10890 uint32_t *freq;
10891 uint8_t chans[QDF_MAX_NUM_CHAN];
10892
10893 hdd_debug("setting mandatory freq/chan list");
10894
10895 freq_len = nla_len(
10896 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
10897 sizeof(uint32_t);
10898
10899 if (freq_len > QDF_MAX_NUM_CHAN) {
10900 hdd_err("insufficient space to hold channels");
10901 return -ENOMEM;
10902 }
10903
10904 freq = nla_data(
10905 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
10906
10907 hdd_debug("freq_len=%d", freq_len);
10908
10909 for (i = 0; i < freq_len; i++) {
10910 chans[i] = ieee80211_frequency_to_channel(freq[i]);
10911 hdd_debug("freq[%d]=%d", i, freq[i]);
10912 }
10913
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080010914 status = policy_mgr_set_sap_mandatory_channels(
10915 hdd_ctx->hdd_psoc, chans, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +053010916 if (QDF_IS_STATUS_ERROR(status))
10917 return -EINVAL;
10918 }
10919
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010920 return 0;
10921}
10922
10923/**
10924 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
10925 * @wiphy: wiphy structure pointer
10926 * @wdev: Wireless device structure pointer
10927 * @data: Pointer to the data received
10928 * @data_len: Length of @data
10929 *
10930 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
10931 * driver.
10932 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
10933 * will initiate restart of sap.
10934 *
10935 * Return: 0 on success; errno on failure
10936 */
10937static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
10938 struct wireless_dev *wdev,
10939 const void *data, int data_len)
10940{
10941 int ret;
10942
10943 cds_ssr_protect(__func__);
10944 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
10945 wdev, data, data_len);
10946 cds_ssr_unprotect(__func__);
10947
10948 return ret;
10949}
10950
Arun Khandavalli2476ef52016-04-26 20:19:43 +053010951#undef BPF_INVALID
10952#undef BPF_SET_RESET
10953#undef BPF_VERSION
10954#undef BPF_ID
10955#undef BPF_PACKET_SIZE
10956#undef BPF_CURRENT_OFFSET
10957#undef BPF_PROGRAM
10958#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010959
Naveen Rawat3ff5cff2018-01-29 14:31:16 -080010960#ifndef QCA_SUPPORT_CP_STATS
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010961/**
10962 * define short names for the global vendor params
10963 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
10964 */
10965#define PARAM_TOTAL_CMD_EVENT_WAKE \
10966 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
10967#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
10968 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
10969#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
10970 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
10971#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
10972 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
10973#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
10974 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
10975#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
10976 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
10977#define PARAM_TOTAL_RX_DATA_WAKE \
10978 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
10979#define PARAM_RX_UNICAST_CNT \
10980 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
10981#define PARAM_RX_MULTICAST_CNT \
10982 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
10983#define PARAM_RX_BROADCAST_CNT \
10984 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
10985#define PARAM_ICMP_PKT \
10986 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
10987#define PARAM_ICMP6_PKT \
10988 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
10989#define PARAM_ICMP6_RA \
10990 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
10991#define PARAM_ICMP6_NA \
10992 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
10993#define PARAM_ICMP6_NS \
10994 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
10995#define PARAM_ICMP4_RX_MULTICAST_CNT \
10996 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
10997#define PARAM_ICMP6_RX_MULTICAST_CNT \
10998 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
10999#define PARAM_OTHER_RX_MULTICAST_CNT \
11000 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +053011001#define PARAM_RSSI_BREACH_CNT \
11002 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
11003#define PARAM_LOW_RSSI_CNT \
11004 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
11005#define PARAM_GSCAN_CNT \
11006 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
11007#define PARAM_PNO_COMPLETE_CNT \
11008 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
11009#define PARAM_PNO_MATCH_CNT \
11010 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
11011
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011012/**
11013 * hdd_send_wakelock_stats() - API to send wakelock stats
11014 * @ctx: context to be passed to callback
11015 * @data: data passed to callback
11016 *
11017 * This function is used to send wake lock stats to HAL layer
11018 *
11019 * Return: 0 on success, error number otherwise.
11020 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011021static uint32_t hdd_send_wakelock_stats(struct hdd_context *hdd_ctx,
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011022 const struct sir_wake_lock_stats *data)
11023{
11024 struct sk_buff *skb;
11025 uint32_t nl_buf_len;
11026 uint32_t total_rx_data_wake, rx_multicast_cnt;
11027 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +053011028 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011029
Dustin Brown491d54b2018-03-14 12:39:11 -070011030 hdd_enter();
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011031
11032 nl_buf_len = NLMSG_HDRLEN;
11033 nl_buf_len +=
11034 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
11035 (NLMSG_HDRLEN + sizeof(uint32_t));
11036
11037 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
11038
11039 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -070011040 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011041 return -ENOMEM;
11042 }
11043
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011044 hdd_debug("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011045 data->wow_ucast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011046 hdd_debug("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011047 data->wow_bcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011048 hdd_debug("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011049 data->wow_ipv4_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011050 hdd_debug("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011051 data->wow_ipv6_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011052 hdd_debug("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011053 data->wow_ipv6_mcast_ra_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011054 hdd_debug("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011055 data->wow_ipv6_mcast_ns_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011056 hdd_debug("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011057 data->wow_ipv6_mcast_na_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011058 hdd_debug("wow_icmpv4_count %d", data->wow_icmpv4_count);
11059 hdd_debug("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +053011060 data->wow_icmpv6_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011061 hdd_debug("wow_rssi_breach_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +053011062 data->wow_rssi_breach_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011063 hdd_debug("wow_low_rssi_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +053011064 data->wow_low_rssi_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011065 hdd_debug("wow_gscan_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +053011066 data->wow_gscan_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011067 hdd_debug("wow_pno_complete_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +053011068 data->wow_pno_complete_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011069 hdd_debug("wow_pno_match_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +053011070 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011071
11072 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +053011073 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011074
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +053011075 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +053011076 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +053011077
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011078 rx_multicast_cnt =
11079 data->wow_ipv4_mcast_wake_up_count +
11080 ipv6_rx_multicast_addr_cnt;
11081
11082 total_rx_data_wake =
11083 data->wow_ucast_wake_up_count +
11084 data->wow_bcast_wake_up_count +
11085 rx_multicast_cnt;
11086
11087 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
11088 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
11089 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
11090 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
11091 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
11092 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
11093 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
11094 total_rx_data_wake) ||
11095 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
11096 data->wow_ucast_wake_up_count) ||
11097 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
11098 rx_multicast_cnt) ||
11099 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
11100 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +053011101 nla_put_u32(skb, PARAM_ICMP_PKT,
11102 data->wow_icmpv4_count) ||
11103 nla_put_u32(skb, PARAM_ICMP6_PKT,
11104 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011105 nla_put_u32(skb, PARAM_ICMP6_RA,
11106 data->wow_ipv6_mcast_ra_stats) ||
11107 nla_put_u32(skb, PARAM_ICMP6_NA,
11108 data->wow_ipv6_mcast_na_stats) ||
11109 nla_put_u32(skb, PARAM_ICMP6_NS,
11110 data->wow_ipv6_mcast_ns_stats) ||
11111 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
11112 data->wow_ipv4_mcast_wake_up_count) ||
11113 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
11114 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +053011115 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
11116 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
11117 data->wow_rssi_breach_wake_up_count) ||
11118 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
11119 data->wow_low_rssi_wake_up_count) ||
11120 nla_put_u32(skb, PARAM_GSCAN_CNT,
11121 data->wow_gscan_wake_up_count) ||
11122 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
11123 data->wow_pno_complete_wake_up_count) ||
11124 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
11125 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -070011126 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011127 goto nla_put_failure;
11128 }
11129
11130 cfg80211_vendor_cmd_reply(skb);
11131
Dustin Browne74003f2018-03-14 12:51:58 -070011132 hdd_exit();
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011133 return 0;
11134
11135nla_put_failure:
11136 kfree_skb(skb);
11137 return -EINVAL;
11138}
Naveen Rawat3ff5cff2018-01-29 14:31:16 -080011139#endif
11140
11141#ifdef QCA_SUPPORT_CP_STATS
11142static int wlan_hdd_process_wake_lock_stats(struct hdd_context *hdd_ctx)
11143{
11144 return wlan_cfg80211_mc_cp_stats_get_wakelock_stats(hdd_ctx->hdd_psoc,
11145 hdd_ctx->wiphy);
11146}
11147#else
11148/**
11149 * wlan_hdd_process_wake_lock_stats() - wrapper function to absract cp_stats
11150 * or legacy get_wake_lock_stats API.
11151 * @hdd_ctx: pointer to hdd_ctx
11152 *
11153 * Return: 0 on success; error number otherwise.
11154 */
11155static int wlan_hdd_process_wake_lock_stats(struct hdd_context *hdd_ctx)
11156{
11157 int ret;
11158 QDF_STATUS qdf_status;
11159 struct sir_wake_lock_stats wake_lock_stats = {0};
11160
11161 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
11162 if (qdf_status != QDF_STATUS_SUCCESS) {
11163 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
11164 return -EINVAL;
11165 }
11166
11167 ret = hdd_send_wakelock_stats(hdd_ctx, &wake_lock_stats);
11168 if (ret)
11169 hdd_err("Failed to post wake lock stats");
11170
11171 return ret;
11172}
11173#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011174
11175/**
11176 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
11177 * @wiphy: wiphy pointer
11178 * @wdev: pointer to struct wireless_dev
11179 * @data: pointer to incoming NL vendor data
11180 * @data_len: length of @data
11181 *
11182 * This function parses the incoming NL vendor command data attributes and
11183 * invokes the SME Api and blocks on a completion variable.
11184 * WMA copies required data and invokes callback
11185 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
11186 *
11187 * Return: 0 on success; error number otherwise.
11188 */
11189static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
11190 struct wireless_dev *wdev,
11191 const void *data,
11192 int data_len)
11193{
Naveen Rawat3ff5cff2018-01-29 14:31:16 -080011194 int ret;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011195 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011196
Dustin Brown491d54b2018-03-14 12:39:11 -070011197 hdd_enter();
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011198
11199 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -070011200 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011201 return -EINVAL;
11202 }
11203
Naveen Rawat3ff5cff2018-01-29 14:31:16 -080011204 ret = wlan_hdd_validate_context(hdd_ctx);
11205 if (0 != ret)
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011206 return -EINVAL;
11207
Naveen Rawat3ff5cff2018-01-29 14:31:16 -080011208 ret = wlan_hdd_process_wake_lock_stats(hdd_ctx);
Dustin Browne74003f2018-03-14 12:51:58 -070011209 hdd_exit();
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011210 return ret;
11211}
11212
11213/**
11214 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
11215 * @wiphy: wiphy pointer
11216 * @wdev: pointer to struct wireless_dev
11217 * @data: pointer to incoming NL vendor data
11218 * @data_len: length of @data
11219 *
11220 * This function parses the incoming NL vendor command data attributes and
11221 * invokes the SME Api and blocks on a completion variable.
11222 * WMA copies required data and invokes callback
11223 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
11224 *
11225 * Return: 0 on success; error number otherwise.
11226 */
11227static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
11228 struct wireless_dev *wdev,
11229 const void *data, int data_len)
11230{
11231 int ret;
11232
11233 cds_ssr_protect(__func__);
11234 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
11235 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -070011236 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011237
11238 return ret;
11239}
11240
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011241/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011242 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
11243 * @wiphy: wiphy structure pointer
11244 * @wdev: Wireless device structure pointer
11245 * @data: Pointer to the data received
11246 * @data_len: Length of @data
11247 *
11248 * This function reads wmi max bus size and fill in the skb with
11249 * NL attributes and send up the NL event.
11250 * Return: 0 on success; errno on failure
11251 */
11252static int
11253__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
11254 struct wireless_dev *wdev,
11255 const void *data, int data_len)
11256{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011257 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011258 int ret_val;
11259 struct sk_buff *skb;
11260 uint32_t nl_buf_len;
11261
Dustin Brown491d54b2018-03-14 12:39:11 -070011262 hdd_enter();
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011263
11264 ret_val = wlan_hdd_validate_context(hdd_ctx);
11265 if (ret_val)
11266 return ret_val;
11267
11268 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
11269 hdd_err("Command not allowed in FTM mode");
11270 return -EINVAL;
11271 }
11272
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011273 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011274
11275 nl_buf_len = NLMSG_HDRLEN;
11276 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
11277
11278 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
11279 if (!skb) {
11280 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
11281 return -ENOMEM;
11282 }
11283
11284 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
11285 hdd_ctx->wmi_max_len)) {
11286 hdd_err("nla put failure");
11287 goto nla_put_failure;
11288 }
11289
11290 cfg80211_vendor_cmd_reply(skb);
11291
Dustin Browne74003f2018-03-14 12:51:58 -070011292 hdd_exit();
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011293
11294 return 0;
11295
11296nla_put_failure:
11297 kfree_skb(skb);
11298 return -EINVAL;
11299}
11300
11301/**
11302 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
11303 * @wiphy: wiphy structure pointer
11304 * @wdev: Wireless device structure pointer
11305 * @data: Pointer to the data received
11306 * @data_len: Length of @data
11307 *
11308 * Return: 0 on success; errno on failure
11309 */
11310static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
11311 struct wireless_dev *wdev,
11312 const void *data, int data_len)
11313{
11314 int ret;
11315
11316 cds_ssr_protect(__func__);
11317 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
11318 cds_ssr_unprotect(__func__);
11319
11320 return ret;
11321}
11322
11323/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011324 *__wlan_hdd_cfg80211_setband() - set band
11325 * @wiphy: Pointer to wireless phy
11326 * @wdev: Pointer to wireless device
11327 * @data: Pointer to data
11328 * @data_len: Length of @data
11329 *
11330 * Return: 0 on success, negative errno on failure
11331 */
11332static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
11333 struct wireless_dev *wdev,
11334 const void *data, int data_len)
11335{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011336 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -070011337 struct net_device *dev = wdev->netdev;
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011338 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
11339 int ret;
11340 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
11341 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
11342
Dustin Brown491d54b2018-03-14 12:39:11 -070011343 hdd_enter();
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011344
11345 ret = wlan_hdd_validate_context(hdd_ctx);
11346 if (ret)
11347 return ret;
11348
Dustin Brown4ea21db2018-01-05 14:13:17 -080011349 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX,
11350 data, data_len, policy)) {
Dustin Brownbacc48f2018-03-14 14:48:44 -070011351 hdd_err("Invalid ATTR");
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011352 return -EINVAL;
11353 }
11354
11355 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
Dustin Brownbacc48f2018-03-14 14:48:44 -070011356 hdd_err("attr SETBAND_VALUE failed");
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011357 return -EINVAL;
11358 }
11359
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -070011360 ret = hdd_reg_set_band(dev,
11361 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011362
Dustin Browne74003f2018-03-14 12:51:58 -070011363 hdd_exit();
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011364 return ret;
11365}
11366
11367/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011368 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
11369 * @adapter: hdd adapter
11370 * @channel: channel number
11371 *
11372 * return: QDF status based on success or failure
11373 */
Jeff Johnsone5006672017-08-29 14:39:02 -070011374static QDF_STATUS wlan_hdd_validate_acs_channel(struct hdd_adapter *adapter,
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011375 int channel, int chan_bw)
11376{
11377 if (QDF_STATUS_SUCCESS !=
11378 wlan_hdd_validate_operation_channel(adapter, channel))
11379 return QDF_STATUS_E_FAILURE;
11380 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
11381 channel,
11382 PHY_SINGLE_CHANNEL_CENTERED))) {
Dustin Brown5e89ef82018-03-14 11:50:23 -070011383 hdd_info("channel %d is in nol", channel);
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011384 return -EINVAL;
11385 }
11386
11387 if ((wlansap_is_channel_leaking_in_nol(
11388 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
11389 channel, chan_bw))) {
Dustin Brown5e89ef82018-03-14 11:50:23 -070011390 hdd_info("channel %d is leaking in nol", channel);
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011391 return -EINVAL;
11392 }
11393
11394 return 0;
11395
11396}
11397
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011398static void hdd_update_acs_sap_config(struct hdd_context *hdd_ctx,
Jeff Johnsone4c11db2018-05-05 23:22:32 -070011399 tsap_config_t *sap_config,
Kapil Gupta8878ad92017-02-13 11:56:04 +053011400 struct hdd_vendor_chan_info *channel_list)
11401{
11402 sap_config->channel = channel_list->pri_ch;
11403
11404 sap_config->ch_params.center_freq_seg0 =
11405 channel_list->vht_seg0_center_ch;
11406 sap_config->ch_params.center_freq_seg1 =
11407 channel_list->vht_seg1_center_ch;
11408
11409 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
11410 sap_config->ch_params.ch_width = channel_list->chan_width;
11411 if (sap_config->channel >= 36)
11412 sap_config->ch_width_orig =
11413 hdd_ctx->config->vhtChannelWidth;
11414 else
11415 sap_config->ch_width_orig =
11416 hdd_ctx->config->nChannelBondingMode24GHz ?
11417 eHT_CHANNEL_WIDTH_40MHZ :
11418 eHT_CHANNEL_WIDTH_20MHZ;
11419
11420 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
11421 sap_config->acs_cfg.ch_width = channel_list->chan_width;
11422 sap_config->acs_cfg.vht_seg0_center_ch =
11423 channel_list->vht_seg0_center_ch;
11424 sap_config->acs_cfg.vht_seg1_center_ch =
11425 channel_list->vht_seg1_center_ch;
11426 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
11427}
11428
Jeff Johnsone5006672017-08-29 14:39:02 -070011429static int hdd_update_acs_channel(struct hdd_adapter *adapter, uint8_t reason,
Kapil Gupta8878ad92017-02-13 11:56:04 +053011430 uint8_t channel_cnt,
11431 struct hdd_vendor_chan_info *channel_list)
11432{
Jeff Johnsone4c11db2018-05-05 23:22:32 -070011433 tsap_config_t *sap_config;
Jeff Johnson87251032017-08-29 13:31:11 -070011434 struct hdd_ap_ctx *hdd_ap_ctx;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011435 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011436 QDF_STATUS status = QDF_STATUS_SUCCESS;
11437
Min Liuab6ed4f2018-01-09 13:13:57 +080011438 if (!channel_list) {
11439 hdd_err("channel_list is NULL");
11440 return -EINVAL;
11441 }
11442
Kapil Gupta8878ad92017-02-13 11:56:04 +053011443 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
Jeff Johnsonb9424862017-10-30 08:49:35 -070011444 sap_config = &adapter->session.ap.sap_config;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011445
11446 if (QDF_TIMER_STATE_RUNNING ==
Jeff Johnsonb9424862017-10-30 08:49:35 -070011447 qdf_mc_timer_get_current_state(&adapter->session.
Kapil Gupta8878ad92017-02-13 11:56:04 +053011448 ap.vendor_acs_timer)) {
Jeff Johnsonb9424862017-10-30 08:49:35 -070011449 qdf_mc_timer_stop(&adapter->session.ap.vendor_acs_timer);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011450 }
11451
Min Liuab6ed4f2018-01-09 13:13:57 +080011452 if (channel_list->pri_ch == 0) {
Kapil Gupta8878ad92017-02-13 11:56:04 +053011453 /* Check mode, set default channel */
11454 channel_list->pri_ch = 6;
11455 /*
11456 * sap_select_default_oper_chan(hdd_ctx->hHal,
11457 * sap_config->acs_cfg.hw_mode);
11458 */
11459 }
11460
11461 switch (reason) {
11462 /* SAP init case */
11463 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
11464 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
11465 /* Update Hostapd */
11466 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
11467 break;
11468
11469 /* DFS detected on current channel */
11470 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
11471 wlan_sap_update_next_channel(
11472 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
11473 channel_list->pri_ch,
11474 channel_list->chan_width);
11475 status = sme_update_new_channel_event(
11476 WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -070011477 adapter->session_id);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011478 break;
11479
11480 /* LTE coex event on current channel */
11481 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
11482 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
11483 sap_config->acs_cfg.ch_width = channel_list->chan_width;
Jeff Johnson91df29d2017-10-27 19:29:50 -070011484 hdd_ap_ctx->sap_config.ch_width_orig =
Kapil Gupta8878ad92017-02-13 11:56:04 +053011485 channel_list->chan_width;
Min Liu2fef5792018-01-19 17:59:42 +080011486 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch,
11487 true);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011488 break;
11489
11490 default:
11491 hdd_info("invalid reason for timer invoke");
11492 }
Dustin Browne74003f2018-03-14 12:51:58 -070011493 hdd_exit();
Min Liuab6ed4f2018-01-09 13:13:57 +080011494 return qdf_status_to_os_return(status);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011495}
11496
11497/**
11498 * Define short name for vendor channel set config
11499 */
11500#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
Kapil Gupta8878ad92017-02-13 11:56:04 +053011501#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
11502#define SET_CHAN_PRIMARY_CHANNEL \
11503 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
11504#define SET_CHAN_SECONDARY_CHANNEL \
11505 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
11506#define SET_CHAN_SEG0_CENTER_CHANNEL \
11507 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
11508#define SET_CHAN_SEG1_CENTER_CHANNEL \
11509 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
11510#define SET_CHAN_CHANNEL_WIDTH \
11511 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
11512#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
Kapil Gupta63e75282017-05-18 20:55:10 +053011513#define SET_EXT_ACS_BAND QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_BAND
Kapil Gupta8878ad92017-02-13 11:56:04 +053011514
11515/**
11516 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
11517 * @channel_list: pointer to hdd_vendor_chan_info
11518 * @reason: channel change reason
11519 * @channel_cnt: channel count
11520 * @data: data
11521 * @data_len: data len
11522 *
11523 * Return: 0 on success, negative errno on failure
11524 */
11525static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
11526 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
11527 const void *data, int data_len)
11528{
11529 int rem, i = 0;
11530 struct nlattr *tb[SET_CHAN_MAX + 1];
11531 struct nlattr *tb2[SET_CHAN_MAX + 1];
11532 struct nlattr *curr_attr;
11533 struct hdd_vendor_chan_info *channel_list;
11534
Dustin Brown4ea21db2018-01-05 14:13:17 -080011535 if (wlan_cfg80211_nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
Kapil Gupta8878ad92017-02-13 11:56:04 +053011536 hdd_err("Invalid ATTR");
11537 return -EINVAL;
11538 }
11539
11540 if (tb[SET_CHAN_REASON])
11541 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
11542
Kapil Gupta63e75282017-05-18 20:55:10 +053011543 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem)
11544 i++;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011545
Kapil Gupta63e75282017-05-18 20:55:10 +053011546 *channel_cnt = i;
11547
11548 if (i == 0)
11549 hdd_err("incorrect channel count");
Kapil Gupta8878ad92017-02-13 11:56:04 +053011550
11551 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
11552 (*channel_cnt));
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011553 if (NULL == channel_list) {
11554 hdd_err("Could not allocate for channel_list");
11555 return -ENOMEM;
11556 }
Kapil Gupta8878ad92017-02-13 11:56:04 +053011557
Kapil Gupta63e75282017-05-18 20:55:10 +053011558 i = 0;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011559 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
Dustin Brown4ea21db2018-01-05 14:13:17 -080011560 if (wlan_cfg80211_nla_parse(tb2, SET_CHAN_MAX,
11561 nla_data(curr_attr),
11562 nla_len(curr_attr), NULL)) {
11563 hdd_err("nla_parse failed");
Kapil Gupta8878ad92017-02-13 11:56:04 +053011564 return -EINVAL;
11565 }
Kapil Gupta63e75282017-05-18 20:55:10 +053011566 if (tb2[SET_EXT_ACS_BAND]) {
11567 channel_list[i].band =
11568 nla_get_u8(tb2[SET_EXT_ACS_BAND]);
11569 }
Kapil Gupta8878ad92017-02-13 11:56:04 +053011570 /* Parse and Fetch allowed SSID list*/
11571 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
11572 channel_list[i].pri_ch =
11573 nla_get_u8(
11574 tb2[SET_CHAN_PRIMARY_CHANNEL]);
11575 }
11576 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
11577 channel_list[i].ht_sec_ch =
11578 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
11579 }
11580 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
11581 channel_list[i].vht_seg0_center_ch =
11582 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
11583 }
11584 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
11585 channel_list[i].vht_seg1_center_ch =
11586 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
11587 }
11588 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
11589 channel_list[i].chan_width =
11590 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
11591 }
Kapil Gupta63e75282017-05-18 20:55:10 +053011592 hdd_debug("index %d pri %d sec %d seg0 %d seg1 %d width %d",
Kapil Gupta8878ad92017-02-13 11:56:04 +053011593 i, channel_list[i].pri_ch,
11594 channel_list[i].ht_sec_ch,
11595 channel_list[i].vht_seg0_center_ch,
11596 channel_list[i].vht_seg1_center_ch,
11597 channel_list[i].chan_width);
11598 i++;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011599 }
11600 *chan_list_ptr = channel_list;
11601
11602 return 0;
11603}
11604
11605/**
11606 * Undef short names for vendor set channel configuration
11607 */
11608#undef SET_CHAN_REASON
11609#undef SET_CHAN_CHANNEL_COUNT
11610#undef SET_CHAN_CHAN_LIST
11611#undef SET_CHAN_PRIMARY_CHANNEL
11612#undef SET_CHAN_SECONDARY_CHANNEL
11613#undef SET_CHAN_SEG0_CENTER_CHANNEL
11614#undef SET_CHAN_SEG1_CENTER_CHANNEL
11615#undef SET_CHAN_CHANNEL_WIDTH
11616#undef SET_CHAN_MAX
11617
11618/**
11619 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
11620 * @wiphy: Pointer to wireless phy
11621 * @wdev: Pointer to wireless device
11622 * @data: Pointer to data
11623 * @data_len: Length of @data
11624 *
11625 * Return: 0 on success, negative errno on failure
11626 */
11627static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
11628 struct wireless_dev *wdev,
11629 const void *data, int data_len)
11630{
11631 int ret_val;
11632 QDF_STATUS qdf_status;
11633 uint8_t channel_cnt = 0, reason = -1;
11634 struct hdd_vendor_chan_info *channel_list = NULL;
Jeff Johnsone5006672017-08-29 14:39:02 -070011635 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011636 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011637 struct hdd_vendor_chan_info *channel_list_ptr;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011638
Dustin Brown491d54b2018-03-14 12:39:11 -070011639 hdd_enter();
Kapil Gupta8878ad92017-02-13 11:56:04 +053011640
11641 ret_val = wlan_hdd_validate_context(hdd_ctx);
11642 if (ret_val)
11643 return ret_val;
11644
11645 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
11646 hdd_err("Command not allowed in FTM mode");
11647 return -EINVAL;
11648 }
11649
11650 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
11651 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
11652 else {
11653 hdd_err("already timeout happened for acs");
11654 return -EINVAL;
11655 }
11656
11657 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
11658 &channel_cnt, data, data_len);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011659 channel_list_ptr = channel_list;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011660 if (ret_val)
11661 return ret_val;
11662
11663 /* Validate channel to be set */
11664 while (channel_cnt && channel_list) {
11665 qdf_status = wlan_hdd_validate_acs_channel(adapter,
11666 channel_list->pri_ch,
11667 channel_list->chan_width);
11668 if (qdf_status == QDF_STATUS_SUCCESS)
11669 break;
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011670 else if (channel_cnt == 1) {
11671 hdd_err("invalid channel %d received from app",
11672 channel_list->pri_ch);
11673 channel_list->pri_ch = 0;
11674 break;
11675 }
11676
Kapil Gupta8878ad92017-02-13 11:56:04 +053011677 channel_cnt--;
11678 channel_list++;
11679 }
Min Liuab6ed4f2018-01-09 13:13:57 +080011680
Kapil Gupta8878ad92017-02-13 11:56:04 +053011681 if ((channel_cnt <= 0) || !channel_list) {
Jeff Johnson36e74c42017-09-18 08:15:42 -070011682 hdd_err("no available channel/chanlist %d/%pK", channel_cnt,
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011683 channel_list);
11684 qdf_mem_free(channel_list_ptr);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011685 return -EINVAL;
11686 }
11687
Min Liuab6ed4f2018-01-09 13:13:57 +080011688 hdd_debug("received primary channel as %d", channel_list->pri_ch);
11689
11690 ret_val = hdd_update_acs_channel(adapter, reason,
Kapil Gupta8878ad92017-02-13 11:56:04 +053011691 channel_cnt, channel_list);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011692 qdf_mem_free(channel_list_ptr);
Min Liuab6ed4f2018-01-09 13:13:57 +080011693 return ret_val;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011694}
11695
11696/**
11697 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
11698 * @wiphy: Pointer to wireless phy
11699 * @wdev: Pointer to wireless device
11700 * @data: Pointer to data
11701 * @data_len: Length of @data
11702 *
11703 * Return: 0 on success, negative errno on failure
11704 */
11705static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
11706 struct wireless_dev *wdev,
11707 const void *data, int data_len)
11708{
11709 int ret;
11710
11711 cds_ssr_protect(__func__);
11712 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
11713 data_len);
11714 cds_ssr_protect(__func__);
11715
11716 return ret;
11717}
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011718
11719/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011720 * wlan_hdd_cfg80211_setband() - Wrapper to setband
11721 * @wiphy: wiphy structure pointer
11722 * @wdev: Wireless device structure pointer
11723 * @data: Pointer to the data received
11724 * @data_len: Length of @data
11725 *
11726 * Return: 0 on success; errno on failure
11727 */
11728static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
11729 struct wireless_dev *wdev,
11730 const void *data, int data_len)
11731{
11732 int ret;
11733
11734 cds_ssr_protect(__func__);
11735 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
11736 cds_ssr_unprotect(__func__);
11737
11738 return ret;
11739}
11740
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011741/**
11742 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
11743 * @nl80211_value: Vendor command attribute value
11744 * @wmi_value: Pointer to return converted WMI return value
11745 *
11746 * Convert NL80211 vendor command value for SAR limit set to WMI value
11747 * Return: 0 on success, -1 on invalid value
11748 */
11749static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
11750 u32 *wmi_value)
11751{
11752 int ret = 0;
11753
11754 switch (nl80211_value) {
11755 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
11756 *wmi_value = WMI_SAR_FEATURE_OFF;
11757 break;
11758 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
11759 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
11760 break;
11761 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
11762 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
11763 break;
11764 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
11765 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
11766 break;
11767 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
11768 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
11769 break;
11770 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
11771 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
11772 break;
11773 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
11774 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
11775 break;
11776 default:
11777 ret = -1;
11778 }
11779 return ret;
11780}
11781
11782/**
11783 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
11784 * @nl80211_value: Vendor command attribute value
11785 * @wmi_value: Pointer to return converted WMI return value
11786 *
11787 * Convert NL80211 vendor command value for SAR BAND to WMI value
11788 * Return: 0 on success, -1 on invalid value
11789 */
11790static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
11791{
11792 int ret = 0;
11793
11794 switch (nl80211_value) {
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070011795 case HDD_NL80211_BAND_2GHZ:
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011796 *wmi_value = WMI_SAR_2G_ID;
11797 break;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070011798 case HDD_NL80211_BAND_5GHZ:
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011799 *wmi_value = WMI_SAR_5G_ID;
11800 break;
11801 default:
11802 ret = -1;
11803 }
11804 return ret;
11805}
11806
11807/**
11808 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
11809 * @nl80211_value: Vendor command attribute value
11810 * @wmi_value: Pointer to return converted WMI return value
11811 *
11812 * Convert NL80211 vendor command value for SAR Modulation to WMI value
11813 * Return: 0 on success, -1 on invalid value
11814 */
11815static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
11816 u32 *wmi_value)
11817{
11818 int ret = 0;
11819
11820 switch (nl80211_value) {
11821 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
11822 *wmi_value = WMI_SAR_MOD_CCK;
11823 break;
11824 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
11825 *wmi_value = WMI_SAR_MOD_OFDM;
11826 break;
11827 default:
11828 ret = -1;
11829 }
11830 return ret;
11831}
11832
Jeff Johnson8c83f132017-12-18 16:41:37 -080011833static u32 hdd_sar_wmi_to_nl_enable(uint32_t wmi_value)
11834{
11835 switch (wmi_value) {
11836 default:
11837 case WMI_SAR_FEATURE_OFF:
11838 return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE;
11839 case WMI_SAR_FEATURE_ON_SET_0:
11840 return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0;
11841 case WMI_SAR_FEATURE_ON_SET_1:
11842 return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1;
11843 case WMI_SAR_FEATURE_ON_SET_2:
11844 return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2;
11845 case WMI_SAR_FEATURE_ON_SET_3:
11846 return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3;
11847 case WMI_SAR_FEATURE_ON_SET_4:
11848 return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4;
11849 case WMI_SAR_FEATURE_ON_USER_DEFINED:
11850 return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER;
11851 }
11852}
11853
11854static u32 hdd_sar_wmi_to_nl_band(uint32_t wmi_value)
11855{
11856 switch (wmi_value) {
11857 default:
11858 case WMI_SAR_2G_ID:
11859 return HDD_NL80211_BAND_2GHZ;
11860 case WMI_SAR_5G_ID:
11861 return HDD_NL80211_BAND_5GHZ;
11862 }
11863}
11864
11865static u32 hdd_sar_wmi_to_nl_modulation(uint32_t wmi_value)
11866{
11867 switch (wmi_value) {
11868 default:
11869 case WMI_SAR_MOD_CCK:
11870 return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK;
11871 case WMI_SAR_MOD_OFDM:
11872 return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM;
11873 }
11874}
11875
Jeff Johnsonb17a93c2017-06-02 12:26:55 -070011876static const struct nla_policy
11877sar_limits_policy[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1] = {
11878 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE] = {.type = NLA_U32},
11879 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS] = {.type = NLA_U32},
11880 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND] = {.type = NLA_U32},
11881 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN] = {.type = NLA_U32},
11882 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION] = {.type = NLA_U32},
11883 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT] = {.type = NLA_U32},
11884};
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011885
Jeff Johnson8c83f132017-12-18 16:41:37 -080011886#define WLAN_WAIT_TIME_SAR 5000
11887
11888/**
11889 * hdd_sar_context - hdd sar context
11890 * @event: sar limit event
11891 */
11892struct hdd_sar_context {
11893 struct sar_limit_event event;
11894};
11895
11896/**
11897 * hdd_sar_cb () - sar response message handler
11898 * @cookie: hdd request cookie
11899 * @event: sar response event
11900 *
11901 * Return: none
11902 */
11903static void hdd_sar_cb(void *cookie,
11904 struct sar_limit_event *event)
11905{
11906 struct hdd_request *request;
11907 struct hdd_sar_context *context;
11908
Dustin Brown491d54b2018-03-14 12:39:11 -070011909 hdd_enter();
Jeff Johnson8c83f132017-12-18 16:41:37 -080011910
11911 if (!event) {
11912 hdd_err("response is NULL");
11913 return;
11914 }
11915
11916 request = hdd_request_get(cookie);
11917 if (!request) {
11918 hdd_debug("Obsolete request");
11919 return;
11920 }
11921
11922 context = hdd_request_priv(request);
11923 context->event = *event;
11924 hdd_request_complete(request);
11925 hdd_request_put(request);
11926
Dustin Browne74003f2018-03-14 12:51:58 -070011927 hdd_exit();
Jeff Johnson8c83f132017-12-18 16:41:37 -080011928}
11929
11930static uint32_t hdd_sar_get_response_len(const struct sar_limit_event *event)
11931{
11932 uint32_t len;
11933 uint32_t row_len;
11934
11935 len = NLMSG_HDRLEN;
11936 /* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE */
11937 len += NLA_HDRLEN + sizeof(u32);
11938 /* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS */
11939 len += NLA_HDRLEN + sizeof(u32);
11940
11941 /* nest */
11942 row_len = NLA_HDRLEN;
11943 /* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND */
11944 row_len += NLA_HDRLEN + sizeof(u32);
11945 /* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN */
11946 row_len += NLA_HDRLEN + sizeof(u32);
11947 /* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION */
11948 row_len += NLA_HDRLEN + sizeof(u32);
11949 /* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT */
11950 row_len += NLA_HDRLEN + sizeof(u32);
11951
11952 /* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC */
11953 len += NLA_HDRLEN + (row_len * event->num_limit_rows);
11954
11955 return len;
11956}
11957
11958static int hdd_sar_fill_response(struct sk_buff *skb,
11959 const struct sar_limit_event *event)
11960{
11961 int errno;
11962 u32 value;
11963 u32 attr;
11964 struct nlattr *nla_spec_attr;
11965 struct nlattr *nla_row_attr;
11966 uint32_t row;
11967 const struct sar_limit_event_row *event_row;
11968
11969 attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE;
11970 value = hdd_sar_wmi_to_nl_enable(event->sar_enable);
11971 errno = nla_put_u32(skb, attr, value);
11972 if (errno)
11973 return errno;
11974
11975 attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS;
11976 value = event->num_limit_rows;
11977 errno = nla_put_u32(skb, attr, value);
11978 if (errno)
11979 return errno;
11980
11981 attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC;
11982 nla_spec_attr = nla_nest_start(skb, attr);
11983 if (!nla_spec_attr)
11984 return -EINVAL;
11985
11986 for (row = 0, event_row = event->sar_limit_row;
11987 row < event->num_limit_rows;
11988 row++, event_row++) {
11989 nla_row_attr = nla_nest_start(skb, attr);
11990 if (!nla_row_attr)
11991 return -EINVAL;
11992
11993 attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND;
11994 value = hdd_sar_wmi_to_nl_band(event_row->band_id);
11995 errno = nla_put_u32(skb, attr, value);
11996 if (errno)
11997 return errno;
11998
11999 attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN;
12000 value = event_row->chain_id;
12001 errno = nla_put_u32(skb, attr, value);
12002 if (errno)
12003 return errno;
12004
12005 attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION;
12006 value = hdd_sar_wmi_to_nl_modulation(event_row->mod_id);
12007 errno = nla_put_u32(skb, attr, value);
12008 if (errno)
12009 return errno;
12010
12011 attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT;
12012 value = event_row->limit_value;
12013 errno = nla_put_u32(skb, attr, value);
12014 if (errno)
12015 return errno;
12016
12017 nla_nest_end(skb, nla_row_attr);
12018 }
12019 nla_nest_end(skb, nla_spec_attr);
12020
12021 return 0;
12022}
12023
12024static int hdd_sar_send_response(struct wiphy *wiphy,
12025 const struct sar_limit_event *event)
12026{
12027 uint32_t len;
12028 struct sk_buff *skb;
12029 int errno;
12030
12031 len = hdd_sar_get_response_len(event);
12032 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len);
12033 if (!skb) {
12034 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
12035 return -ENOMEM;
12036 }
12037
12038 errno = hdd_sar_fill_response(skb, event);
12039 if (errno) {
12040 kfree_skb(skb);
12041 return errno;
12042 }
12043
12044 return cfg80211_vendor_cmd_reply(skb);
12045}
12046
12047/**
12048 * __wlan_hdd_get_sar_power_limits() - Get SAR power limits
12049 * @wiphy: Pointer to wireless phy
12050 * @wdev: Pointer to wireless device
12051 * @data: Pointer to data
12052 * @data_len: Length of @data
12053 *
12054 * This function is used to retrieve Specific Absorption Rate limit specs.
12055 *
12056 * Return: 0 on success, negative errno on failure
12057 */
12058static int __wlan_hdd_get_sar_power_limits(struct wiphy *wiphy,
12059 struct wireless_dev *wdev,
12060 const void *data, int data_len)
12061{
12062 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
12063 struct hdd_request *request;
12064 struct hdd_sar_context *context;
12065 void *cookie;
12066 QDF_STATUS status;
12067 int ret;
12068 static const struct hdd_request_params params = {
12069 .priv_size = sizeof(*context),
12070 .timeout_ms = WLAN_WAIT_TIME_SAR,
12071 };
12072
Dustin Brown491d54b2018-03-14 12:39:11 -070012073 hdd_enter();
Jeff Johnson8c83f132017-12-18 16:41:37 -080012074
12075 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
12076 hdd_err("Command not allowed in FTM mode");
12077 return -EPERM;
12078 }
12079
12080 if (wlan_hdd_validate_context(hdd_ctx))
12081 return -EINVAL;
12082
12083 request = hdd_request_alloc(&params);
12084 if (!request) {
12085 hdd_err("Request allocation failure");
12086 return -ENOMEM;
12087 }
12088
12089 cookie = hdd_request_cookie(request);
12090
12091 status = sme_get_sar_power_limits(hdd_ctx->hHal, hdd_sar_cb, cookie);
12092 if (!QDF_IS_STATUS_SUCCESS(status)) {
12093 hdd_err("Unable to post sar message");
12094 ret = -EINVAL;
12095 goto cleanup;
12096 }
12097
12098 ret = hdd_request_wait_for_response(request);
12099 if (ret) {
12100 hdd_err("Target response timed out");
12101 goto cleanup;
12102 }
12103
12104 context = hdd_request_priv(request);
12105 ret = hdd_sar_send_response(wiphy, &context->event);
12106
12107cleanup:
12108 hdd_request_put(request);
12109
12110 return ret;
12111}
12112
12113/**
12114 * wlan_hdd_cfg80211_get_sar_power_limits() - Get SAR power limits
12115 * @wiphy: Pointer to wireless phy
12116 * @wdev: Pointer to wireless device
12117 * @data: Pointer to data
12118 * @data_len: Length of @data
12119 *
12120 * Wrapper function of __wlan_hdd_cfg80211_get_sar_power_limits()
12121 *
12122 * Return: 0 on success, negative errno on failure
12123 */
12124static int wlan_hdd_cfg80211_get_sar_power_limits(struct wiphy *wiphy,
12125 struct wireless_dev *wdev,
12126 const void *data,
12127 int data_len)
12128{
12129 int ret;
12130
12131 cds_ssr_protect(__func__);
12132 ret = __wlan_hdd_get_sar_power_limits(wiphy, wdev, data, data_len);
12133 cds_ssr_unprotect(__func__);
12134
12135 return ret;
12136}
12137
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012138/**
12139 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
12140 * @wiphy: Pointer to wireless phy
12141 * @wdev: Pointer to wireless device
12142 * @data: Pointer to data
12143 * @data_len: Length of @data
12144 *
12145 * This function is used to setup Specific Absorption Rate limit specs.
12146 *
12147 * Return: 0 on success, negative errno on failure
12148 */
12149static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
12150 struct wireless_dev *wdev,
12151 const void *data, int data_len)
12152{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070012153 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012154 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
12155 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
12156 *sar_spec_list;
12157 struct sar_limit_cmd_params sar_limit_cmd = {0};
12158 int ret = -EINVAL, i = 0, rem = 0;
12159
Dustin Brown491d54b2018-03-14 12:39:11 -070012160 hdd_enter();
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012161
12162 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
12163 hdd_err("Command not allowed in FTM mode");
12164 return -EPERM;
12165 }
12166
12167 if (wlan_hdd_validate_context(hdd_ctx))
12168 return -EINVAL;
12169
Dustin Brown4ea21db2018-01-05 14:13:17 -080012170 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
12171 data, data_len, sar_limits_policy)) {
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012172 hdd_err("Invalid SAR attributes");
12173 return -EINVAL;
12174 }
12175
12176 /* Vendor command manadates all SAR Specs in single call */
12177 sar_limit_cmd.commit_limits = 1;
12178 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
12179 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
12180 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
12181 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
12182 &sar_limit_cmd.sar_enable) < 0) {
12183 hdd_err("Invalid SAR Enable attr");
12184 goto fail;
12185 }
12186 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012187 hdd_debug("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012188
12189 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
12190 sar_limit_cmd.num_limit_rows = nla_get_u32(
12191 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012192 hdd_debug("attr sar num_limit_rows %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012193 sar_limit_cmd.num_limit_rows);
12194 }
12195 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
12196 hdd_err("SAR Spec list exceed supported size");
12197 goto fail;
12198 }
12199 if (sar_limit_cmd.num_limit_rows == 0)
12200 goto send_sar_limits;
12201 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
12202 struct sar_limit_cmd_row) *
12203 sar_limit_cmd.num_limit_rows);
12204 if (!sar_limit_cmd.sar_limit_row_list) {
12205 ret = -ENOMEM;
12206 goto fail;
12207 }
12208 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
12209 hdd_err("Invalid SAR SPECs list");
12210 goto fail;
12211 }
12212
12213 nla_for_each_nested(sar_spec_list,
12214 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
12215 if (i == sar_limit_cmd.num_limit_rows) {
12216 hdd_warn("SAR Cmd has excess SPECs in list");
12217 break;
12218 }
12219
Dustin Brown4ea21db2018-01-05 14:13:17 -080012220 if (wlan_cfg80211_nla_parse(sar_spec,
12221 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
12222 nla_data(sar_spec_list),
12223 nla_len(sar_spec_list),
12224 sar_limits_policy)) {
12225 hdd_err("nla_parse failed for SAR Spec list");
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012226 goto fail;
12227 }
12228 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
12229 if (sar_spec[
12230 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
12231 sar_limit_cmd.sar_limit_row_list[i].limit_value =
12232 nla_get_u32(sar_spec[
12233 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
12234 } else {
12235 hdd_err("SAR Spec does not have power limit value");
12236 goto fail;
12237 }
12238
12239 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
12240 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
12241 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
12242 &sar_limit_cmd.sar_limit_row_list[i].band_id)
12243 < 0) {
12244 hdd_err("Invalid SAR Band attr");
12245 goto fail;
12246 }
12247 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
12248 WMI_SAR_BAND_ID_VALID_MASK;
12249 }
12250 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
12251 sar_limit_cmd.sar_limit_row_list[i].chain_id =
12252 nla_get_u32(sar_spec[
12253 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
12254 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
12255 WMI_SAR_CHAIN_ID_VALID_MASK;
12256 }
12257 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
12258 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
12259 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
12260 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
12261 < 0) {
12262 hdd_err("Invalid SAR Modulation attr");
12263 goto fail;
12264 }
12265 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
12266 WMI_SAR_MOD_ID_VALID_MASK;
12267 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012268 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012269 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
12270 sar_limit_cmd.sar_limit_row_list[i].chain_id,
12271 sar_limit_cmd.sar_limit_row_list[i].mod_id,
12272 sar_limit_cmd.sar_limit_row_list[i].limit_value,
12273 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
12274 i++;
12275 }
12276
12277 if (i < sar_limit_cmd.num_limit_rows) {
12278 hdd_warn("SAR Cmd has less SPECs in list");
12279 sar_limit_cmd.num_limit_rows = i;
12280 }
12281
12282send_sar_limits:
12283 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
12284 QDF_STATUS_SUCCESS)
12285 ret = 0;
12286fail:
12287 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
12288 return ret;
12289}
12290
12291/**
12292 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
12293 * @wiphy: Pointer to wireless phy
12294 * @wdev: Pointer to wireless device
12295 * @data: Pointer to data
12296 * @data_len: Length of @data
12297 *
12298 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
12299 *
12300 * Return: 0 on success, negative errno on failure
12301 */
12302static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
12303 struct wireless_dev *wdev,
12304 const void *data,
12305 int data_len)
12306{
12307 int ret;
12308
12309 cds_ssr_protect(__func__);
12310 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
12311 data_len);
12312 cds_ssr_unprotect(__func__);
12313
12314 return ret;
12315}
12316
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012317static const struct
12318nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
12319 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
12320 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
12321 .len = QDF_MAC_ADDR_SIZE},
12322};
12323
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +053012324void wlan_hdd_rso_cmd_status_cb(void *ctx, struct rso_cmd_status *rso_status)
12325{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070012326 struct hdd_context *hdd_ctx = (struct hdd_context *)ctx;
Jeff Johnsone5006672017-08-29 14:39:02 -070012327 struct hdd_adapter *adapter;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +053012328
12329 adapter = hdd_get_adapter_by_vdev(hdd_ctx, rso_status->vdev_id);
12330 if (!adapter) {
12331 hdd_err("adapter NULL");
12332 return;
12333 }
12334
12335 adapter->lfr_fw_status.is_disabled = rso_status->status;
12336 complete(&adapter->lfr_fw_status.disable_lfr_event);
12337}
12338
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012339/**
12340 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
12341 * @wiphy: Pointer to wireless phy
12342 * @wdev: Pointer to wireless device
12343 * @data: Pointer to data
12344 * @data_len: Length of @data
12345 *
12346 * This function is used to enable/disable roaming using vendor commands
12347 *
12348 * Return: 0 on success, negative errno on failure
12349 */
12350static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
12351 struct wireless_dev *wdev,
12352 const void *data, int data_len)
12353{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070012354 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012355 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -070012356 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012357 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
Abhishek Singh1f217ec2017-12-22 11:48:27 +053012358 uint32_t is_fast_roam_enabled;
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012359 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +053012360 QDF_STATUS qdf_status;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +053012361 unsigned long rc;
Jeff Johnson40dae4e2017-08-29 14:00:25 -070012362 struct hdd_station_ctx *hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012363
Dustin Brownfdf17c12018-03-14 12:55:34 -070012364 hdd_enter_dev(dev);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012365
12366 ret = wlan_hdd_validate_context(hdd_ctx);
12367 if (0 != ret)
12368 return ret;
12369
12370 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
12371 hdd_err("Command not allowed in FTM mode");
12372 return -EINVAL;
12373 }
12374
Dustin Brown4ea21db2018-01-05 14:13:17 -080012375 ret = wlan_cfg80211_nla_parse(tb,
12376 QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
12377 qca_wlan_vendor_attr);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012378 if (ret) {
12379 hdd_err("Invalid ATTR");
12380 return -EINVAL;
12381 }
12382
12383 /* Parse and fetch Enable flag */
12384 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
12385 hdd_err("attr enable failed");
12386 return -EINVAL;
12387 }
12388
12389 is_fast_roam_enabled = nla_get_u32(
12390 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Abhishek Singh1f217ec2017-12-22 11:48:27 +053012391 hdd_debug("isFastRoamEnabled %d", is_fast_roam_enabled);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012392
12393 /* Update roaming */
Jeff Johnson1b780e42017-10-31 14:11:45 -070012394 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->session_id,
Abhishek Singh1f217ec2017-12-22 11:48:27 +053012395 is_fast_roam_enabled);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +053012396 if (qdf_status != QDF_STATUS_SUCCESS)
12397 hdd_err("sme_config_fast_roaming failed with status=%d",
12398 qdf_status);
12399 ret = qdf_status_to_os_return(qdf_status);
12400
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +053012401 if (eConnectionState_Associated == hdd_sta_ctx->conn_info.connState &&
Abhishek Singh1f217ec2017-12-22 11:48:27 +053012402 QDF_IS_STATUS_SUCCESS(qdf_status) && !is_fast_roam_enabled) {
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +053012403
12404 INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +053012405 /*
12406 * wait only for LFR disable in fw as LFR enable
12407 * is always success
12408 */
12409 rc = wait_for_completion_timeout(
12410 &adapter->lfr_fw_status.disable_lfr_event,
12411 msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
12412 if (!rc) {
12413 hdd_err("Timed out waiting for RSO CMD status");
12414 return -ETIMEDOUT;
12415 }
12416
12417 if (!adapter->lfr_fw_status.is_disabled) {
12418 hdd_err("Roam disable attempt in FW fails");
12419 return -EBUSY;
12420 }
12421 }
12422
Dustin Browne74003f2018-03-14 12:51:58 -070012423 hdd_exit();
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012424 return ret;
12425}
12426
12427/**
12428 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
12429 * @wiphy: Pointer to wireless phy
12430 * @wdev: Pointer to wireless device
12431 * @data: Pointer to data
12432 * @data_len: Length of @data
12433 *
12434 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
12435 *
12436 * Return: 0 on success, negative errno on failure
12437 */
12438static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
12439 struct wireless_dev *wdev,
12440 const void *data, int data_len)
12441{
12442 int ret;
12443
12444 cds_ssr_protect(__func__);
12445 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
12446 cds_ssr_unprotect(__func__);
12447
12448 return ret;
12449}
12450
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012451/*
12452 * define short names for the global vendor params
12453 * used by wlan_hdd_cfg80211_setarp_stats_cmd()
12454 */
12455#define STATS_SET_INVALID \
12456 QCA_ATTR_NUD_STATS_SET_INVALID
12457#define STATS_SET_START \
12458 QCA_ATTR_NUD_STATS_SET_START
12459#define STATS_GW_IPV4 \
12460 QCA_ATTR_NUD_STATS_GW_IPV4
12461#define STATS_SET_DATA_PKT_INFO \
12462 QCA_ATTR_NUD_STATS_SET_DATA_PKT_INFO
12463#define STATS_SET_MAX \
12464 QCA_ATTR_NUD_STATS_SET_MAX
12465
12466const struct nla_policy
12467qca_wlan_vendor_set_nud_stats[STATS_SET_MAX + 1] = {
12468 [STATS_SET_START] = {.type = NLA_FLAG },
12469 [STATS_GW_IPV4] = {.type = NLA_U32 },
12470 [STATS_SET_DATA_PKT_INFO] = {.type = NLA_U32 },
12471};
12472
12473/* define short names for the global vendor params */
12474#define CONNECTIVITY_STATS_SET_INVALID \
12475 QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_INVALID
12476#define STATS_PKT_INFO_TYPE \
12477 QCA_ATTR_CONNECTIVITY_CHECK_STATS_STATS_PKT_INFO_TYPE
12478#define STATS_DNS_DOMAIN_NAME \
12479 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DNS_DOMAIN_NAME
12480#define STATS_SRC_PORT \
12481 QCA_ATTR_CONNECTIVITY_CHECK_STATS_SRC_PORT
12482#define STATS_DEST_PORT \
12483 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_PORT
12484#define STATS_DEST_IPV4 \
12485 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV4
12486#define STATS_DEST_IPV6 \
12487 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV6
12488#define CONNECTIVITY_STATS_SET_MAX \
12489 QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_MAX
12490
12491const struct nla_policy
12492qca_wlan_vendor_set_connectivity_check_stats[CONNECTIVITY_STATS_SET_MAX + 1] = {
12493 [STATS_PKT_INFO_TYPE] = {.type = NLA_U32 },
12494 [STATS_DNS_DOMAIN_NAME] = {.type = NLA_BINARY,
12495 .len = DNS_DOMAIN_NAME_MAX_LEN },
12496 [STATS_SRC_PORT] = {.type = NLA_U32 },
12497 [STATS_DEST_PORT] = {.type = NLA_U32 },
12498 [STATS_DEST_IPV4] = {.type = NLA_U32 },
12499 [STATS_DEST_IPV6] = {.type = NLA_BINARY,
12500 .len = ICMPv6_ADDR_LEN },
12501};
12502
12503/**
12504 * hdd_dns_unmake_name_query() - Convert an uncompressed DNS name to a
12505 * NUL-terminated string
12506 * @name: DNS name
12507 *
12508 * Return: Produce a printable version of a DNS name.
12509 */
12510static inline uint8_t *hdd_dns_unmake_name_query(uint8_t *name)
12511{
12512 uint8_t *p;
12513 unsigned int len;
12514
12515 p = name;
12516 while ((len = *p)) {
12517 *(p++) = '.';
12518 p += len;
12519 }
12520
12521 return name + 1;
12522}
12523
12524/**
12525 * hdd_dns_make_name_query() - Convert a standard NUL-terminated string
12526 * to DNS name
12527 * @string: Name as a NUL-terminated string
12528 * @buf: Buffer in which to place DNS name
12529 *
12530 * DNS names consist of "<length>element" pairs.
12531 *
12532 * Return: Byte following constructed DNS name
12533 */
12534static uint8_t *hdd_dns_make_name_query(const uint8_t *string, uint8_t *buf)
12535{
12536 uint8_t *length_byte = buf++;
12537 uint8_t c;
12538
12539 while ((c = *(string++))) {
12540 if (c == '.') {
12541 *length_byte = buf - length_byte - 1;
12542 length_byte = buf;
12543 }
12544 *(buf++) = c;
12545 }
12546 *length_byte = buf - length_byte - 1;
12547 *(buf++) = '\0';
12548 return buf;
12549}
12550
12551/**
12552 * hdd_set_clear_connectivity_check_stats_info() - set/clear stats info
12553 * @adapter: Pointer to hdd adapter
12554 * @arp_stats_params: arp stats structure to be sent to FW
12555 * @tb: nl attribute
12556 * @is_set_stats: set/clear stats
12557 *
12558 *
12559 * Return: 0 on success, negative errno on failure
12560 */
12561static int hdd_set_clear_connectivity_check_stats_info(
12562 struct hdd_adapter *adapter,
12563 struct set_arp_stats_params *arp_stats_params,
12564 struct nlattr **tb, bool is_set_stats)
12565{
12566 struct nlattr *tb2[CONNECTIVITY_STATS_SET_MAX + 1];
12567 struct nlattr *curr_attr = NULL;
12568 int err = 0;
12569 uint32_t pkt_bitmap;
12570 int rem;
12571
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012572 /* Set NUD command for start tracking is received. */
12573 nla_for_each_nested(curr_attr,
12574 tb[STATS_SET_DATA_PKT_INFO],
12575 rem) {
12576
12577 if (wlan_cfg80211_nla_parse(tb2,
12578 CONNECTIVITY_STATS_SET_MAX,
12579 nla_data(curr_attr), nla_len(curr_attr),
12580 qca_wlan_vendor_set_connectivity_check_stats)) {
12581 hdd_err("nla_parse failed");
12582 err = -EINVAL;
12583 goto end;
12584 }
12585
12586 if (tb2[STATS_PKT_INFO_TYPE]) {
12587 pkt_bitmap = nla_get_u32(tb2[STATS_PKT_INFO_TYPE]);
12588 if (!pkt_bitmap) {
12589 hdd_err("pkt tracking bitmap is empty");
12590 err = -EINVAL;
12591 goto end;
12592 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012593
12594 if (is_set_stats) {
12595 arp_stats_params->pkt_type_bitmap = pkt_bitmap;
12596 arp_stats_params->flag = true;
12597 adapter->pkt_type_bitmap |=
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012598 arp_stats_params->pkt_type_bitmap;
12599
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012600 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_ARP) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012601 if (!tb[STATS_GW_IPV4]) {
12602 hdd_err("GW ipv4 address is not present");
12603 err = -EINVAL;
12604 goto end;
12605 }
12606 arp_stats_params->ip_addr =
12607 nla_get_u32(tb[STATS_GW_IPV4]);
12608 arp_stats_params->pkt_type =
12609 WLAN_NUD_STATS_ARP_PKT_TYPE;
12610 adapter->track_arp_ip =
12611 arp_stats_params->ip_addr;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012612 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012613
12614 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
12615 uint8_t *domain_name;
12616
12617 if (!tb2[STATS_DNS_DOMAIN_NAME]) {
12618 hdd_err("DNS domain id is not present");
12619 err = -EINVAL;
12620 goto end;
12621 }
12622 domain_name = nla_data(
12623 tb2[STATS_DNS_DOMAIN_NAME]);
12624 adapter->track_dns_domain_len =
12625 nla_len(tb2[
12626 STATS_DNS_DOMAIN_NAME]);
12627 hdd_dns_make_name_query(domain_name,
12628 adapter->dns_payload);
12629 /* DNStracking isn't supported in FW. */
12630 arp_stats_params->pkt_type_bitmap &=
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012631 ~CONNECTIVITY_CHECK_SET_DNS;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012632 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012633
12634 if (pkt_bitmap &
12635 CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
12636 if (!tb2[STATS_SRC_PORT] ||
12637 !tb2[STATS_DEST_PORT]) {
12638 hdd_err("Source/Dest port is not present");
12639 err = -EINVAL;
12640 goto end;
12641 }
12642 arp_stats_params->tcp_src_port =
12643 nla_get_u32(
12644 tb2[STATS_SRC_PORT]);
12645 arp_stats_params->tcp_dst_port =
12646 nla_get_u32(
12647 tb2[STATS_DEST_PORT]);
12648 adapter->track_src_port =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012649 arp_stats_params->tcp_src_port;
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012650 adapter->track_dest_port =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012651 arp_stats_params->tcp_dst_port;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012652 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012653
12654 if (pkt_bitmap &
12655 CONNECTIVITY_CHECK_SET_ICMPV4) {
12656 if (!tb2[STATS_DEST_IPV4]) {
12657 hdd_err("destination ipv4 address to track ping packets is not present");
12658 err = -EINVAL;
12659 goto end;
12660 }
12661 arp_stats_params->icmp_ipv4 =
12662 nla_get_u32(
12663 tb2[STATS_DEST_IPV4]);
12664 adapter->track_dest_ipv4 =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012665 arp_stats_params->icmp_ipv4;
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012666 }
12667 } else {
12668 /* clear stats command received */
12669 arp_stats_params->pkt_type_bitmap = pkt_bitmap;
12670 arp_stats_params->flag = false;
12671 adapter->pkt_type_bitmap &=
12672 (~arp_stats_params->pkt_type_bitmap);
12673
12674 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_ARP) {
12675 arp_stats_params->pkt_type =
12676 WLAN_NUD_STATS_ARP_PKT_TYPE;
12677 qdf_mem_zero(&adapter->hdd_stats.
12678 hdd_arp_stats,
12679 sizeof(adapter->hdd_stats.
12680 hdd_arp_stats));
12681 adapter->track_arp_ip = 0;
12682 }
12683
12684 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
12685 /* DNStracking isn't supported in FW. */
12686 arp_stats_params->pkt_type_bitmap &=
12687 ~CONNECTIVITY_CHECK_SET_DNS;
12688 qdf_mem_zero(&adapter->hdd_stats.
12689 hdd_dns_stats,
12690 sizeof(adapter->hdd_stats.
12691 hdd_dns_stats));
12692 qdf_mem_zero(adapter->dns_payload,
12693 adapter->track_dns_domain_len);
12694 adapter->track_dns_domain_len = 0;
12695 }
12696
12697 if (pkt_bitmap &
12698 CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
12699 qdf_mem_zero(&adapter->hdd_stats.
12700 hdd_tcp_stats,
12701 sizeof(adapter->hdd_stats.
12702 hdd_tcp_stats));
12703 adapter->track_src_port = 0;
12704 adapter->track_dest_port = 0;
12705 }
12706
12707 if (pkt_bitmap &
12708 CONNECTIVITY_CHECK_SET_ICMPV4) {
12709 qdf_mem_zero(&adapter->hdd_stats.
12710 hdd_icmpv4_stats,
12711 sizeof(adapter->hdd_stats.
12712 hdd_icmpv4_stats));
12713 adapter->track_dest_ipv4 = 0;
12714 }
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012715 }
12716 } else {
12717 hdd_err("stats list empty");
12718 err = -EINVAL;
12719 goto end;
12720 }
12721 }
12722
12723end:
12724 return err;
12725}
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +053012726
12727void hdd_update_cca_info_cb(void *context, uint32_t congestion,
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012728 uint32_t vdev_id)
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +053012729{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070012730 struct hdd_context *hdd_ctx = (struct hdd_context *)context;
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +053012731 int status;
Jeff Johnsone5006672017-08-29 14:39:02 -070012732 struct hdd_adapter *adapter = NULL;
Jeff Johnson40dae4e2017-08-29 14:00:25 -070012733 struct hdd_station_ctx *hdd_sta_ctx;
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +053012734
12735 status = wlan_hdd_validate_context(hdd_ctx);
12736 if (status != 0)
12737 return;
12738
12739 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
12740 if (adapter == NULL) {
12741 hdd_err("vdev_id %d does not exist with host", vdev_id);
12742 return;
12743 }
12744
12745 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
12746 hdd_sta_ctx->conn_info.cca = congestion;
12747 hdd_info("congestion:%d", congestion);
12748}
12749
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012750static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
12751 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
12752 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
12753 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
12754 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
12755};
12756
12757/**
12758 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
12759 * @wiphy: Pointer to wireless phy
12760 * @wdev: Pointer to wireless device
12761 * @data: Pointer to data
12762 * @data_len: Length of @data
12763 *
12764 * Return: 0 on success, negative errno on failure
12765 */
12766static int
12767__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
12768 struct wireless_dev *wdev,
12769 const void *data,
12770 int data_len)
12771{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070012772 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012773 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
12774 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
12775 struct nlattr *apth;
12776 int rem;
12777 int ret = 1;
12778 int print_idx = -1;
12779 int module_id = -1;
12780 int bit_mask = -1;
12781 int status;
12782
Dustin Brown491d54b2018-03-14 12:39:11 -070012783 hdd_enter();
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012784
12785 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
12786 hdd_err("Command not allowed in FTM mode");
12787 return -EINVAL;
12788 }
12789
12790 ret = wlan_hdd_validate_context(hdd_ctx);
12791 if (ret != 0)
12792 return -EINVAL;
12793
12794 print_idx = qdf_get_pidx();
12795 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
12796 hdd_err("Invalid print controle object index");
12797 return -EINVAL;
12798 }
12799
Dustin Brown4ea21db2018-01-05 14:13:17 -080012800 if (wlan_cfg80211_nla_parse(tb1,
12801 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
12802 data, data_len,
12803 qca_wlan_vendor_set_trace_level_policy)) {
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012804 hdd_err("Invalid attr");
12805 return -EINVAL;
12806 }
12807
12808 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
12809 hdd_err("attr trace level param failed");
12810 return -EINVAL;
12811 }
12812
12813 nla_for_each_nested(apth,
12814 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
Dustin Brown4ea21db2018-01-05 14:13:17 -080012815 if (wlan_cfg80211_nla_parse(tb2,
12816 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
12817 nla_data(apth), nla_len(apth), NULL)) {
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012818 hdd_err("Invalid attr");
12819 return -EINVAL;
12820 }
12821
12822 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
12823 hdd_err("attr Module ID failed");
12824 return -EINVAL;
12825 }
12826 module_id = nla_get_u32
12827 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
12828
12829 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
12830 hdd_err("attr Verbose mask failed");
12831 return -EINVAL;
12832 }
12833 bit_mask = nla_get_u32
12834 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
12835
12836 status = hdd_qdf_trace_enable(module_id, bit_mask);
12837
12838 if (status != 0)
12839 hdd_err("can not set verbose mask %d for the category %d",
12840 bit_mask, module_id);
12841 }
12842
Dustin Browne74003f2018-03-14 12:51:58 -070012843 hdd_exit();
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012844 return ret;
12845}
12846
12847/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +053012848 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
12849 * @wiphy: Pointer to wireless phy
12850 * @wdev: Pointer to wireless device
12851 * @data: Pointer to data
12852 * @data_len: Length of @data
12853 *
12854 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
12855 *
12856 * Return: 0 on success, negative errno on failure
12857 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012858
12859static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
12860 struct wireless_dev *wdev,
12861 const void *data,
12862 int data_len)
12863{
12864 int ret;
12865
12866 cds_ssr_protect(__func__);
12867 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
12868 cds_ssr_unprotect(__func__);
12869
12870 return ret;
12871}
12872
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012873/**
12874 * __wlan_hdd_cfg80211_set_nud_stats() - set arp stats command to firmware
12875 * @wiphy: pointer to wireless wiphy structure.
12876 * @wdev: pointer to wireless_dev structure.
12877 * @data: pointer to apfind configuration data.
12878 * @data_len: the length in byte of apfind data.
12879 *
12880 * This is called when wlan driver needs to send arp stats to
12881 * firmware.
12882 *
12883 * Return: An error code or 0 on success.
12884 */
12885static int __wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
12886 struct wireless_dev *wdev,
12887 const void *data, int data_len)
12888{
12889 struct nlattr *tb[STATS_SET_MAX + 1];
12890 struct net_device *dev = wdev->netdev;
12891 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
12892 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012893 struct set_arp_stats_params arp_stats_params = {0};
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012894 int err = 0;
12895
Dustin Brown491d54b2018-03-14 12:39:11 -070012896 hdd_enter();
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012897
Anurag Chouhan9fb2bd52018-01-04 12:25:48 +053012898 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
12899 hdd_err("Command not allowed in FTM mode");
12900 return -EINVAL;
12901 }
12902
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012903 err = wlan_hdd_validate_context(hdd_ctx);
12904 if (0 != err)
12905 return err;
12906
Dustin Brown4ea21db2018-01-05 14:13:17 -080012907 err = wlan_cfg80211_nla_parse(tb, STATS_SET_MAX, data, data_len,
12908 qca_wlan_vendor_set_nud_stats);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012909 if (err) {
Dustin Browna2868622018-03-20 11:38:14 -070012910 hdd_err("STATS_SET_START ATTR");
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012911 return err;
12912 }
12913
Yeshwanth Sriram Guntukad5aae7f2017-11-27 14:33:51 +053012914 if (adapter->session_id == HDD_SESSION_ID_INVALID) {
12915 hdd_err("Invalid session id");
12916 return -EINVAL;
12917 }
12918
Poddar, Siddarthdf076672018-02-26 14:21:45 +053012919 if (adapter->device_mode != QDF_STA_MODE) {
Dustin Browna2868622018-03-20 11:38:14 -070012920 hdd_err("STATS supported in only STA mode!");
Poddar, Siddarthdf076672018-02-26 14:21:45 +053012921 return -EINVAL;
12922 }
12923
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012924 if (tb[STATS_SET_START]) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012925 /* tracking is enabled for stats other than arp. */
12926 if (tb[STATS_SET_DATA_PKT_INFO]) {
12927 err = hdd_set_clear_connectivity_check_stats_info(
12928 adapter,
12929 &arp_stats_params, tb, true);
12930 if (err)
12931 return -EINVAL;
12932
12933 /*
12934 * if only tracking dns, then don't send
12935 * wmi command to FW.
12936 */
12937 if (!arp_stats_params.pkt_type_bitmap)
12938 return err;
12939 } else {
12940 if (!tb[STATS_GW_IPV4]) {
Dustin Browna2868622018-03-20 11:38:14 -070012941 hdd_err("STATS_SET_START CMD");
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012942 return -EINVAL;
12943 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012944
12945 arp_stats_params.pkt_type_bitmap =
12946 CONNECTIVITY_CHECK_SET_ARP;
12947 adapter->pkt_type_bitmap |=
12948 arp_stats_params.pkt_type_bitmap;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012949 arp_stats_params.flag = true;
12950 arp_stats_params.ip_addr =
12951 nla_get_u32(tb[STATS_GW_IPV4]);
12952 adapter->track_arp_ip = arp_stats_params.ip_addr;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012953 arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012954 }
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012955 } else {
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012956 /* clear stats command received. */
12957 if (tb[STATS_SET_DATA_PKT_INFO]) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012958 err = hdd_set_clear_connectivity_check_stats_info(
12959 adapter,
12960 &arp_stats_params, tb, false);
12961 if (err)
12962 return -EINVAL;
12963
12964 /*
12965 * if only tracking dns, then don't send
12966 * wmi command to FW.
12967 */
12968 if (!arp_stats_params.pkt_type_bitmap)
12969 return err;
12970 } else {
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012971 arp_stats_params.pkt_type_bitmap =
12972 CONNECTIVITY_CHECK_SET_ARP;
12973 adapter->pkt_type_bitmap &=
12974 (~arp_stats_params.pkt_type_bitmap);
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012975 arp_stats_params.flag = false;
12976 qdf_mem_zero(&adapter->hdd_stats.hdd_arp_stats,
12977 sizeof(adapter->hdd_stats.hdd_arp_stats));
12978 arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
12979 }
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012980 }
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012981
Dustin Browna2868622018-03-20 11:38:14 -070012982 hdd_info("STATS_SET_START Received flag %d!", arp_stats_params.flag);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012983
Jeff Johnson1b780e42017-10-31 14:11:45 -070012984 arp_stats_params.vdev_id = adapter->session_id;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012985
12986 if (QDF_STATUS_SUCCESS !=
12987 sme_set_nud_debug_stats(hdd_ctx->hHal, &arp_stats_params)) {
Dustin Browna2868622018-03-20 11:38:14 -070012988 hdd_err("STATS_SET_START CMD Failed!");
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012989 return -EINVAL;
12990 }
12991
Dustin Browne74003f2018-03-14 12:51:58 -070012992 hdd_exit();
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012993
12994 return err;
12995}
12996
12997/**
12998 * wlan_hdd_cfg80211_set_nud_stats() - set arp stats command to firmware
12999 * @wiphy: pointer to wireless wiphy structure.
13000 * @wdev: pointer to wireless_dev structure.
13001 * @data: pointer to apfind configuration data.
13002 * @data_len: the length in byte of apfind data.
13003 *
13004 * This is called when wlan driver needs to send arp stats to
13005 * firmware.
13006 *
13007 * Return: An error code or 0 on success.
13008 */
13009static int wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
13010 struct wireless_dev *wdev,
13011 const void *data, int data_len)
13012{
13013 int ret;
13014
13015 cds_ssr_protect(__func__);
13016 ret = __wlan_hdd_cfg80211_set_nud_stats(wiphy, wdev, data, data_len);
13017 cds_ssr_unprotect(__func__);
13018
13019 return ret;
13020}
13021
13022#undef STATS_SET_INVALID
13023#undef STATS_SET_START
13024#undef STATS_GW_IPV4
13025#undef STATS_SET_MAX
13026
13027/*
13028 * define short names for the global vendor params
13029 * used by wlan_hdd_cfg80211_setarp_stats_cmd()
13030 */
13031#define STATS_GET_INVALID \
13032 QCA_ATTR_NUD_STATS_SET_INVALID
13033#define COUNT_FROM_NETDEV \
13034 QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
13035#define COUNT_TO_LOWER_MAC \
13036 QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
13037#define RX_COUNT_BY_LOWER_MAC \
13038 QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
13039#define COUNT_TX_SUCCESS \
13040 QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
13041#define RSP_RX_COUNT_BY_LOWER_MAC \
13042 QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
13043#define RSP_RX_COUNT_BY_UPPER_MAC \
13044 QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
13045#define RSP_COUNT_TO_NETDEV \
13046 QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
13047#define RSP_COUNT_OUT_OF_ORDER_DROP \
13048 QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
13049#define AP_LINK_ACTIVE \
13050 QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
13051#define AP_LINK_DAD \
13052 QCA_ATTR_NUD_STATS_IS_DAD
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013053#define DATA_PKT_STATS \
13054 QCA_ATTR_NUD_STATS_DATA_PKT_STATS
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013055#define STATS_GET_MAX \
13056 QCA_ATTR_NUD_STATS_GET_MAX
13057
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013058#define CHECK_STATS_INVALID \
13059 QCA_ATTR_CONNECTIVITY_CHECK_STATS_INVALID
13060#define CHECK_STATS_PKT_TYPE \
13061 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_TYPE
13062#define CHECK_STATS_PKT_DNS_DOMAIN_NAME \
13063 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DNS_DOMAIN_NAME
13064#define CHECK_STATS_PKT_SRC_PORT \
13065 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_SRC_PORT
13066#define CHECK_STATS_PKT_DEST_PORT \
13067 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_PORT
13068#define CHECK_STATS_PKT_DEST_IPV4 \
13069 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV4
13070#define CHECK_STATS_PKT_DEST_IPV6 \
13071 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV6
13072#define CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV \
13073 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV
13074#define CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC \
13075 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC
13076#define CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC \
13077 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC
13078#define CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS \
13079 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS
13080#define CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC \
13081 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC
13082#define CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC \
13083 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC
13084#define CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV \
13085 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV
13086#define CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP \
13087 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP
13088#define CHECK_DATA_STATS_MAX \
13089 QCA_ATTR_CONNECTIVITY_CHECK_DATA_STATS_MAX
13090
13091
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013092const struct nla_policy
13093qca_wlan_vendor_get_nud_stats[STATS_GET_MAX + 1] = {
13094 [COUNT_FROM_NETDEV] = {.type = NLA_U16 },
13095 [COUNT_TO_LOWER_MAC] = {.type = NLA_U16 },
13096 [RX_COUNT_BY_LOWER_MAC] = {.type = NLA_U16 },
13097 [COUNT_TX_SUCCESS] = {.type = NLA_U16 },
13098 [RSP_RX_COUNT_BY_LOWER_MAC] = {.type = NLA_U16 },
13099 [RSP_RX_COUNT_BY_UPPER_MAC] = {.type = NLA_U16 },
13100 [RSP_COUNT_TO_NETDEV] = {.type = NLA_U16 },
13101 [RSP_COUNT_OUT_OF_ORDER_DROP] = {.type = NLA_U16 },
13102 [AP_LINK_ACTIVE] = {.type = NLA_FLAG },
13103 [AP_LINK_DAD] = {.type = NLA_FLAG },
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013104 [DATA_PKT_STATS] = {.type = NLA_U16 },
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013105};
13106
13107/**
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013108 * hdd_populate_dns_stats_info() - send dns stats info to network stack
13109 * @adapter: pointer to adapter context
13110 * @skb: pointer to skb
13111 *
13112 *
13113 * Return: An error code or 0 on success.
13114 */
13115static int hdd_populate_dns_stats_info(struct hdd_adapter *adapter,
13116 struct sk_buff *skb)
13117{
13118 uint8_t *dns_query;
13119
13120 dns_query = qdf_mem_malloc(adapter->track_dns_domain_len + 1);
13121 if (!dns_query) {
Dustin Browna2868622018-03-20 11:38:14 -070013122 hdd_err("mem alloc fail");
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013123 return -EINVAL;
13124 }
13125
13126 qdf_mem_copy(dns_query, adapter->dns_payload,
13127 adapter->track_dns_domain_len);
13128
13129 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
13130 CONNECTIVITY_CHECK_SET_DNS) ||
13131 nla_put(skb, CHECK_STATS_PKT_DNS_DOMAIN_NAME,
13132 adapter->track_dns_domain_len,
13133 hdd_dns_unmake_name_query(dns_query)) ||
13134 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
13135 adapter->hdd_stats.hdd_dns_stats.tx_dns_req_count) ||
13136 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
13137 adapter->hdd_stats.hdd_dns_stats.tx_host_fw_sent) ||
13138 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
13139 adapter->hdd_stats.hdd_dns_stats.tx_host_fw_sent) ||
13140 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
13141 adapter->hdd_stats.hdd_dns_stats.tx_ack_cnt) ||
13142 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
13143 adapter->hdd_stats.hdd_dns_stats.rx_dns_rsp_count) ||
13144 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
13145 adapter->hdd_stats.hdd_dns_stats.rx_delivered) ||
13146 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
13147 adapter->hdd_stats.hdd_dns_stats.rx_host_drop)) {
13148 hdd_err("nla put fail");
13149 qdf_mem_free(dns_query);
13150 kfree_skb(skb);
13151 return -EINVAL;
13152 }
13153 qdf_mem_free(dns_query);
13154 return 0;
13155}
13156
13157/**
13158 * hdd_populate_tcp_stats_info() - send tcp stats info to network stack
13159 * @adapter: pointer to adapter context
13160 * @skb: pointer to skb
13161 * @pkt_type: tcp pkt type
13162 *
13163 * Return: An error code or 0 on success.
13164 */
13165static int hdd_populate_tcp_stats_info(struct hdd_adapter *adapter,
13166 struct sk_buff *skb,
13167 uint8_t pkt_type)
13168{
13169 switch (pkt_type) {
13170 case CONNECTIVITY_CHECK_SET_TCP_SYN:
13171 /* Fill info for tcp syn packets (tx packet) */
13172 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
13173 CONNECTIVITY_CHECK_SET_TCP_SYN) ||
13174 nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
13175 adapter->track_src_port) ||
13176 nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
13177 adapter->track_dest_port) ||
13178 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
13179 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_syn_count) ||
13180 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
13181 adapter->hdd_stats.hdd_tcp_stats.
13182 tx_tcp_syn_host_fw_sent) ||
13183 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
13184 adapter->hdd_stats.hdd_tcp_stats.
13185 tx_tcp_syn_host_fw_sent) ||
13186 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
13187 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_syn_ack_cnt)) {
13188 hdd_err("nla put fail");
13189 kfree_skb(skb);
13190 return -EINVAL;
13191 }
13192 break;
13193 case CONNECTIVITY_CHECK_SET_TCP_SYN_ACK:
13194 /* Fill info for tcp syn-ack packets (rx packet) */
13195 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
13196 CONNECTIVITY_CHECK_SET_TCP_SYN_ACK) ||
13197 nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
13198 adapter->track_src_port) ||
13199 nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
13200 adapter->track_dest_port) ||
13201 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC,
13202 adapter->hdd_stats.hdd_tcp_stats.rx_fw_cnt) ||
13203 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
13204 adapter->hdd_stats.hdd_tcp_stats.
13205 rx_tcp_syn_ack_count) ||
13206 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
13207 adapter->hdd_stats.hdd_tcp_stats.rx_delivered) ||
13208 nla_put_u16(skb,
13209 CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
13210 adapter->hdd_stats.hdd_tcp_stats.rx_host_drop)) {
13211 hdd_err("nla put fail");
13212 kfree_skb(skb);
13213 return -EINVAL;
13214 }
13215 break;
13216 case CONNECTIVITY_CHECK_SET_TCP_ACK:
13217 /* Fill info for tcp ack packets (tx packet) */
13218 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
13219 CONNECTIVITY_CHECK_SET_TCP_ACK) ||
13220 nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
13221 adapter->track_src_port) ||
13222 nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
13223 adapter->track_dest_port) ||
13224 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
13225 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_ack_count) ||
13226 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
13227 adapter->hdd_stats.hdd_tcp_stats.
13228 tx_tcp_ack_host_fw_sent) ||
13229 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
13230 adapter->hdd_stats.hdd_tcp_stats.
13231 tx_tcp_ack_host_fw_sent) ||
13232 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
13233 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_ack_ack_cnt)) {
13234 hdd_err("nla put fail");
13235 kfree_skb(skb);
13236 return -EINVAL;
13237 }
13238 break;
13239 default:
13240 break;
13241 }
13242 return 0;
13243}
13244
13245/**
13246 * hdd_populate_icmpv4_stats_info() - send icmpv4 stats info to network stack
13247 * @adapter: pointer to adapter context
13248 * @skb: pointer to skb
13249 *
13250 *
13251 * Return: An error code or 0 on success.
13252 */
13253static int hdd_populate_icmpv4_stats_info(struct hdd_adapter *adapter,
13254 struct sk_buff *skb)
13255{
13256 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
13257 CONNECTIVITY_CHECK_SET_ICMPV4) ||
13258 nla_put_u32(skb, CHECK_STATS_PKT_DEST_IPV4,
13259 adapter->track_dest_ipv4) ||
13260 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
13261 adapter->hdd_stats.hdd_icmpv4_stats.tx_icmpv4_req_count) ||
13262 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
13263 adapter->hdd_stats.hdd_icmpv4_stats.tx_host_fw_sent) ||
13264 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
13265 adapter->hdd_stats.hdd_icmpv4_stats.tx_host_fw_sent) ||
13266 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
13267 adapter->hdd_stats.hdd_icmpv4_stats.tx_ack_cnt) ||
13268 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC,
13269 adapter->hdd_stats.hdd_icmpv4_stats.rx_fw_cnt) ||
13270 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
13271 adapter->hdd_stats.hdd_icmpv4_stats.rx_icmpv4_rsp_count) ||
13272 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
13273 adapter->hdd_stats.hdd_icmpv4_stats.rx_delivered) ||
13274 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
13275 adapter->hdd_stats.hdd_icmpv4_stats.rx_host_drop)) {
13276 hdd_err("nla put fail");
13277 kfree_skb(skb);
13278 return -EINVAL;
13279 }
13280 return 0;
13281}
13282
13283/**
13284 * hdd_populate_connectivity_check_stats_info() - send connectivity stats info
13285 * to network stack
13286 * @adapter: pointer to adapter context
13287 * @skb: pointer to skb
13288 *
13289 *
13290 * Return: An error code or 0 on success.
13291 */
13292
13293static int hdd_populate_connectivity_check_stats_info(
13294 struct hdd_adapter *adapter, struct sk_buff *skb)
13295{
13296 struct nlattr *connect_stats, *connect_info;
13297 uint32_t count = 0;
13298
13299 connect_stats = nla_nest_start(skb, DATA_PKT_STATS);
13300 if (connect_stats == NULL) {
13301 hdd_err("nla_nest_start failed");
13302 return -EINVAL;
13303 }
13304
13305 if (adapter->pkt_type_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
13306 connect_info = nla_nest_start(skb, count);
13307 if (connect_info == NULL) {
13308 hdd_err("nla_nest_start failed count %u", count);
13309 return -EINVAL;
13310 }
13311
13312 if (hdd_populate_dns_stats_info(adapter, skb))
13313 goto put_attr_fail;
13314 nla_nest_end(skb, connect_info);
13315 count++;
13316 }
13317
13318 if (adapter->pkt_type_bitmap & CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
13319 connect_info = nla_nest_start(skb, count);
13320 if (connect_info == NULL) {
13321 hdd_err("nla_nest_start failed count %u", count);
13322 return -EINVAL;
13323 }
13324 if (hdd_populate_tcp_stats_info(adapter, skb,
13325 CONNECTIVITY_CHECK_SET_TCP_SYN))
13326 goto put_attr_fail;
13327 nla_nest_end(skb, connect_info);
13328 count++;
13329
13330 connect_info = nla_nest_start(skb, count);
13331 if (connect_info == NULL) {
13332 hdd_err("nla_nest_start failed count %u", count);
13333 return -EINVAL;
13334 }
13335 if (hdd_populate_tcp_stats_info(adapter, skb,
13336 CONNECTIVITY_CHECK_SET_TCP_SYN_ACK))
13337 goto put_attr_fail;
13338 nla_nest_end(skb, connect_info);
13339 count++;
13340
13341 connect_info = nla_nest_start(skb, count);
13342 if (connect_info == NULL) {
13343 hdd_err("nla_nest_start failed count %u", count);
13344 return -EINVAL;
13345 }
13346 if (hdd_populate_tcp_stats_info(adapter, skb,
13347 CONNECTIVITY_CHECK_SET_TCP_ACK))
13348 goto put_attr_fail;
13349 nla_nest_end(skb, connect_info);
13350 count++;
13351 }
13352
13353 if (adapter->pkt_type_bitmap & CONNECTIVITY_CHECK_SET_ICMPV4) {
13354 connect_info = nla_nest_start(skb, count);
13355 if (connect_info == NULL) {
13356 hdd_err("nla_nest_start failed count %u", count);
13357 return -EINVAL;
13358 }
13359
13360 if (hdd_populate_icmpv4_stats_info(adapter, skb))
13361 goto put_attr_fail;
13362 nla_nest_end(skb, connect_info);
13363 count++;
13364 }
13365
13366 nla_nest_end(skb, connect_stats);
13367 return 0;
13368
13369put_attr_fail:
13370 hdd_err("QCA_WLAN_VENDOR_ATTR put fail. count %u", count);
13371 return -EINVAL;
13372}
13373
13374
13375/**
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013376 * __wlan_hdd_cfg80211_get_nud_stats() - get arp stats command to firmware
13377 * @wiphy: pointer to wireless wiphy structure.
13378 * @wdev: pointer to wireless_dev structure.
13379 * @data: pointer to apfind configuration data.
13380 * @data_len: the length in byte of apfind data.
13381 *
13382 * This is called when wlan driver needs to get arp stats to
13383 * firmware.
13384 *
13385 * Return: An error code or 0 on success.
13386 */
13387static int __wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
13388 struct wireless_dev *wdev,
13389 const void *data, int data_len)
13390{
13391 int err = 0;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013392 struct net_device *dev = wdev->netdev;
13393 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
13394 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
13395 struct get_arp_stats_params arp_stats_params;
Poddar, Siddarthdb568162017-07-27 18:16:38 +053013396 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013397 uint32_t pkt_type_bitmap;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013398 struct sk_buff *skb;
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013399 struct hdd_request *request = NULL;
13400 static const struct hdd_request_params params = {
13401 .priv_size = 0,
13402 .timeout_ms = WLAN_WAIT_TIME_NUD_STATS,
13403 };
13404 void *cookie = NULL;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013405
Dustin Brown491d54b2018-03-14 12:39:11 -070013406 hdd_enter();
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013407
Anurag Chouhan9fb2bd52018-01-04 12:25:48 +053013408 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
13409 hdd_err("Command not allowed in FTM mode");
13410 return -EINVAL;
13411 }
13412
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013413 err = wlan_hdd_validate_context(hdd_ctx);
13414 if (0 != err)
13415 return err;
13416
Rajeev Kumar7f28e8a32017-08-23 15:41:30 -070013417 err = hdd_validate_adapter(adapter);
13418 if (err)
13419 return err;
13420
Poddar, Siddarthdf076672018-02-26 14:21:45 +053013421 if (adapter->device_mode != QDF_STA_MODE) {
Dustin Browna2868622018-03-20 11:38:14 -070013422 hdd_err("STATS supported in only STA mode!");
Poddar, Siddarthdf076672018-02-26 14:21:45 +053013423 return -EINVAL;
13424 }
13425
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013426 request = hdd_request_alloc(&params);
13427 if (!request) {
13428 hdd_err("Request allocation failure");
13429 return -ENOMEM;
13430 }
13431
13432 cookie = hdd_request_cookie(request);
13433
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013434 arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
Jeff Johnson1b780e42017-10-31 14:11:45 -070013435 arp_stats_params.vdev_id = adapter->session_id;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013436
Poddar, Siddarth762c5472018-03-20 14:55:35 +053013437 pkt_type_bitmap = adapter->pkt_type_bitmap;
13438
13439 /* send NUD failure event only when ARP tracking is enabled. */
13440 if (hdd_ctx->config->enable_data_stall_det &&
13441 (pkt_type_bitmap & CONNECTIVITY_CHECK_SET_ARP))
Poddar, Siddarth37033032017-10-11 15:47:40 +053013442 cdp_post_data_stall_event(soc,
13443 DATA_STALL_LOG_INDICATOR_FRAMEWORK,
Poddar, Siddarthdb568162017-07-27 18:16:38 +053013444 DATA_STALL_LOG_NUD_FAILURE,
13445 0xFF, 0XFF,
13446 DATA_STALL_LOG_RECOVERY_TRIGGER_PDR);
13447
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013448 if (sme_set_nud_debug_stats_cb(hdd_ctx->hHal, hdd_get_nud_stats_cb,
13449 cookie) != QDF_STATUS_SUCCESS) {
13450 hdd_err("Setting NUD debug stats callback failure");
13451 err = -EINVAL;
13452 goto exit;
13453 }
13454
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013455 if (QDF_STATUS_SUCCESS !=
13456 sme_get_nud_debug_stats(hdd_ctx->hHal, &arp_stats_params)) {
Dustin Browna2868622018-03-20 11:38:14 -070013457 hdd_err("STATS_SET_START CMD Failed!");
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013458 err = -EINVAL;
13459 goto exit;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013460 }
13461
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013462 err = hdd_request_wait_for_response(request);
13463 if (err) {
13464 hdd_err("SME timedout while retrieving NUD stats");
13465 err = -ETIMEDOUT;
13466 goto exit;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013467 }
13468
13469 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
13470 WLAN_NUD_STATS_LEN);
13471 if (!skb) {
13472 hdd_err("%s: cfg80211_vendor_cmd_alloc_reply_skb failed",
13473 __func__);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013474 err = -ENOMEM;
13475 goto exit;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013476 }
13477
13478 if (nla_put_u16(skb, COUNT_FROM_NETDEV,
Sravan Kumar Kairamc1ae71c2017-02-24 12:27:27 +053013479 adapter->hdd_stats.hdd_arp_stats.tx_arp_req_count) ||
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013480 nla_put_u16(skb, COUNT_TO_LOWER_MAC,
13481 adapter->hdd_stats.hdd_arp_stats.tx_host_fw_sent) ||
13482 nla_put_u16(skb, RX_COUNT_BY_LOWER_MAC,
Sravan Kumar Kairamc1ae71c2017-02-24 12:27:27 +053013483 adapter->hdd_stats.hdd_arp_stats.tx_host_fw_sent) ||
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013484 nla_put_u16(skb, COUNT_TX_SUCCESS,
13485 adapter->hdd_stats.hdd_arp_stats.tx_ack_cnt) ||
13486 nla_put_u16(skb, RSP_RX_COUNT_BY_LOWER_MAC,
13487 adapter->hdd_stats.hdd_arp_stats.rx_fw_cnt) ||
13488 nla_put_u16(skb, RSP_RX_COUNT_BY_UPPER_MAC,
Sravan Kumar Kairamc1ae71c2017-02-24 12:27:27 +053013489 adapter->hdd_stats.hdd_arp_stats.rx_arp_rsp_count) ||
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013490 nla_put_u16(skb, RSP_COUNT_TO_NETDEV,
13491 adapter->hdd_stats.hdd_arp_stats.rx_delivered) ||
13492 nla_put_u16(skb, RSP_COUNT_OUT_OF_ORDER_DROP,
13493 adapter->hdd_stats.hdd_arp_stats.
13494 rx_host_drop_reorder)) {
13495 hdd_err("nla put fail");
13496 kfree_skb(skb);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013497 err = -EINVAL;
13498 goto exit;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013499 }
13500 if (adapter->con_status)
13501 nla_put_flag(skb, AP_LINK_ACTIVE);
13502 if (adapter->dad)
13503 nla_put_flag(skb, AP_LINK_DAD);
13504
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013505 /* ARP tracking is done above. */
13506 pkt_type_bitmap &= ~CONNECTIVITY_CHECK_SET_ARP;
13507
13508 if (pkt_type_bitmap) {
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013509 if (hdd_populate_connectivity_check_stats_info(adapter, skb)) {
13510 err = -EINVAL;
13511 goto exit;
13512 }
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013513 }
13514
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013515 cfg80211_vendor_cmd_reply(skb);
Dundi Raviteja3bcf3a82018-05-22 13:24:18 +053013516exit:
13517 hdd_request_put(request);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013518 return err;
13519}
13520
13521/**
13522 * wlan_hdd_cfg80211_get_nud_stats() - get arp stats command to firmware
13523 * @wiphy: pointer to wireless wiphy structure.
13524 * @wdev: pointer to wireless_dev structure.
13525 * @data: pointer to apfind configuration data.
13526 * @data_len: the length in byte of apfind data.
13527 *
13528 * This is called when wlan driver needs to get arp stats to
13529 * firmware.
13530 *
13531 * Return: An error code or 0 on success.
13532 */
13533static int wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
13534 struct wireless_dev *wdev,
13535 const void *data, int data_len)
13536{
13537 int ret;
13538
13539 cds_ssr_protect(__func__);
13540 ret = __wlan_hdd_cfg80211_get_nud_stats(wiphy, wdev, data, data_len);
13541 cds_ssr_unprotect(__func__);
13542
13543 return ret;
13544}
13545
13546#undef QCA_ATTR_NUD_STATS_SET_INVALID
13547#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
13548#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
13549#undef QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
13550#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
13551#undef QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
13552#undef QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
13553#undef QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
13554#undef QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
13555#undef QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
13556#undef QCA_ATTR_NUD_STATS_GET_MAX
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053013557
13558void hdd_bt_activity_cb(void *context, uint32_t bt_activity)
13559{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070013560 struct hdd_context *hdd_ctx = (struct hdd_context *)context;
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053013561 int status;
13562
13563 status = wlan_hdd_validate_context(hdd_ctx);
13564 if (0 != status)
13565 return;
13566
13567 if (bt_activity == WLAN_COEX_EVENT_BT_A2DP_PROFILE_ADD)
13568 hdd_ctx->bt_a2dp_active = 1;
13569 else if (bt_activity == WLAN_COEX_EVENT_BT_A2DP_PROFILE_REMOVE)
13570 hdd_ctx->bt_a2dp_active = 0;
13571 else if (bt_activity == WLAN_COEX_EVENT_BT_VOICE_PROFILE_ADD)
13572 hdd_ctx->bt_vo_active = 1;
13573 else if (bt_activity == WLAN_COEX_EVENT_BT_VOICE_PROFILE_REMOVE)
13574 hdd_ctx->bt_vo_active = 0;
13575 else
13576 return;
13577
Yeshwanth Sriram Guntuka9b9eb432017-12-14 18:48:41 +053013578 ucfg_scan_set_bt_activity(hdd_ctx->hdd_psoc, hdd_ctx->bt_a2dp_active);
Srinivas Girigowda6598eea2017-07-06 19:26:19 -070013579 hdd_debug("a2dp_active: %d vo_active: %d", hdd_ctx->bt_a2dp_active,
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053013580 hdd_ctx->bt_vo_active);
13581}
13582
13583
13584/**
13585 * wlan_hdd_is_bt_in_progress() - check if bt activity is in progress
13586 * @hdd_ctx : HDD context
13587 *
13588 * Return: true if BT activity is in progress else false
13589 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070013590static inline bool wlan_hdd_is_bt_in_progress(struct hdd_context *hdd_ctx)
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053013591{
13592 if (hdd_ctx->bt_a2dp_active || hdd_ctx->bt_vo_active)
13593 return true;
13594
13595 return false;
13596}
13597
lifengd217d192017-05-09 19:44:16 +080013598struct chain_rssi_priv {
13599 struct chain_rssi_result chain_rssi;
13600};
13601
13602/**
13603 * hdd_get_chain_rssi_cb() - Callback function to get chain rssi
13604 * @context: opaque context originally passed to SME. HDD always passes
13605 * a cookie for the request context
13606 * @data: struct for get chain rssi
13607 *
13608 * This function receives the response/data from the lower layer and
13609 * checks to see if the thread is still waiting then post the results to
13610 * upper layer, if the request has timed out then ignore.
13611 *
13612 * Return: None
13613 */
13614static void hdd_get_chain_rssi_cb(void *context,
13615 struct chain_rssi_result *data)
13616{
13617 struct hdd_request *request;
13618 struct chain_rssi_priv *priv;
13619
Dustin Brown491d54b2018-03-14 12:39:11 -070013620 hdd_enter();
lifengd217d192017-05-09 19:44:16 +080013621
13622 request = hdd_request_get(context);
13623 if (!request) {
13624 hdd_err("Obsolete request");
13625 return;
13626 }
13627
13628 priv = hdd_request_priv(request);
13629 priv->chain_rssi = *data;
13630 hdd_request_complete(request);
13631 hdd_request_put(request);
13632}
13633
13634/**
13635 * hdd_post_get_chain_rssi_rsp - send rsp to user space
13636 * @hdd_ctx: pointer to hdd context
13637 * @result: chain rssi result
13638 *
13639 * Return: 0 for success, non-zero for failure
13640 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070013641static int hdd_post_get_chain_rssi_rsp(struct hdd_context *hdd_ctx,
lifengd217d192017-05-09 19:44:16 +080013642 struct chain_rssi_result *result)
13643{
13644 struct sk_buff *skb;
lifengd217d192017-05-09 19:44:16 +080013645
13646 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
lifengfe6c3e22018-04-03 12:10:04 +080013647 (sizeof(result->chain_rssi) + NLA_HDRLEN) +
13648 (sizeof(result->ant_id) + NLA_HDRLEN) +
13649 NLMSG_HDRLEN);
lifengd217d192017-05-09 19:44:16 +080013650
13651 if (!skb) {
13652 hdd_err("cfg80211_vendor_event_alloc failed");
13653 return -ENOMEM;
13654 }
13655
lifengfe6c3e22018-04-03 12:10:04 +080013656 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_CHAIN_RSSI,
13657 sizeof(result->chain_rssi),
lifengd217d192017-05-09 19:44:16 +080013658 result->chain_rssi)) {
13659 hdd_err("put fail");
13660 goto nla_put_failure;
13661 }
13662
lifengfe6c3e22018-04-03 12:10:04 +080013663 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ANTENNA_INFO,
13664 sizeof(result->ant_id),
13665 result->ant_id)) {
13666 hdd_err("put fail");
13667 goto nla_put_failure;
13668 }
13669
lifengd217d192017-05-09 19:44:16 +080013670 cfg80211_vendor_cmd_reply(skb);
13671 return 0;
13672
13673nla_put_failure:
13674 kfree_skb(skb);
13675 return -EINVAL;
13676}
13677
13678/**
13679 * __wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
13680 * @wiphy: wiphy pointer
13681 * @wdev: pointer to struct wireless_dev
13682 * @data: pointer to incoming NL vendor data
13683 * @data_len: length of @data
13684 *
13685 * Return: 0 on success; error number otherwise.
13686 */
13687static int __wlan_hdd_cfg80211_get_chain_rssi(struct wiphy *wiphy,
13688 struct wireless_dev *wdev,
13689 const void *data,
13690 int data_len)
13691{
Jeff Johnsone5006672017-08-29 14:39:02 -070013692 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070013693 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
lifengd217d192017-05-09 19:44:16 +080013694 struct get_chain_rssi_req_params req_msg;
13695 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
13696 QDF_STATUS status;
13697 int retval;
13698 void *cookie;
13699 struct hdd_request *request;
13700 struct chain_rssi_priv *priv;
13701 static const struct hdd_request_params params = {
13702 .priv_size = sizeof(*priv),
13703 .timeout_ms = WLAN_WAIT_TIME_STATS,
13704 };
13705
Dustin Brown491d54b2018-03-14 12:39:11 -070013706 hdd_enter();
lifengd217d192017-05-09 19:44:16 +080013707
13708 retval = wlan_hdd_validate_context(hdd_ctx);
13709 if (0 != retval)
13710 return retval;
13711
Dustin Brown4ea21db2018-01-05 14:13:17 -080013712 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX,
13713 data, data_len, NULL)) {
lifengd217d192017-05-09 19:44:16 +080013714 hdd_err("Invalid ATTR");
13715 return -EINVAL;
13716 }
13717
13718 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
13719 hdd_err("attr mac addr failed");
13720 return -EINVAL;
13721 }
13722 if (nla_len(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) !=
13723 QDF_MAC_ADDR_SIZE) {
13724 hdd_err("incorrect mac size");
13725 return -EINVAL;
13726 }
13727 memcpy(&req_msg.peer_macaddr,
13728 nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
13729 QDF_MAC_ADDR_SIZE);
Jeff Johnson1b780e42017-10-31 14:11:45 -070013730 req_msg.session_id = adapter->session_id;
lifengd217d192017-05-09 19:44:16 +080013731
13732 request = hdd_request_alloc(&params);
13733 if (!request) {
13734 hdd_err("Request allocation failure");
13735 return -ENOMEM;
13736 }
13737 cookie = hdd_request_cookie(request);
13738
13739 status = sme_get_chain_rssi(hdd_ctx->hHal,
13740 &req_msg,
13741 hdd_get_chain_rssi_cb,
13742 cookie);
13743 if (QDF_STATUS_SUCCESS != status) {
13744 hdd_err("Unable to get chain rssi");
13745 retval = qdf_status_to_os_return(status);
13746 } else {
13747 retval = hdd_request_wait_for_response(request);
13748 if (retval) {
13749 hdd_err("Target response timed out");
13750 } else {
13751 priv = hdd_request_priv(request);
13752 retval = hdd_post_get_chain_rssi_rsp(hdd_ctx,
13753 &priv->chain_rssi);
13754 if (retval)
13755 hdd_err("Failed to post chain rssi");
13756 }
13757 }
13758 hdd_request_put(request);
13759
Dustin Browne74003f2018-03-14 12:51:58 -070013760 hdd_exit();
lifengd217d192017-05-09 19:44:16 +080013761 return retval;
13762}
13763
13764/**
13765 * wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
13766 * @wiphy: wiphy pointer
13767 * @wdev: pointer to struct wireless_dev
13768 * @data: pointer to incoming NL vendor data
13769 * @data_len: length of @data
13770 *
13771 * Return: 0 on success; error number otherwise.
13772 */
13773static int wlan_hdd_cfg80211_get_chain_rssi(struct wiphy *wiphy,
13774 struct wireless_dev *wdev,
13775 const void *data,
13776 int data_len)
13777{
13778 int ret;
13779
13780 cds_ssr_protect(__func__);
13781 ret = __wlan_hdd_cfg80211_get_chain_rssi(wiphy, wdev, data, data_len);
13782 cds_ssr_unprotect(__func__);
13783
13784 return ret;
13785}
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053013786
Ganesh Kondabattinib1960e72017-09-01 09:09:50 +053013787/**
13788 * __wlan_hdd_cfg80211_set_limit_offchan_param() - set limit off-channel cmd
13789 * parameters
13790 * @wiphy: pointer to wireless wiphy structure.
13791 * @wdev: pointer to wireless_dev structure.
13792 * @data: pointer to limit off-channel command parameters.
13793 * @data_len: the length in byte of limit off-channel command parameters.
13794 *
13795 * This is called when application wants to limit the off channel time due to
13796 * active voip traffic.
13797 *
13798 * Return: An error code or 0 on success.
13799 */
13800static int __wlan_hdd_cfg80211_set_limit_offchan_param(struct wiphy *wiphy,
13801 struct wireless_dev *wdev, const void *data, int data_len)
13802{
13803 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_MAX + 1];
13804 struct net_device *dev = wdev->netdev;
13805 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
13806 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
13807 int ret = 0;
13808 uint8_t tos;
13809 uint8_t tos_status;
13810
Dustin Brown491d54b2018-03-14 12:39:11 -070013811 hdd_enter();
Ganesh Kondabattinib1960e72017-09-01 09:09:50 +053013812
13813 ret = wlan_hdd_validate_context(hdd_ctx);
13814 if (ret < 0)
13815 return ret;
13816
Dustin Brown4ea21db2018-01-05 14:13:17 -080013817 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_MAX,
13818 data, data_len,
13819 wlan_hdd_set_limit_off_channel_param_policy)) {
Ganesh Kondabattinib1960e72017-09-01 09:09:50 +053013820 hdd_err("Invalid ATTR");
13821 return -EINVAL;
13822 }
13823
13824 if (!tb[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS]) {
13825 hdd_err("attr tos failed");
13826 goto fail;
13827 }
13828
13829 tos = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS]);
Dundi Ravitejae7b11b82018-04-18 18:19:05 +053013830 if (tos >= HDD_MAX_AC) {
13831 hdd_err("tos value %d exceeded Max value %d",
13832 tos, HDD_MAX_AC);
13833 goto fail;
13834 }
Ganesh Kondabattinib1960e72017-09-01 09:09:50 +053013835 hdd_debug("tos %d", tos);
13836
13837 if (!tb[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_START]) {
13838 hdd_err("attr tos active failed");
13839 goto fail;
13840 }
13841 tos_status = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_START]);
13842
13843 hdd_debug("tos status %d", tos_status);
13844 ret = hdd_set_limit_off_chan_for_tos(adapter, tos, tos_status);
13845
13846fail:
13847 return ret;
13848}
13849
13850/**
13851 * wlan_hdd_cfg80211_set_limit_offchan_param() - set limit off-channel cmd
13852 * parameters
13853 * @wiphy: pointer to wireless wiphy structure.
13854 * @wdev: pointer to wireless_dev structure.
13855 * @data: pointer to limit off-channel command parameters.
13856 * @data_len: the length in byte of limit off-channel command parameters.
13857 *
13858 * This is called when application wants to limit the off channel time due to
13859 * active voip traffic.
13860 *
13861 * Return: An error code or 0 on success.
13862 */
13863static int wlan_hdd_cfg80211_set_limit_offchan_param(struct wiphy *wiphy,
13864 struct wireless_dev *wdev,
13865 const void *data, int data_len)
13866
13867{
13868 int ret = 0;
13869
13870 cds_ssr_protect(__func__);
13871 ret = __wlan_hdd_cfg80211_set_limit_offchan_param(wiphy, wdev, data,
13872 data_len);
13873 cds_ssr_unprotect(__func__);
13874
13875 return ret;
13876}
13877
Vignesh Viswanathan9dd88d32017-11-22 14:22:03 +053013878/**
13879 * wlan_hdd_fill_btm_resp() - Fill bss candidate response buffer
13880 * @reply_skb : pointer to reply_skb
13881 * @info : bss candidate information
13882 * @index : attribute type index for nla_next_start()
13883 *
13884 * Return : 0 on success and errno on failure
13885 */
13886static int wlan_hdd_fill_btm_resp(struct sk_buff *reply_skb,
13887 struct bss_candidate_info *info,
13888 int index)
13889{
13890 struct nlattr *attr;
13891
13892 attr = nla_nest_start(reply_skb, index);
13893 if (!attr) {
13894 hdd_err("nla_nest_start failed");
13895 kfree_skb(reply_skb);
13896 return -EINVAL;
13897 }
13898
13899 if (nla_put(reply_skb,
13900 QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID,
13901 ETH_ALEN, info->bssid.bytes) ||
13902 nla_put_u32(reply_skb,
13903 QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_STATUS,
13904 info->status)) {
13905 hdd_err("nla_put failed");
13906 kfree_skb(reply_skb);
13907 return -EINVAL;
13908 }
13909
13910 nla_nest_end(reply_skb, attr);
13911
13912 return 0;
13913}
13914
13915/**
13916 * __wlan_hdd_cfg80211_fetch_bss_transition_status() - fetch bss transition
13917 * status
13918 * @wiphy : WIPHY structure pointer
13919 * @wdev : Wireless device structure pointer
13920 * @data : Pointer to the data received
13921 * @data_len : Length of the data received
13922 *
Jeff Johnson38c1c7d2018-05-06 15:32:39 -070013923 * This function is used to fetch transition status for candidate bss. The
Vignesh Viswanathan9dd88d32017-11-22 14:22:03 +053013924 * transition status is either accept or reason for reject.
13925 *
13926 * Return : 0 on success and errno on failure
13927 */
13928static int __wlan_hdd_cfg80211_fetch_bss_transition_status(struct wiphy *wiphy,
13929 struct wireless_dev *wdev,
13930 const void *data, int data_len)
13931{
13932 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
13933 struct nlattr *tb_msg[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_MAX + 1];
13934 uint8_t transition_reason;
13935 struct nlattr *attr;
13936 struct sk_buff *reply_skb;
13937 int rem, j;
13938 int ret;
13939 bool is_bt_in_progress;
13940 struct bss_candidate_info candidate_info[MAX_CANDIDATE_INFO];
13941 uint16_t nof_candidates, i = 0;
13942 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
13943 struct net_device *dev = wdev->netdev;
13944 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
13945 struct hdd_station_ctx *hdd_sta_ctx =
13946 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
13947 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
13948
13949 const struct nla_policy
13950 btm_params_policy[QCA_WLAN_VENDOR_ATTR_MAX + 1] = {
13951 [QCA_WLAN_VENDOR_ATTR_BTM_MBO_TRANSITION_REASON] = {
13952 .type = NLA_U8},
13953 [QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO] = {
13954 .type = NLA_NESTED},
13955 };
13956 const struct nla_policy
13957 btm_cand_list_policy[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_MAX + 1]
13958 = {[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID] = {
13959 .len = QDF_MAC_ADDR_SIZE},
13960 [QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_STATUS] = {
13961 .type = NLA_U32},
13962 };
13963
Dustin Brown491d54b2018-03-14 12:39:11 -070013964 hdd_enter();
Vignesh Viswanathan9dd88d32017-11-22 14:22:03 +053013965
13966 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
13967 hdd_err("Command not allowed in FTM mode");
13968 return -EINVAL;
13969 }
13970
13971 ret = wlan_hdd_validate_context(hdd_ctx);
13972 if (ret)
13973 return ret;
13974
13975 if (adapter->device_mode != QDF_STA_MODE ||
13976 hdd_sta_ctx->conn_info.connState != eConnectionState_Associated) {
13977 hdd_err("Command is either not invoked for STA mode (device mode: %d) or STA is not associated (Connection state: %d)",
13978 adapter->device_mode, hdd_sta_ctx->conn_info.connState);
13979 return -EINVAL;
13980 }
13981
Dustin Brown4ea21db2018-01-05 14:13:17 -080013982 ret = wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data,
13983 data_len, btm_params_policy);
Vignesh Viswanathan9dd88d32017-11-22 14:22:03 +053013984 if (ret) {
13985 hdd_err("Attribute parse failed");
13986 return -EINVAL;
13987 }
13988
13989 if (!tb[QCA_WLAN_VENDOR_ATTR_BTM_MBO_TRANSITION_REASON] ||
13990 !tb[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO]) {
13991 hdd_err("Missing attributes");
13992 return -EINVAL;
13993 }
13994
13995 transition_reason = nla_get_u8(
13996 tb[QCA_WLAN_VENDOR_ATTR_BTM_MBO_TRANSITION_REASON]);
13997
13998 nla_for_each_nested(attr,
13999 tb[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO],
14000 rem) {
Dustin Brown4ea21db2018-01-05 14:13:17 -080014001 ret = wlan_cfg80211_nla_parse_nested(tb_msg,
14002 QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_MAX,
14003 attr, btm_cand_list_policy);
Vignesh Viswanathan9dd88d32017-11-22 14:22:03 +053014004 if (ret) {
14005 hdd_err("Attribute parse failed");
14006 return -EINVAL;
14007 }
14008
14009 if (!tb_msg[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID]) {
14010 hdd_err("Missing BSSID attribute");
14011 return -EINVAL;
14012 }
14013
14014 qdf_mem_copy((void *)candidate_info[i].bssid.bytes,
14015 nla_data(tb_msg[
14016 QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID]),
14017 QDF_MAC_ADDR_SIZE);
14018 i++;
14019 if (i == MAX_CANDIDATE_INFO)
14020 break;
14021 }
14022
14023 /*
14024 * Determine status for each candidate and fill in the status field.
14025 * Also arrange the candidates in the order of preference.
14026 */
14027 nof_candidates = i;
14028
14029 is_bt_in_progress = wlan_hdd_is_bt_in_progress(hdd_ctx);
14030
14031 ret = sme_get_bss_transition_status(hal, transition_reason,
14032 &hdd_sta_ctx->conn_info.bssId,
14033 candidate_info,
14034 nof_candidates,
14035 is_bt_in_progress);
14036 if (ret)
14037 return -EINVAL;
14038
14039 /* Prepare the reply and send it to userspace */
14040 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
14041 ((QDF_MAC_ADDR_SIZE + sizeof(uint32_t)) *
14042 nof_candidates) + NLMSG_HDRLEN);
14043 if (!reply_skb) {
14044 hdd_err("reply buffer alloc failed");
14045 return -ENOMEM;
14046 }
14047
14048 attr = nla_nest_start(reply_skb,
14049 QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO);
14050 if (!attr) {
14051 hdd_err("nla_nest_start failed");
14052 kfree_skb(reply_skb);
14053 return -EINVAL;
14054 }
14055
14056 /*
14057 * Order candidates as - accepted candidate list followed by rejected
14058 * candidate list
14059 */
14060 for (i = 0, j = 0; i < nof_candidates; i++) {
14061 /* copy accepted candidate list */
14062 if (candidate_info[i].status == QCA_STATUS_ACCEPT) {
14063 if (wlan_hdd_fill_btm_resp(reply_skb,
14064 &candidate_info[i], j))
14065 return -EINVAL;
14066 j++;
14067 }
14068 }
14069 for (i = 0; i < nof_candidates; i++) {
14070 /* copy rejected candidate list */
14071 if (candidate_info[i].status != QCA_STATUS_ACCEPT) {
14072 if (wlan_hdd_fill_btm_resp(reply_skb,
14073 &candidate_info[i], j))
14074 return -EINVAL;
14075 j++;
14076 }
14077 }
14078 nla_nest_end(reply_skb, attr);
14079
Dustin Browne74003f2018-03-14 12:51:58 -070014080 hdd_exit();
Vignesh Viswanathan9dd88d32017-11-22 14:22:03 +053014081
14082 return cfg80211_vendor_cmd_reply(reply_skb);
14083}
14084
14085/**
14086 * wlan_hdd_cfg80211_fetch_bss_transition_status() - fetch bss transition status
14087 * @wiphy : WIPHY structure pointer
14088 * @wdev : Wireless device structure pointer
14089 * @data : Pointer to the data received
14090 * @data_len : Length of the data received
14091 *
Jeff Johnson38c1c7d2018-05-06 15:32:39 -070014092 * This function is used to fetch transition status for candidate bss. The
Vignesh Viswanathan9dd88d32017-11-22 14:22:03 +053014093 * transition status is either accept or reason for reject.
14094 *
14095 * Return : 0 on success and errno on failure
14096 */
14097static int wlan_hdd_cfg80211_fetch_bss_transition_status(struct wiphy *wiphy,
14098 struct wireless_dev *wdev,
14099 const void *data, int data_len)
14100{
14101 int ret;
14102
14103 cds_ssr_protect(__func__);
14104 ret = __wlan_hdd_cfg80211_fetch_bss_transition_status(wiphy, wdev,
14105 data, data_len);
14106 cds_ssr_unprotect(__func__);
14107
14108 return ret;
14109}
14110
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053014111/**
14112 * wlan_hdd_fill_intf_info() - Fill skb buffer with interface info
14113 * @skb: Pointer to skb
14114 * @info: mac mode info
14115 * @index: attribute type index for nla_nest_start()
14116 *
14117 * Return : 0 on success and errno on failure
14118 */
14119static int wlan_hdd_fill_intf_info(struct sk_buff *skb,
14120 struct connection_info *info, int index)
14121{
14122 struct nlattr *attr;
14123 uint32_t freq;
14124 struct hdd_context *hdd_ctx;
14125 struct hdd_adapter *hdd_adapter;
14126
14127 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
14128 if (!hdd_ctx)
14129 goto error;
14130
14131 hdd_adapter = hdd_get_adapter_by_vdev(hdd_ctx, info->vdev_id);
14132 if (!hdd_adapter)
14133 goto error;
14134
14135 attr = nla_nest_start(skb, index);
14136 if (!attr)
14137 goto error;
14138
14139 freq = sme_chn_to_freq(info->channel);
14140
14141 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_IFINDEX,
14142 hdd_adapter->dev->ifindex) ||
14143 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_FREQ, freq))
14144 goto error;
14145
14146 nla_nest_end(skb, attr);
14147
14148 return 0;
14149error:
14150 hdd_err("Fill buffer with interface info failed");
14151 kfree_skb(skb);
14152 return -EINVAL;
14153}
14154
14155/**
14156 * wlan_hdd_fill_mac_info() - Fill skb buffer with mac info
14157 * @skb: Pointer to skb
14158 * @info: mac mode info
14159 * @mac_id: MAC id
14160 * @conn_count: number of current connections
14161 *
14162 * Return : 0 on success and errno on failure
14163 */
14164static int wlan_hdd_fill_mac_info(struct sk_buff *skb,
14165 struct connection_info *info, uint32_t mac_id,
14166 uint32_t conn_count)
14167{
14168 struct nlattr *attr, *intf_attr;
14169 uint32_t band = 0, i = 0, j = 0;
14170 bool present = false;
14171
14172 while (i < conn_count) {
14173 if (info[i].mac_id == mac_id) {
14174 present = true;
14175 if (info[i].channel <= SIR_11B_CHANNEL_END)
14176 band |= 1 << NL80211_BAND_2GHZ;
14177 else if (info[i].channel <= SIR_11A_CHANNEL_END)
14178 band |= 1 << NL80211_BAND_5GHZ;
14179 }
14180 i++;
14181 }
14182
14183 if (!present)
14184 return 0;
14185
14186 i = 0;
14187 attr = nla_nest_start(skb, mac_id);
14188 if (!attr)
14189 goto error;
14190
14191 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO_MAC_ID, mac_id) ||
14192 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO_BAND, band))
14193 goto error;
14194
14195 intf_attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO);
14196 if (!intf_attr)
14197 goto error;
14198
14199 while (i < conn_count) {
14200 if (info[i].mac_id == mac_id) {
14201 if (wlan_hdd_fill_intf_info(skb, &info[i], j))
14202 return -EINVAL;
14203 j++;
14204 }
14205 i++;
14206 }
14207
14208 nla_nest_end(skb, intf_attr);
14209
14210 nla_nest_end(skb, attr);
14211
14212 return 0;
14213error:
14214 hdd_err("Fill buffer with mac info failed");
14215 kfree_skb(skb);
14216 return -EINVAL;
14217}
14218
14219
14220int wlan_hdd_send_mode_change_event(void)
14221{
14222 int err;
14223 struct hdd_context *hdd_ctx;
14224 struct sk_buff *skb;
14225 struct nlattr *attr;
14226 struct connection_info info[MAX_NUMBER_OF_CONC_CONNECTIONS];
14227 uint32_t conn_count, mac_id;
14228
Dustin Brown491d54b2018-03-14 12:39:11 -070014229 hdd_enter();
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053014230 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
14231 if (!hdd_ctx) {
14232 hdd_err("HDD context is NULL");
14233 return -EINVAL;
14234 }
14235
14236 err = wlan_hdd_validate_context(hdd_ctx);
14237 if (0 != err)
14238 return err;
14239
14240 conn_count = policy_mgr_get_connection_info(hdd_ctx->hdd_psoc, info);
14241 if (!conn_count)
14242 return -EINVAL;
14243
14244 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy, NULL,
14245 (sizeof(uint32_t) * 4) *
14246 MAX_NUMBER_OF_CONC_CONNECTIONS + NLMSG_HDRLEN,
14247 QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO_INDEX,
14248 GFP_KERNEL);
14249 if (!skb) {
14250 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
14251 return -ENOMEM;
14252 }
14253
14254 attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO);
14255 if (!attr) {
14256 hdd_err("nla_nest_start failed");
14257 kfree_skb(skb);
14258 return -EINVAL;
14259 }
14260
14261 for (mac_id = 0; mac_id < MAX_MAC; mac_id++) {
14262 if (wlan_hdd_fill_mac_info(skb, info, mac_id, conn_count))
14263 return -EINVAL;
14264 }
14265
14266 nla_nest_end(skb, attr);
14267
14268 cfg80211_vendor_event(skb, GFP_KERNEL);
Dustin Browne74003f2018-03-14 12:51:58 -070014269 hdd_exit();
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053014270
14271 return err;
14272}
14273
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014274const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
14275 {
14276 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14277 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
14278 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +053014279 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014280 .doit = is_driver_dfs_capable
14281 },
14282
14283#ifdef WLAN_FEATURE_NAN
14284 {
14285 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14286 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
14287 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14288 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14289 .doit = wlan_hdd_cfg80211_nan_request
14290 },
14291#endif
14292
14293#ifdef WLAN_FEATURE_STATS_EXT
14294 {
14295 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14296 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
14297 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14298 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14299 .doit = wlan_hdd_cfg80211_stats_ext_request
14300 },
14301#endif
14302#ifdef FEATURE_WLAN_EXTSCAN
14303 {
14304 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14305 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
14306 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14307 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14308 .doit = wlan_hdd_cfg80211_extscan_start
14309 },
14310 {
14311 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14312 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
14313 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14314 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14315 .doit = wlan_hdd_cfg80211_extscan_stop
14316 },
14317 {
14318 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14319 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
Manjeet Singh3abd7302017-01-11 16:07:42 +053014320 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14321 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014322 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
14323 },
14324 {
14325 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14326 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
14327 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14328 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14329 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
14330 },
14331 {
14332 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14333 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
14334 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14335 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14336 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
14337 },
14338 {
14339 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14340 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
14341 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14342 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14343 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
14344 },
14345 {
14346 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14347 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
14348 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14349 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14350 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
14351 },
14352 {
14353 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14354 .info.subcmd =
14355 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
14356 .flags =
14357 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
14358 WIPHY_VENDOR_CMD_NEED_RUNNING,
14359 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
14360 },
14361 {
14362 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14363 .info.subcmd =
14364 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
14365 .flags =
14366 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
14367 WIPHY_VENDOR_CMD_NEED_RUNNING,
14368 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
14369 },
14370 {
14371 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14372 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
14373 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14374 WIPHY_VENDOR_CMD_NEED_NETDEV |
14375 WIPHY_VENDOR_CMD_NEED_RUNNING,
14376 .doit = wlan_hdd_cfg80211_set_epno_list
14377 },
14378#endif /* FEATURE_WLAN_EXTSCAN */
14379
14380#ifdef WLAN_FEATURE_LINK_LAYER_STATS
14381 {
14382 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14383 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
14384 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14385 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14386 .doit = wlan_hdd_cfg80211_ll_stats_clear
14387 },
14388
14389 {
14390 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14391 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
14392 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14393 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14394 .doit = wlan_hdd_cfg80211_ll_stats_set
14395 },
14396
14397 {
14398 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14399 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
14400 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14401 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14402 .doit = wlan_hdd_cfg80211_ll_stats_get
14403 },
14404#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
14405#ifdef FEATURE_WLAN_TDLS
14406 {
14407 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14408 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
14409 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14410 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14411 .doit = wlan_hdd_cfg80211_exttdls_enable
14412 },
14413 {
14414 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14415 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
14416 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14417 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14418 .doit = wlan_hdd_cfg80211_exttdls_disable
14419 },
14420 {
14421 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14422 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
14423 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
14424 .doit = wlan_hdd_cfg80211_exttdls_get_status
14425 },
14426#endif
14427 {
14428 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14429 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
14430 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
14431 .doit = wlan_hdd_cfg80211_get_supported_features
14432 },
14433 {
14434 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14435 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053014436 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14437 WIPHY_VENDOR_CMD_NEED_NETDEV |
14438 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014439 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
14440 },
14441 {
14442 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14443 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
14444 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +053014445 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014446 },
14447 {
14448 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14449 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
14450 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053014451 WIPHY_VENDOR_CMD_NEED_NETDEV |
14452 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014453 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
14454 },
Manikandan Mohan80dea792016-04-28 16:36:48 -070014455 {
14456 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14457 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
14458 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053014459 WIPHY_VENDOR_CMD_NEED_NETDEV |
14460 WIPHY_VENDOR_CMD_NEED_RUNNING,
Manikandan Mohan80dea792016-04-28 16:36:48 -070014461 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
14462 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014463 {
14464 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +053014465 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
14466 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14467 WIPHY_VENDOR_CMD_NEED_NETDEV |
14468 WIPHY_VENDOR_CMD_NEED_RUNNING,
14469 .doit = hdd_cfg80211_get_station_cmd
14470 },
14471 {
14472 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014473 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
14474 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14475 WIPHY_VENDOR_CMD_NEED_NETDEV |
14476 WIPHY_VENDOR_CMD_NEED_RUNNING,
14477 .doit = wlan_hdd_cfg80211_do_acs
14478 },
14479
14480 {
14481 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14482 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
14483 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14484 WIPHY_VENDOR_CMD_NEED_NETDEV,
14485 .doit = wlan_hdd_cfg80211_get_features
14486 },
14487#ifdef WLAN_FEATURE_ROAM_OFFLOAD
14488 {
14489 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14490 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
14491 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14492 WIPHY_VENDOR_CMD_NEED_NETDEV |
14493 WIPHY_VENDOR_CMD_NEED_RUNNING,
14494 .doit = wlan_hdd_cfg80211_keymgmt_set_key
14495 },
14496#endif
14497#ifdef FEATURE_WLAN_EXTSCAN
14498 {
14499 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14500 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
14501 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14502 WIPHY_VENDOR_CMD_NEED_NETDEV |
14503 WIPHY_VENDOR_CMD_NEED_RUNNING,
14504 .doit = wlan_hdd_cfg80211_set_passpoint_list
14505 },
14506 {
14507 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14508 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
14509 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14510 WIPHY_VENDOR_CMD_NEED_NETDEV |
14511 WIPHY_VENDOR_CMD_NEED_RUNNING,
14512 .doit = wlan_hdd_cfg80211_reset_passpoint_list
14513 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014514#endif /* FEATURE_WLAN_EXTSCAN */
14515 {
14516 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14517 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
14518 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14519 WIPHY_VENDOR_CMD_NEED_NETDEV,
14520 .doit = wlan_hdd_cfg80211_get_wifi_info
14521 },
Paul Zhang3a210c52016-12-08 10:18:12 +080014522#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014523 {
14524 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14525 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
14526 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14527 WIPHY_VENDOR_CMD_NEED_NETDEV |
14528 WIPHY_VENDOR_CMD_NEED_RUNNING,
14529 .doit = wlan_hdd_cfg80211_wifi_configuration_set
14530 },
Paul Zhang3a210c52016-12-08 10:18:12 +080014531#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014532 {
14533 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -080014534 .info.subcmd =
14535 QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION,
14536 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14537 WIPHY_VENDOR_CMD_NEED_NETDEV |
14538 WIPHY_VENDOR_CMD_NEED_RUNNING,
14539 .doit = wlan_hdd_cfg80211_set_wifi_test_config
14540 },
14541
14542 {
14543 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014544 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
14545 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053014546 WIPHY_VENDOR_CMD_NEED_NETDEV |
14547 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014548 .doit = wlan_hdd_cfg80211_set_ext_roam_params
14549 },
14550 {
14551 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14552 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
14553 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053014554 WIPHY_VENDOR_CMD_NEED_NETDEV |
14555 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014556 .doit = wlan_hdd_cfg80211_wifi_logger_start
14557 },
14558 {
14559 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14560 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
14561 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053014562 WIPHY_VENDOR_CMD_NEED_NETDEV |
14563 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014564 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
14565 },
14566 {
14567 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14568 .info.subcmd =
14569 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
14570 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14571 WIPHY_VENDOR_CMD_NEED_NETDEV |
14572 WIPHY_VENDOR_CMD_NEED_RUNNING,
14573 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
14574 },
14575 {
14576 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14577 .info.subcmd =
14578 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
14579 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14580 WIPHY_VENDOR_CMD_NEED_NETDEV |
14581 WIPHY_VENDOR_CMD_NEED_RUNNING,
14582 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
14583 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070014584#ifdef WLAN_FEATURE_TSF
14585 {
14586 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14587 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
14588 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14589 WIPHY_VENDOR_CMD_NEED_NETDEV |
14590 WIPHY_VENDOR_CMD_NEED_RUNNING,
14591 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
14592 },
14593#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014594#ifdef FEATURE_WLAN_TDLS
14595 {
14596 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14597 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
14598 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14599 WIPHY_VENDOR_CMD_NEED_NETDEV |
14600 WIPHY_VENDOR_CMD_NEED_RUNNING,
14601 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
14602 },
14603#endif
14604#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
14605 {
14606 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14607 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
14608 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14609 WIPHY_VENDOR_CMD_NEED_NETDEV |
14610 WIPHY_VENDOR_CMD_NEED_RUNNING,
14611 .doit = wlan_hdd_cfg80211_offloaded_packets
14612 },
14613#endif
14614 {
14615 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14616 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
14617 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14618 WIPHY_VENDOR_CMD_NEED_NETDEV |
14619 WIPHY_VENDOR_CMD_NEED_RUNNING,
14620 .doit = wlan_hdd_cfg80211_monitor_rssi
14621 },
14622 {
14623 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +053014624 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
14625 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14626 WIPHY_VENDOR_CMD_NEED_NETDEV |
14627 WIPHY_VENDOR_CMD_NEED_RUNNING,
14628 .doit = wlan_hdd_cfg80211_set_ns_offload
14629 },
14630 {
14631 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014632 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
14633 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Sourav Mohapatra412ceb92018-03-07 18:41:16 +053014634 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014635 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
14636 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014637 {
14638 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14639 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
14640 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14641 WIPHY_VENDOR_CMD_NEED_NETDEV |
14642 WIPHY_VENDOR_CMD_NEED_RUNNING,
14643 .doit = wlan_hdd_cfg80211_vendor_scan
14644 },
14645
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014646 /* Vendor abort scan */
14647 {
14648 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14649 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
14650 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14651 WIPHY_VENDOR_CMD_NEED_NETDEV |
14652 WIPHY_VENDOR_CMD_NEED_RUNNING,
14653 .doit = wlan_hdd_vendor_abort_scan
14654 },
14655
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014656 /* OCB commands */
14657 {
14658 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14659 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
14660 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14661 WIPHY_VENDOR_CMD_NEED_NETDEV |
14662 WIPHY_VENDOR_CMD_NEED_RUNNING,
14663 .doit = wlan_hdd_cfg80211_ocb_set_config
14664 },
14665 {
14666 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14667 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
14668 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14669 WIPHY_VENDOR_CMD_NEED_NETDEV |
14670 WIPHY_VENDOR_CMD_NEED_RUNNING,
14671 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
14672 },
14673 {
14674 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14675 .info.subcmd =
14676 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
14677 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14678 WIPHY_VENDOR_CMD_NEED_NETDEV |
14679 WIPHY_VENDOR_CMD_NEED_RUNNING,
14680 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
14681 },
14682 {
14683 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14684 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
14685 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14686 WIPHY_VENDOR_CMD_NEED_NETDEV |
14687 WIPHY_VENDOR_CMD_NEED_RUNNING,
14688 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
14689 },
14690 {
14691 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14692 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
14693 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14694 WIPHY_VENDOR_CMD_NEED_NETDEV |
14695 WIPHY_VENDOR_CMD_NEED_RUNNING,
14696 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
14697 },
14698 {
14699 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14700 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
14701 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14702 WIPHY_VENDOR_CMD_NEED_NETDEV |
14703 WIPHY_VENDOR_CMD_NEED_RUNNING,
14704 .doit = wlan_hdd_cfg80211_dcc_get_stats
14705 },
14706 {
14707 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14708 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
14709 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14710 WIPHY_VENDOR_CMD_NEED_NETDEV |
14711 WIPHY_VENDOR_CMD_NEED_RUNNING,
14712 .doit = wlan_hdd_cfg80211_dcc_clear_stats
14713 },
14714 {
14715 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14716 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
14717 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14718 WIPHY_VENDOR_CMD_NEED_NETDEV |
14719 WIPHY_VENDOR_CMD_NEED_RUNNING,
14720 .doit = wlan_hdd_cfg80211_dcc_update_ndl
14721 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053014722 {
14723 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14724 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
14725 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14726 WIPHY_VENDOR_CMD_NEED_NETDEV |
14727 WIPHY_VENDOR_CMD_NEED_RUNNING,
14728 .doit = wlan_hdd_cfg80211_get_link_properties
14729 },
Peng Xu278d0122015-09-24 16:34:17 -070014730 {
Peng Xud2220962016-07-11 17:59:17 -070014731 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -070014732 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
14733 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14734 WIPHY_VENDOR_CMD_NEED_NETDEV |
14735 WIPHY_VENDOR_CMD_NEED_RUNNING,
14736 .doit = wlan_hdd_cfg80211_set_ota_test
14737 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -080014738#ifdef FEATURE_LFR_SUBNET_DETECTION
14739 {
14740 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14741 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
14742 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14743 WIPHY_VENDOR_CMD_NEED_NETDEV |
14744 WIPHY_VENDOR_CMD_NEED_RUNNING,
14745 .doit = wlan_hdd_cfg80211_set_gateway_params
14746 },
14747#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -070014748 {
Peng Xud2220962016-07-11 17:59:17 -070014749 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -070014750 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
14751 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14752 WIPHY_VENDOR_CMD_NEED_NETDEV |
14753 WIPHY_VENDOR_CMD_NEED_RUNNING,
14754 .doit = wlan_hdd_cfg80211_txpower_scale
14755 },
14756 {
14757 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14758 .info.subcmd =
14759 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
14760 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14761 WIPHY_VENDOR_CMD_NEED_NETDEV |
14762 WIPHY_VENDOR_CMD_NEED_RUNNING,
14763 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
14764 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +053014765 {
14766 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14767 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
14768 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14769 WIPHY_VENDOR_CMD_NEED_NETDEV |
14770 WIPHY_VENDOR_CMD_NEED_RUNNING,
14771 .doit = wlan_hdd_cfg80211_bpf_offload
14772 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053014773 {
14774 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +053014775 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
14776 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14777 WIPHY_VENDOR_CMD_NEED_NETDEV |
14778 WIPHY_VENDOR_CMD_NEED_RUNNING,
14779 .doit = wlan_hdd_cfg80211_acs_dfs_mode
14780 },
14781 {
14782 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +053014783 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
14784 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14785 WIPHY_VENDOR_CMD_NEED_NETDEV |
14786 WIPHY_VENDOR_CMD_NEED_RUNNING,
14787 .doit = wlan_hdd_cfg80211_sta_roam_policy
14788 },
Agrawal Ashish467dde42016-09-08 18:44:22 +053014789#ifdef FEATURE_WLAN_CH_AVOID
14790 {
14791 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14792 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
14793 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14794 WIPHY_VENDOR_CMD_NEED_NETDEV |
14795 WIPHY_VENDOR_CMD_NEED_RUNNING,
14796 .doit = wlan_hdd_cfg80211_avoid_freq
14797 },
14798#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +053014799 {
14800 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053014801 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
14802 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14803 WIPHY_VENDOR_CMD_NEED_NETDEV |
14804 WIPHY_VENDOR_CMD_NEED_RUNNING,
14805 .doit = wlan_hdd_cfg80211_sap_configuration_set
14806 },
Peng Xu8fdaa492016-06-22 10:20:47 -070014807 {
Peng Xu4225c152016-07-14 21:18:14 -070014808 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -070014809 .info.subcmd =
14810 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
14811 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14812 WIPHY_VENDOR_CMD_NEED_NETDEV |
14813 WIPHY_VENDOR_CMD_NEED_RUNNING,
14814 .doit = wlan_hdd_cfg80211_p2p_lo_start
14815 },
14816 {
14817 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14818 .info.subcmd =
14819 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
14820 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14821 WIPHY_VENDOR_CMD_NEED_NETDEV |
14822 WIPHY_VENDOR_CMD_NEED_RUNNING,
14823 .doit = wlan_hdd_cfg80211_p2p_lo_stop
14824 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053014825 {
14826 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14827 .info.subcmd =
14828 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
14829 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14830 WIPHY_VENDOR_CMD_NEED_NETDEV |
14831 WIPHY_VENDOR_CMD_NEED_RUNNING,
14832 .doit = wlan_hdd_cfg80211_conditional_chan_switch
14833 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070014834#ifdef WLAN_FEATURE_NAN_DATAPATH
14835 {
14836 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14837 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
14838 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14839 WIPHY_VENDOR_CMD_NEED_NETDEV |
14840 WIPHY_VENDOR_CMD_NEED_RUNNING,
14841 .doit = wlan_hdd_cfg80211_process_ndp_cmd
14842 },
14843#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053014844 {
14845 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14846 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
14847 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14848 WIPHY_VENDOR_CMD_NEED_NETDEV |
14849 WIPHY_VENDOR_CMD_NEED_RUNNING,
14850 .doit = wlan_hdd_cfg80211_get_wakelock_stats
14851 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053014852 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053014853 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14854 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
14855 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14856 WIPHY_VENDOR_CMD_NEED_NETDEV |
14857 WIPHY_VENDOR_CMD_NEED_RUNNING,
14858 .doit = wlan_hdd_cfg80211_get_bus_size
14859 },
14860 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053014861 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14862 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
14863 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14864 WIPHY_VENDOR_CMD_NEED_NETDEV |
14865 WIPHY_VENDOR_CMD_NEED_RUNNING,
14866 .doit = wlan_hdd_cfg80211_update_vendor_channel
14867 },
14868 {
bingsd09dea32017-03-17 10:08:26 +080014869 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053014870 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
14871 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14872 WIPHY_VENDOR_CMD_NEED_NETDEV |
14873 WIPHY_VENDOR_CMD_NEED_RUNNING,
14874 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053014875 },
14876 {
14877 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14878 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
14879 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14880 WIPHY_VENDOR_CMD_NEED_NETDEV |
14881 WIPHY_VENDOR_CMD_NEED_RUNNING,
14882 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053014883 },
14884#ifdef WLAN_FEATURE_DISA
14885 {
14886 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14887 .info.subcmd =
14888 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
14889 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14890 WIPHY_VENDOR_CMD_NEED_NETDEV |
14891 WIPHY_VENDOR_CMD_NEED_RUNNING,
14892 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
14893 },
14894#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070014895#ifdef FEATURE_WLAN_TDLS
14896 {
14897 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14898 .info.subcmd =
14899 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
14900 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14901 WIPHY_VENDOR_CMD_NEED_NETDEV |
14902 WIPHY_VENDOR_CMD_NEED_RUNNING,
14903 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080014904 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070014905#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080014906 {
14907 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Jeff Johnson8c83f132017-12-18 16:41:37 -080014908 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS,
14909 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14910 WIPHY_VENDOR_CMD_NEED_RUNNING,
14911 .doit = wlan_hdd_cfg80211_get_sar_power_limits
14912 },
14913 {
14914 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080014915 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
14916 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14917 WIPHY_VENDOR_CMD_NEED_RUNNING,
14918 .doit = wlan_hdd_cfg80211_set_sar_power_limits
14919 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053014920 {
14921 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14922 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
14923 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14924 WIPHY_VENDOR_CMD_NEED_NETDEV |
14925 WIPHY_VENDOR_CMD_NEED_RUNNING,
14926 .doit = wlan_hdd_cfg80211_set_trace_level
14927 },
Zhang Qian4ead8f02017-03-27 14:21:47 +080014928 {
14929 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14930 .info.subcmd =
14931 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT,
14932 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14933 WIPHY_VENDOR_CMD_NEED_NETDEV |
14934 WIPHY_VENDOR_CMD_NEED_RUNNING,
14935 .doit = wlan_hdd_cfg80211_ll_stats_ext_set_param
14936 },
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053014937 {
14938 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14939 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET,
14940 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14941 WIPHY_VENDOR_CMD_NEED_NETDEV |
14942 WIPHY_VENDOR_CMD_NEED_RUNNING,
14943 .doit = wlan_hdd_cfg80211_set_nud_stats
14944 },
14945 {
14946 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14947 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET,
14948 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14949 WIPHY_VENDOR_CMD_NEED_NETDEV |
14950 WIPHY_VENDOR_CMD_NEED_RUNNING,
14951 .doit = wlan_hdd_cfg80211_get_nud_stats
14952 },
Vignesh Viswanathan9dd88d32017-11-22 14:22:03 +053014953 {
14954 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14955 .info.subcmd =
14956 QCA_NL80211_VENDOR_SUBCMD_FETCH_BSS_TRANSITION_STATUS,
14957 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14958 WIPHY_VENDOR_CMD_NEED_NETDEV |
14959 WIPHY_VENDOR_CMD_NEED_RUNNING,
14960 .doit = wlan_hdd_cfg80211_fetch_bss_transition_status
14961 },
Sandeep Puligilla063a4342018-01-10 02:50:14 -080014962 FEATURE_SPECTRAL_SCAN_VENDOR_COMMANDS
Paul Zhang3a210c52016-12-08 10:18:12 +080014963#ifdef WLAN_UMAC_CONVERGENCE
14964 COMMON_VENDOR_COMMANDS
14965#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080014966 FEATURE_11AX_VENDOR_COMMANDS
lifengd217d192017-05-09 19:44:16 +080014967
14968 {
14969 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14970 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI,
14971 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14972 WIPHY_VENDOR_CMD_NEED_NETDEV |
14973 WIPHY_VENDOR_CMD_NEED_RUNNING,
14974 .doit = wlan_hdd_cfg80211_get_chain_rssi
14975 },
Ganesh Kondabattinib1960e72017-09-01 09:09:50 +053014976 {
14977 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14978 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACTIVE_TOS,
14979 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14980 WIPHY_VENDOR_CMD_NEED_NETDEV |
14981 WIPHY_VENDOR_CMD_NEED_RUNNING,
14982 .doit = wlan_hdd_cfg80211_set_limit_offchan_param
14983 },
14984
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014985};
14986
Dustin Brown52ba1ce2017-08-16 12:10:55 -070014987#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
14988static inline void
14989hdd_wiphy_set_max_sched_scans(struct wiphy *wiphy, uint8_t max_scans)
14990{
14991 if (max_scans == 0)
14992 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
14993 else
14994 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
14995}
14996#else
14997static inline void
14998hdd_wiphy_set_max_sched_scans(struct wiphy *wiphy, uint8_t max_scans)
14999{
15000 wiphy->max_sched_scan_reqs = max_scans;
15001}
15002#endif /* KERNEL_VERSION(4, 12, 0) */
15003
Padma, Santhosh Kumar4b302b62017-07-21 17:33:27 +053015004/**
15005 * wlan_hdd_cfg80211_add_connected_pno_support() - Set connected PNO support
15006 * @wiphy: Pointer to wireless phy
15007 *
15008 * This function is used to set connected PNO support to kernel
15009 *
15010 * Return: None
15011 */
Arif Hussain67c583a2018-04-26 17:00:09 -070015012#if defined(CFG80211_REPORT_BETTER_BSS_IN_SCHED_SCAN) || \
15013 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
Padma, Santhosh Kumar4b302b62017-07-21 17:33:27 +053015014static void wlan_hdd_cfg80211_add_connected_pno_support(struct wiphy *wiphy)
15015{
15016 wiphy_ext_feature_set(wiphy,
15017 NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI);
15018}
15019#else
15020static void wlan_hdd_cfg80211_add_connected_pno_support(struct wiphy *wiphy)
15021{
15022}
15023#endif
15024
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053015025#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
15026 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
15027 defined(FEATURE_WLAN_SCAN_PNO)
15028/**
15029 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
15030 * @wiphy: pointer to wiphy
15031 * @config: pointer to config
15032 *
15033 * Return: None
15034 */
15035static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
15036 struct hdd_config *config)
15037{
15038 if (config->configPNOScanSupport) {
Dustin Brown52ba1ce2017-08-16 12:10:55 -070015039 hdd_wiphy_set_max_sched_scans(wiphy, 1);
Abhishek Singh0481d662017-04-11 18:20:11 +053015040 wiphy->max_sched_scan_ssids = SCAN_PNO_MAX_SUPP_NETWORKS;
15041 wiphy->max_match_sets = SCAN_PNO_MAX_SUPP_NETWORKS;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053015042 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Abhishek Singh0481d662017-04-11 18:20:11 +053015043 wiphy->max_sched_scan_plans = SCAN_PNO_MAX_PLAN_REQUEST;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053015044 if (config->max_sched_scan_plan_interval)
15045 wiphy->max_sched_scan_plan_interval =
15046 config->max_sched_scan_plan_interval;
15047 if (config->max_sched_scan_plan_iterations)
15048 wiphy->max_sched_scan_plan_iterations =
15049 config->max_sched_scan_plan_iterations;
15050 }
15051}
15052#else
15053static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
15054 struct hdd_config *config)
15055{
15056}
15057#endif
15058
15059
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080015060/**
15061 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
15062 * @priv_size: Size of the hdd context.
15063 *
15064 * Allocate wiphy context and hdd context.
15065 *
15066 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015067 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070015068struct hdd_context *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015069{
15070 struct wiphy *wiphy;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070015071 struct hdd_context *hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080015072
Dustin Brown491d54b2018-03-14 12:39:11 -070015073 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015074
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015075 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
15076
15077 if (!wiphy) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015078 hdd_err("wiphy init failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015079 return NULL;
15080 }
15081
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080015082 hdd_ctx = wiphy_priv(wiphy);
15083
15084 hdd_ctx->wiphy = wiphy;
15085
15086 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015087}
15088
15089/*
15090 * FUNCTION: wlan_hdd_cfg80211_update_band
15091 * This function is called from the supplicant through a
15092 * private ioctl to change the band value
15093 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070015094int wlan_hdd_cfg80211_update_band(struct hdd_context *hdd_ctx, struct wiphy *wiphy,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080015095 enum band_info eBand)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015096{
15097 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070015098 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015099
Dustin Brown491d54b2018-03-14 12:39:11 -070015100 hdd_enter();
Srinivas Girigowda5da651b2017-08-04 11:22:54 -070015101
15102 for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015103
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080015104 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015105 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015106
15107 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
15108 struct ieee80211_supported_band *band = wiphy->bands[i];
15109
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070015110 channelEnabledState = wlan_reg_get_channel_state(
15111 hdd_ctx->hdd_pdev,
15112 band->channels[j].hw_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015113
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015114 if (HDD_NL80211_BAND_2GHZ == i &&
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080015115 BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015116 /* 5G only */
15117#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
15118 /* Enable Social channels for P2P */
15119 if (WLAN_HDD_IS_SOCIAL_CHANNEL
15120 (band->channels[j].center_freq)
15121 && CHANNEL_STATE_ENABLE ==
15122 channelEnabledState)
15123 band->channels[j].flags &=
15124 ~IEEE80211_CHAN_DISABLED;
15125 else
15126#endif
15127 band->channels[j].flags |=
15128 IEEE80211_CHAN_DISABLED;
15129 continue;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015130 } else if (HDD_NL80211_BAND_5GHZ == i &&
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080015131 BAND_2G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015132 /* 2G only */
15133 band->channels[j].flags |=
15134 IEEE80211_CHAN_DISABLED;
15135 continue;
15136 }
15137
Amar Singhal6842e8f2016-02-23 16:30:32 -080015138 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015139 band->channels[j].flags &=
15140 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015141 }
15142 }
15143 return 0;
15144}
15145
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +053015146#if defined(CFG80211_SCAN_RANDOM_MAC_ADDR) || \
15147 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
15148static void wlan_hdd_cfg80211_scan_randomization_init(struct wiphy *wiphy)
15149{
Paul Zhang382248f2017-10-17 14:24:45 +080015150 struct hdd_context *hdd_ctx;
Jeff Johnsone0847ba2018-03-01 12:34:50 -080015151
Paul Zhang382248f2017-10-17 14:24:45 +080015152 hdd_ctx = wiphy_priv(wiphy);
15153
15154 if (false == hdd_ctx->config->enable_mac_spoofing) {
15155 hdd_warn("MAC address spoofing is not enabled");
15156 } else {
15157 wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
15158 wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR;
15159 }
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +053015160}
15161#else
15162static void wlan_hdd_cfg80211_scan_randomization_init(struct wiphy *wiphy)
15163{
15164}
15165#endif
15166
Peng Xuacfdda12017-02-06 16:15:38 -080015167#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053015168
15169#if defined(WLAN_FEATURE_FILS_SK) && \
15170 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
15171 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053015172static void wlan_hdd_cfg80211_set_wiphy_fils_feature(struct wiphy *wiphy)
15173{
15174 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_SK_OFFLOAD);
15175}
15176#else
15177static void wlan_hdd_cfg80211_set_wiphy_fils_feature(struct wiphy *wiphy)
15178{
15179}
15180#endif
15181
gaurank kathpaliaa398d5f2018-02-27 16:42:22 +053015182#if defined (CFG80211_SCAN_DBS_CONTROL_SUPPORT) || \
15183 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0))
15184static void wlan_hdd_cfg80211_set_wiphy_scan_flags(struct wiphy *wiphy)
15185{
15186 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_LOW_SPAN_SCAN);
15187 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_LOW_POWER_SCAN);
15188 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN);
15189}
15190#else
15191static void wlan_hdd_cfg80211_set_wiphy_scan_flags(struct wiphy *wiphy)
15192{
15193}
15194#endif
15195
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053015196#if defined(WLAN_FEATURE_SAE) && \
15197 defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053015198/**
15199 * wlan_hdd_cfg80211_set_wiphy_sae_feature() - Indicates support of SAE feature
15200 * @wiphy: Pointer to wiphy
15201 * @config: pointer to config
15202 *
15203 * This function is used to indicate the support of SAE
15204 *
15205 * Return: None
15206 */
15207static void wlan_hdd_cfg80211_set_wiphy_sae_feature(struct wiphy *wiphy,
15208 struct hdd_config *config)
15209{
15210 if (config->is_sae_enabled)
15211 wiphy->features |= NL80211_FEATURE_SAE;
15212}
15213#else
15214static void wlan_hdd_cfg80211_set_wiphy_sae_feature(struct wiphy *wiphy,
15215 struct hdd_config *config)
15216{
15217}
15218#endif
15219
Peng Xu8e8b0392018-04-30 11:32:34 -070015220#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)) || \
15221 defined(CFG80211_DFS_OFFLOAD_BACKPORT)
15222static void wlan_hdd_cfg80211_set_dfs_offload_feature(struct wiphy *wiphy)
15223{
15224 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD);
15225}
15226#else
15227static void wlan_hdd_cfg80211_set_dfs_offload_feature(struct wiphy *wiphy)
15228{
15229 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
15230}
15231#endif
15232
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015233/*
15234 * FUNCTION: wlan_hdd_cfg80211_init
15235 * This function is called by hdd_wlan_startup()
15236 * during initialization.
15237 * This function is used to initialize and register wiphy structure.
15238 */
15239int wlan_hdd_cfg80211_init(struct device *dev,
15240 struct wiphy *wiphy, struct hdd_config *pCfg)
15241{
15242 int i, j;
Jeff Johnsonb8944722017-09-03 09:03:19 -070015243 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +053015244 int len = 0;
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053015245 uint32_t *cipher_suites;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015246
Dustin Brown491d54b2018-03-14 12:39:11 -070015247 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015248
15249 /* Now bind the underlying wlan device with wiphy */
15250 set_wiphy_dev(wiphy, dev);
15251
15252 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
15253
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015254 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
15255 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
15256 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
15257#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
15258 | WIPHY_FLAG_4ADDR_STATION
15259#endif
15260 | WIPHY_FLAG_OFFCHAN_TX;
15261
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015262#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
15263 wiphy->wowlan = &wowlan_support_cfg80211_init;
15264#else
15265 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
15266 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
15267 wiphy->wowlan.pattern_min_len = 1;
15268 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
15269#endif
15270
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070015271 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015272#ifdef FEATURE_WLAN_ESE
15273 || pCfg->isEseIniFeatureEnabled
15274#endif
15275 ) {
15276 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
15277 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015278#ifdef FEATURE_WLAN_TDLS
15279 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
15280 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
15281#endif
15282
15283 wiphy->features |= NL80211_FEATURE_HT_IBSS;
15284
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015285#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
15286 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
15287#endif
Vignesh Viswanathancc7f1b92017-09-28 13:12:24 +053015288 if (pCfg->is_fils_enabled)
15289 wlan_hdd_cfg80211_set_wiphy_fils_feature(wiphy);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015290
gaurank kathpaliaa398d5f2018-02-27 16:42:22 +053015291 wlan_hdd_cfg80211_set_wiphy_scan_flags(wiphy);
15292
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053015293 wlan_hdd_cfg80211_set_wiphy_sae_feature(wiphy, pCfg);
15294
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053015295 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Padma, Santhosh Kumar4b302b62017-07-21 17:33:27 +053015296 wlan_hdd_cfg80211_add_connected_pno_support(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015297
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015298 wiphy->max_scan_ssids = MAX_SCAN_SSID;
15299
15300 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
15301
15302 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
15303
Arun Khandavallifae92942016-08-01 13:31:08 +053015304 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
15305 | BIT(NL80211_IFTYPE_ADHOC)
15306 | BIT(NL80211_IFTYPE_P2P_CLIENT)
15307 | BIT(NL80211_IFTYPE_P2P_GO)
15308 | BIT(NL80211_IFTYPE_AP)
15309 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015310
Arun Khandavallifae92942016-08-01 13:31:08 +053015311 if (pCfg->advertiseConcurrentOperation) {
15312 if (pCfg->enableMCC) {
15313 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015314
Arun Khandavallifae92942016-08-01 13:31:08 +053015315 for (i = 0;
15316 i < ARRAY_SIZE(wlan_hdd_iface_combination);
15317 i++) {
15318 if (!pCfg->allowMCCGODiffBI)
15319 wlan_hdd_iface_combination[i].
15320 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015321 }
15322 }
15323 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053015324 ARRAY_SIZE(wlan_hdd_iface_combination);
15325 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015326 }
15327
15328 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015329 * on ini values
15330 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015331 if (!pCfg->ShortGI20MhzEnable) {
15332 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
15333 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015334 }
15335
Srinivas Girigowda576b2352017-08-25 14:44:26 -070015336 if (!pCfg->ShortGI40MhzEnable)
15337 wlan_hdd_band_5_ghz.ht_cap.cap &=
15338 ~IEEE80211_HT_CAP_SGI_40;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015339
Srinivas Girigowda576b2352017-08-25 14:44:26 -070015340 if (!pCfg->nChannelBondingMode5GHz)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015341 wlan_hdd_band_5_ghz.ht_cap.cap &=
15342 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015343
Abhishek Singhf512bf32016-05-04 16:47:46 +053015344 /*
15345 * In case of static linked driver at the time of driver unload,
15346 * module exit doesn't happens. Module cleanup helps in cleaning
15347 * of static memory.
15348 * If driver load happens statically, at the time of driver unload,
15349 * wiphy flags don't get reset because of static memory.
15350 * It's better not to store channel in static memory.
15351 */
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015352 wiphy->bands[HDD_NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
15353 wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053015354 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015355 if (wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053015356 hdd_err("Not enough memory to allocate channels");
15357 return -ENOMEM;
15358 }
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015359 qdf_mem_copy(wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053015360 &hdd_channels_2_4_ghz[0],
15361 sizeof(hdd_channels_2_4_ghz));
Jeff Johnsonb8944722017-09-03 09:03:19 -070015362 if ((hdd_is_5g_supported(hdd_ctx)) &&
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053015363 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
15364 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
15365 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
15366 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015367 wiphy->bands[HDD_NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +053015368
15369 if (pCfg->dot11p_mode) {
15370 wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels =
15371 qdf_mem_malloc(sizeof(hdd_channels_5_ghz) +
15372 sizeof(hdd_channels_dot11p));
15373 if (wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels ==
15374 NULL) {
15375 goto mem_fail;
15376 }
15377 wiphy->bands[HDD_NL80211_BAND_5GHZ]->n_channels =
15378 QDF_ARRAY_SIZE(hdd_channels_5_ghz) +
15379 QDF_ARRAY_SIZE(hdd_channels_dot11p);
15380
15381 qdf_mem_copy(wiphy->bands[HDD_NL80211_BAND_5GHZ]->
15382 channels, &hdd_channels_5_ghz[0],
15383 sizeof(hdd_channels_5_ghz));
15384 len = sizeof(hdd_channels_5_ghz);
15385 qdf_mem_copy((char *)wiphy->
15386 bands[HDD_NL80211_BAND_5GHZ]->channels
15387 + len,
15388 &hdd_channels_dot11p[0],
15389 sizeof(hdd_channels_dot11p));
15390
15391 } else {
15392 wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053015393 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +053015394 if (wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels ==
15395 NULL) {
15396 goto mem_fail;
15397 }
15398 qdf_mem_copy(wiphy->
15399 bands[HDD_NL80211_BAND_5GHZ]->channels,
15400 &hdd_channels_5_ghz[0],
15401 sizeof(hdd_channels_5_ghz));
Abhishek Singhf512bf32016-05-04 16:47:46 +053015402 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015403 }
15404
Srinivas Girigowda5da651b2017-08-04 11:22:54 -070015405 for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015406
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080015407 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015408 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015409
15410 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
15411 struct ieee80211_supported_band *band = wiphy->bands[i];
15412
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015413 if (HDD_NL80211_BAND_2GHZ == i &&
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080015414 BAND_5G == pCfg->nBandCapability) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015415 /* 5G only */
15416#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
15417 /* Enable social channels for P2P */
15418 if (WLAN_HDD_IS_SOCIAL_CHANNEL
15419 (band->channels[j].center_freq))
15420 band->channels[j].flags &=
15421 ~IEEE80211_CHAN_DISABLED;
15422 else
15423#endif
15424 band->channels[j].flags |=
15425 IEEE80211_CHAN_DISABLED;
15426 continue;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015427 } else if (HDD_NL80211_BAND_5GHZ == i &&
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080015428 BAND_2G == pCfg->nBandCapability) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015429 /* 2G only */
15430 band->channels[j].flags |=
15431 IEEE80211_CHAN_DISABLED;
15432 continue;
15433 }
15434 }
15435 }
15436 /*Initialise the supported cipher suite details */
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053015437 if (pCfg->gcmp_enabled) {
15438 cipher_suites = qdf_mem_malloc(sizeof(hdd_cipher_suites) +
15439 sizeof(hdd_gcmp_cipher_suits));
15440 if (cipher_suites == NULL) {
15441 hdd_err("Not enough memory for cipher suites");
15442 return -ENOMEM;
15443 }
15444 wiphy->n_cipher_suites = QDF_ARRAY_SIZE(hdd_cipher_suites) +
15445 QDF_ARRAY_SIZE(hdd_gcmp_cipher_suits);
15446 qdf_mem_copy(cipher_suites, &hdd_cipher_suites,
15447 sizeof(hdd_cipher_suites));
15448 qdf_mem_copy(cipher_suites + QDF_ARRAY_SIZE(hdd_cipher_suites),
15449 &hdd_gcmp_cipher_suits,
15450 sizeof(hdd_gcmp_cipher_suits));
15451 } else {
15452 cipher_suites = qdf_mem_malloc(sizeof(hdd_cipher_suites));
15453 if (cipher_suites == NULL) {
15454 hdd_err("Not enough memory for cipher suites");
15455 return -ENOMEM;
15456 }
15457 wiphy->n_cipher_suites = QDF_ARRAY_SIZE(hdd_cipher_suites);
15458 qdf_mem_copy(cipher_suites, &hdd_cipher_suites,
15459 sizeof(hdd_cipher_suites));
15460 }
15461 wiphy->cipher_suites = cipher_suites;
15462 cipher_suites = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015463 /*signal strength in mBm (100*dBm) */
15464 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
15465 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
15466
Anurag Chouhan6d760662016-02-20 16:05:43 +053015467 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015468 wiphy->n_vendor_commands =
15469 ARRAY_SIZE(hdd_wiphy_vendor_commands);
15470 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
15471
15472 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
15473 wiphy->n_vendor_events =
15474 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
15475 }
15476
Srinivas Girigowda576b2352017-08-25 14:44:26 -070015477 if (pCfg->enableDFSMasterCap)
Peng Xu8e8b0392018-04-30 11:32:34 -070015478 wlan_hdd_cfg80211_set_dfs_offload_feature(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015479
15480 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
15481
15482#ifdef QCA_HT_2040_COEX
15483 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
15484#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053015485 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080015486
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053015487#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) || \
wadesonga75734c2017-02-07 16:03:25 +080015488 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
15489 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
15490 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
15491 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
15492#endif
15493
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015494 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080015495 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Kiran Kumar Lokered547fdd2017-09-13 17:20:55 -070015496 if (pCfg->enable_mac_spoofing)
15497 wlan_hdd_cfg80211_scan_randomization_init(wiphy);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015498
Dustin Browne74003f2018-03-14 12:51:58 -070015499 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015500 return 0;
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +053015501
15502mem_fail:
15503 hdd_err("Not enough memory to allocate channels");
15504 if (wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels != NULL) {
15505 qdf_mem_free(wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels);
15506 wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels = NULL;
15507 }
15508 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015509}
15510
Abhishek Singhf512bf32016-05-04 16:47:46 +053015511/**
Yingying Tang80e15f32016-09-27 18:23:01 +080015512 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
15513 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053015514 *
15515 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053015516 * memory allocated in wlan_hdd_cfg80211_init also
15517 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053015518 *
15519 * Return: void
15520 */
15521void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
15522{
15523 int i;
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053015524 const uint32_t *cipher_suites;
Abhishek Singhf512bf32016-05-04 16:47:46 +053015525
Srinivas Girigowda5da651b2017-08-04 11:22:54 -070015526 for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053015527 if (NULL != wiphy->bands[i] &&
15528 (NULL != wiphy->bands[i]->channels)) {
15529 qdf_mem_free(wiphy->bands[i]->channels);
15530 wiphy->bands[i]->channels = NULL;
15531 }
15532 }
Amar Singhal5cccafe2017-02-15 12:42:58 -080015533
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053015534 cipher_suites = wiphy->cipher_suites;
15535 wiphy->cipher_suites = NULL;
15536 wiphy->n_cipher_suites = 0;
15537 qdf_mem_free((uint32_t *)cipher_suites);
15538 cipher_suites = NULL;
Abhishek Singh3e6172f2016-05-04 16:56:48 +053015539 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053015540}
15541
Yingying Tang80e15f32016-09-27 18:23:01 +080015542/**
15543 * wlan_hdd_update_band_cap() - update capabilities for supported bands
15544 * @hdd_ctx: HDD context
15545 *
15546 * this function will update capabilities for supported bands
15547 *
15548 * Return: void
15549 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070015550static void wlan_hdd_update_band_cap(struct hdd_context *hdd_ctx)
Yingying Tang80e15f32016-09-27 18:23:01 +080015551{
15552 uint32_t val32;
15553 uint16_t val16;
15554 tSirMacHTCapabilityInfo *ht_cap_info;
15555 QDF_STATUS status;
15556
15557 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
15558 if (QDF_STATUS_SUCCESS != status) {
15559 hdd_err("could not get HT capability info");
15560 val32 = 0;
15561 }
15562 val16 = (uint16_t)val32;
15563 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
15564
15565 if (ht_cap_info->txSTBC == true) {
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015566 if (NULL != hdd_ctx->wiphy->bands[HDD_NL80211_BAND_2GHZ])
15567 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_2GHZ]->ht_cap.cap |=
Yingying Tang80e15f32016-09-27 18:23:01 +080015568 IEEE80211_HT_CAP_TX_STBC;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015569 if (NULL != hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ])
15570 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ]->ht_cap.cap |=
Yingying Tang80e15f32016-09-27 18:23:01 +080015571 IEEE80211_HT_CAP_TX_STBC;
15572 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080015573
15574 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015575 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_2GHZ]->
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080015576 vht_cap.vht_supported = 0;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015577 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_2GHZ]->vht_cap.cap = 0;
15578 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ]->
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080015579 vht_cap.vht_supported = 0;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015580 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ]->vht_cap.cap = 0;
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080015581 }
Yingying Tang80e15f32016-09-27 18:23:01 +080015582}
15583
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015584/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053015585 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015586 * initialization. In wlan_hdd_cfg80211_init, only the
15587 * default values will be initialized. The final initialization
15588 * of all required members can be done here.
15589 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070015590void wlan_hdd_update_wiphy(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015591{
Yingying Tang80e15f32016-09-27 18:23:01 +080015592 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
15593
15594 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015595}
15596
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080015597/**
15598 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
15599 * @cfg: hdd cfg
15600 *
15601 * this function update 11n mode in hdd cfg
15602 *
15603 * Return: void
15604 */
15605void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
15606{
15607 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015608 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080015609 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015610 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080015611 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
15612 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
15613 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
Himanshu Agarwal4ecf6ca2018-05-09 16:48:56 +053015614 cfg->sap_11ac_override = 0;
15615 cfg->go_11ac_override = 0;
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080015616 }
15617 }
15618}
15619
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015620/* In this function we are registering wiphy. */
15621int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
15622{
Dustin Brown491d54b2018-03-14 12:39:11 -070015623 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015624 /* Register our wiphy dev with cfg80211 */
15625 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070015626 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015627 return -EIO;
15628 }
15629
Dustin Browne74003f2018-03-14 12:51:58 -070015630 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015631 return 0;
15632}
15633
15634/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015635 * HDD function to update wiphy capability based on target offload status.
15636 *
15637 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
15638 * capability even before downloading firmware to the target. In discrete
15639 * case, host will get know certain offload capability (say sched_scan
15640 * caps) only after downloading firmware to the target and target boots up.
15641 * This function is used to override setting done in wlan_hdd_cfg80211_init()
15642 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015643 */
15644void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
15645{
15646#ifdef FEATURE_WLAN_SCAN_PNO
Jeff Johnsonb8944722017-09-03 09:03:19 -070015647 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
15648 struct hdd_config *pCfg = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015649
15650 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
15651 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015652 * have PNO support.
15653 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015654 if (!pCfg->PnoOffload) {
Dustin Brown52ba1ce2017-08-16 12:10:55 -070015655 hdd_wiphy_set_max_sched_scans(wiphy, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015656 wiphy->max_sched_scan_ssids = 0;
15657 wiphy->max_match_sets = 0;
15658 wiphy->max_sched_scan_ie_len = 0;
15659 }
15660#endif
15661}
15662
15663/* This function registers for all frame which supplicant is interested in */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015664int wlan_hdd_cfg80211_register_frames(struct hdd_adapter *adapter)
Wu Gao84d120c2017-03-24 18:46:00 +080015665{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015666 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(adapter);
Wu Gao84d120c2017-03-24 18:46:00 +080015667 /* Register for all P2P action, public action etc frames */
15668 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015669 QDF_STATUS status;
Wu Gao84d120c2017-03-24 18:46:00 +080015670
Dustin Brown491d54b2018-03-14 12:39:11 -070015671 hdd_enter();
Wu Gao84d120c2017-03-24 18:46:00 +080015672
15673 /* Register frame indication call back */
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015674 status = sme_register_mgmt_frame_ind_callback(hHal,
15675 hdd_indicate_mgmt_frame);
15676 if (status != QDF_STATUS_SUCCESS) {
15677 hdd_err("Failed to register hdd_indicate_mgmt_frame");
15678 goto ret_status;
15679 }
Wu Gao84d120c2017-03-24 18:46:00 +080015680
Wu Gao84d120c2017-03-24 18:46:00 +080015681 /* Right now we are registering these frame when driver is getting
15682 * initialized. Once we will move to 2.6.37 kernel, in which we have
15683 * frame register ops, we will move this code as a part of that
15684 */
15685
15686 /* GAS Initial Request */
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015687 status = sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
Wu Gao84d120c2017-03-24 18:46:00 +080015688 (uint8_t *) GAS_INITIAL_REQ,
15689 GAS_INITIAL_REQ_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015690 if (status != QDF_STATUS_SUCCESS) {
15691 hdd_err("Failed to register GAS_INITIAL_REQ");
15692 goto ret_status;
15693 }
Wu Gao84d120c2017-03-24 18:46:00 +080015694
15695 /* GAS Initial Response */
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015696 status = sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
Wu Gao84d120c2017-03-24 18:46:00 +080015697 (uint8_t *) GAS_INITIAL_RSP,
15698 GAS_INITIAL_RSP_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015699 if (status != QDF_STATUS_SUCCESS) {
15700 hdd_err("Failed to register GAS_INITIAL_RSP");
15701 goto dereg_gas_initial_req;
15702 }
Wu Gao84d120c2017-03-24 18:46:00 +080015703
15704 /* GAS Comeback Request */
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015705 status = sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
Wu Gao84d120c2017-03-24 18:46:00 +080015706 (uint8_t *) GAS_COMEBACK_REQ,
15707 GAS_COMEBACK_REQ_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015708 if (status != QDF_STATUS_SUCCESS) {
15709 hdd_err("Failed to register GAS_COMEBACK_REQ");
15710 goto dereg_gas_initial_rsp;
15711 }
Wu Gao84d120c2017-03-24 18:46:00 +080015712
15713 /* GAS Comeback Response */
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015714 status = sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
Wu Gao84d120c2017-03-24 18:46:00 +080015715 (uint8_t *) GAS_COMEBACK_RSP,
15716 GAS_COMEBACK_RSP_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015717 if (status != QDF_STATUS_SUCCESS) {
15718 hdd_err("Failed to register GAS_COMEBACK_RSP");
15719 goto dereg_gas_comeback_req;
15720 }
Wu Gao84d120c2017-03-24 18:46:00 +080015721
15722 /* WNM BSS Transition Request frame */
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015723 status = sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
Wu Gao84d120c2017-03-24 18:46:00 +080015724 (uint8_t *) WNM_BSS_ACTION_FRAME,
15725 WNM_BSS_ACTION_FRAME_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015726 if (status != QDF_STATUS_SUCCESS) {
15727 hdd_err("Failed to register WNM_BSS_ACTION_FRAME");
15728 goto dereg_gas_comeback_rsp;
15729 }
Wu Gao84d120c2017-03-24 18:46:00 +080015730
15731 /* WNM-Notification */
Jeff Johnson1b780e42017-10-31 14:11:45 -070015732 status = sme_register_mgmt_frame(hHal, adapter->session_id, type,
Wu Gao84d120c2017-03-24 18:46:00 +080015733 (uint8_t *) WNM_NOTIFICATION_FRAME,
15734 WNM_NOTIFICATION_FRAME_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015735 if (status != QDF_STATUS_SUCCESS) {
15736 hdd_err("Failed to register WNM_NOTIFICATION_FRAME");
15737 goto dereg_wnm_bss_action_frm;
15738 }
15739
Dustin Brown237baee2018-05-10 13:22:18 -070015740 return 0;
15741
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015742dereg_wnm_bss_action_frm:
15743 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
15744 (uint8_t *) WNM_BSS_ACTION_FRAME,
15745 WNM_BSS_ACTION_FRAME_SIZE);
15746dereg_gas_comeback_rsp:
15747 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
15748 (uint8_t *) GAS_COMEBACK_RSP,
15749 GAS_COMEBACK_RSP_SIZE);
15750dereg_gas_comeback_req:
15751 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
15752 (uint8_t *) GAS_COMEBACK_REQ,
15753 GAS_COMEBACK_REQ_SIZE);
15754dereg_gas_initial_rsp:
15755 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
15756 (uint8_t *) GAS_INITIAL_RSP,
15757 GAS_INITIAL_RSP_SIZE);
15758dereg_gas_initial_req:
15759 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
15760 (uint8_t *) GAS_INITIAL_REQ,
15761 GAS_INITIAL_REQ_SIZE);
15762ret_status:
15763 return qdf_status_to_os_return(status);
Wu Gao84d120c2017-03-24 18:46:00 +080015764}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015765
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015766void wlan_hdd_cfg80211_deregister_frames(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015767{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015768 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015769 /* Register for all P2P action, public action etc frames */
15770 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
15771
Dustin Brown491d54b2018-03-14 12:39:11 -070015772 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015773
15774 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015775 * initialized. Once we will move to 2.6.37 kernel, in which we have
15776 * frame register ops, we will move this code as a part of that
15777 */
15778
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015779 /* GAS Initial Request */
15780
15781 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
15782 (uint8_t *) GAS_INITIAL_REQ,
15783 GAS_INITIAL_REQ_SIZE);
15784
15785 /* GAS Initial Response */
15786 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
15787 (uint8_t *) GAS_INITIAL_RSP,
15788 GAS_INITIAL_RSP_SIZE);
15789
15790 /* GAS Comeback Request */
15791 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
15792 (uint8_t *) GAS_COMEBACK_REQ,
15793 GAS_COMEBACK_REQ_SIZE);
15794
15795 /* GAS Comeback Response */
15796 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
15797 (uint8_t *) GAS_COMEBACK_RSP,
15798 GAS_COMEBACK_RSP_SIZE);
15799
15800 /* P2P Public Action */
15801 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
15802 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
15803 P2P_PUBLIC_ACTION_FRAME_SIZE);
15804
15805 /* P2P Action */
15806 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
15807 (uint8_t *) P2P_ACTION_FRAME,
15808 P2P_ACTION_FRAME_SIZE);
15809
15810 /* WNM-Notification */
Jeff Johnson1b780e42017-10-31 14:11:45 -070015811 sme_deregister_mgmt_frame(hHal, adapter->session_id, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015812 (uint8_t *) WNM_NOTIFICATION_FRAME,
15813 WNM_NOTIFICATION_FRAME_SIZE);
15814}
15815
15816#ifdef FEATURE_WLAN_WAPI
Jeff Johnsonfee20aa2017-10-30 21:33:14 -070015817void wlan_hdd_cfg80211_set_key_wapi(struct hdd_adapter *adapter,
15818 uint8_t key_index,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015819 const uint8_t *mac_addr, const uint8_t *key,
15820 int key_Len)
15821{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015822 tCsrRoamSetKey setKey;
15823 bool isConnected = true;
15824 int status = 0;
Krunal Sonibfd05492017-10-03 15:48:37 -070015825 uint32_t roamId = INVALID_ROAM_ID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015826 uint8_t *pKeyPtr = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015827
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015828 hdd_debug("Device_mode %s(%d)",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015829 hdd_device_mode_to_string(adapter->device_mode),
15830 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015831
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015832 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015833 setKey.keyId = key_index; /* Store Key ID */
15834 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
15835 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
15836 setKey.paeRole = 0; /* the PAE role */
Srinivas Girigowda576b2352017-08-25 14:44:26 -070015837 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
Anurag Chouhanc5548422016-02-24 18:33:27 +053015838 qdf_set_macaddr_broadcast(&setKey.peerMac);
Srinivas Girigowda576b2352017-08-25 14:44:26 -070015839 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015840 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda576b2352017-08-25 14:44:26 -070015841
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015842 setKey.keyLength = key_Len;
15843 pKeyPtr = setKey.Key;
15844 memcpy(pKeyPtr, key, key_Len);
15845
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015846 hdd_debug("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015847
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015848 if (isConnected) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015849 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -070015850 adapter->session_id, &setKey, &roamId);
Jeff Johnsonfee20aa2017-10-30 21:33:14 -070015851 if (status != 0)
15852 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015853 }
15854}
15855#endif /* FEATURE_WLAN_WAPI */
15856
Krunal Soni364e0872017-05-10 21:24:34 -070015857bool wlan_hdd_is_ap_supports_immediate_power_save(uint8_t *ies, int length)
15858{
Naveen Rawat08db88f2017-09-08 15:07:48 -070015859 const uint8_t *vendor_ie;
Krunal Soni364e0872017-05-10 21:24:34 -070015860
15861 if (length < 2) {
15862 hdd_debug("bss size is less than expected");
15863 return true;
15864 }
15865 if (!ies) {
15866 hdd_debug("invalid IE pointer");
15867 return true;
15868 }
Naveen Rawat08db88f2017-09-08 15:07:48 -070015869 vendor_ie = wlan_get_vendor_ie_ptr_from_oui(VENDOR1_AP_OUI_TYPE,
Krunal Soni364e0872017-05-10 21:24:34 -070015870 VENDOR1_AP_OUI_TYPE_SIZE, ies, length);
15871 if (vendor_ie) {
15872 hdd_debug("AP can't support immediate powersave. defer it");
15873 return false;
15874 }
15875 return true;
15876}
15877
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015878/*
15879 * FUNCTION: wlan_hdd_validate_operation_channel
15880 * called by wlan_hdd_cfg80211_start_bss() and
15881 * wlan_hdd_set_channel()
15882 * This function validates whether given channel is part of valid
15883 * channel list.
15884 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015885QDF_STATUS wlan_hdd_validate_operation_channel(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015886 int channel)
15887{
15888
15889 uint32_t num_ch = 0;
15890 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
15891 u32 indx = 0;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015892 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015893 uint8_t fValidChannel = false, count = 0;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015894 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(adapter))->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015895
15896 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
15897
15898 if (hdd_pConfig_ini->sapAllowAllChannel) {
15899 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080015900 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070015901 if (channel == WLAN_REG_CH_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015902 fValidChannel = true;
15903 break;
15904 }
15905 }
15906 if (fValidChannel != true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015907 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015908 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015909 }
15910 } else {
15911 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
15912 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070015913 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015914 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015915 }
15916 for (indx = 0; indx < num_ch; indx++) {
Srinivas Girigowda576b2352017-08-25 14:44:26 -070015917 if (channel == valid_ch[indx])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015918 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015919 }
15920
15921 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015922 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015923 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015924 }
15925 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015926 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015927
15928}
15929
15930#ifdef DHCP_SERVER_OFFLOAD
Jeff Johnson9c4f93d2017-10-04 08:56:22 -070015931static void wlan_hdd_set_dhcp_server_offload(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015932{
Jeff Johnson9c4f93d2017-10-04 08:56:22 -070015933 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015934 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
15935 uint8_t numEntries = 0;
15936 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
15937 uint8_t num;
15938 uint32_t temp;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070015939
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015940 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015941 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070015942 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015943 return;
15944 }
Jeff Johnson1b780e42017-10-31 14:11:45 -070015945 pDhcpSrvInfo->vdev_id = adapter->session_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015946 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
Jeff Johnsonb8944722017-09-03 09:03:19 -070015947 pDhcpSrvInfo->dhcpClientNum = hdd_ctx->config->dhcpMaxNumClients;
15948 hdd_string_to_u8_array(hdd_ctx->config->dhcpServerIP,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015949 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
15950 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnsonb8944722017-09-03 09:03:19 -070015951 hdd_err("Incorrect IP address (%s) assigned for DHCP server!", hdd_ctx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015952 goto end;
15953 }
15954 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnsonb8944722017-09-03 09:03:19 -070015955 hdd_err("Invalid IP address (%s)! It could NOT be multicast IP address!", hdd_ctx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015956 goto end;
15957 }
15958 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnsonb8944722017-09-03 09:03:19 -070015959 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 -080015960 goto end;
15961 }
15962 for (num = 0; num < numEntries; num++) {
15963 temp = srv_ip[num];
15964 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
15965 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015966 if (QDF_STATUS_SUCCESS !=
Jeff Johnsonb8944722017-09-03 09:03:19 -070015967 sme_set_dhcp_srv_offload(hdd_ctx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070015968 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015969 goto end;
15970 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015971 hdd_debug("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015972end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015973 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015974}
15975#endif /* DHCP_SERVER_OFFLOAD */
15976
15977static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
15978 struct net_device *dev,
15979 struct bss_parameters *params)
15980{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015981 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
15982 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015983 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053015984 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015985
Dustin Brown491d54b2018-03-14 12:39:11 -070015986 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015987
Anurag Chouhan6d760662016-02-20 16:05:43 +053015988 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070015989 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015990 return -EINVAL;
15991 }
15992
Jeff Johnson1b780e42017-10-31 14:11:45 -070015993 if (wlan_hdd_validate_session_id(adapter->session_id)) {
15994 hdd_err("invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015995 return -EINVAL;
15996 }
15997
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015998 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015999 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
Jeff Johnson1b780e42017-10-31 14:11:45 -070016000 adapter->session_id, params->ap_isolate));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016001 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016002 hdd_device_mode_to_string(adapter->device_mode),
16003 adapter->device_mode, params->ap_isolate);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016004
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016005 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070016006 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016007 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016008 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016009
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016010 if (!(adapter->device_mode == QDF_SAP_MODE ||
16011 adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016012 return -EOPNOTSUPP;
16013 }
16014
16015 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016016 * want to update this parameter
16017 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016018 if (-1 != params->ap_isolate) {
Jeff Johnsonb9424862017-10-30 08:49:35 -070016019 adapter->session.ap.disable_intrabss_fwd =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016020 !!params->ap_isolate;
16021
Jeff Johnsonb8944722017-09-03 09:03:19 -070016022 qdf_ret_status = sme_ap_disable_intra_bss_fwd(hdd_ctx->hHal,
Jeff Johnson1b780e42017-10-31 14:11:45 -070016023 adapter->session_id,
Jeff Johnsonb9424862017-10-30 08:49:35 -070016024 adapter->session.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016025 ap.
Jeff Johnson82ceb082017-10-27 14:52:42 -070016026 disable_intrabss_fwd);
Srinivas Girigowda576b2352017-08-25 14:44:26 -070016027 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016028 ret = -EINVAL;
Sravan Kumar Kairam858073b2018-03-13 09:03:32 +053016029
16030 ucfg_ipa_set_ap_ibss_fwd(hdd_ctx->hdd_pdev,
16031 adapter->session.ap.
16032 disable_intrabss_fwd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016033 }
16034
Dustin Browne74003f2018-03-14 12:51:58 -070016035 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016036 return ret;
16037}
16038
Krunal Soni8c37e322016-02-03 16:08:37 -080016039/**
16040 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
16041 * @ndev: pointer to net device provided by supplicant
16042 * @type: type of the interface, upper layer wanted to change
16043 *
16044 * Upper layer provides the new interface mode that needs to be changed
16045 * for given net device
16046 *
16047 * Return: success or failure in terms of integer value
16048 */
16049static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016050 enum nl80211_iftype type)
16051{
Jeff Johnsone5006672017-08-29 14:39:02 -070016052 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070016053 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080016054 struct hdd_config *config = hdd_ctx->config;
Jeff Johnson20227a92018-03-13 09:41:05 -070016055 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016056 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053016057 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016058
Dustin Brown491d54b2018-03-14 12:39:11 -070016059 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016060
Krunal Soni8c37e322016-02-03 16:08:37 -080016061 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016062 hdd_warn("ACS is in progress, don't change iface!");
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070016063 return -EBUSY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016064 }
16065
16066 wdev = ndev->ieee80211_ptr;
Dustin Browndb2a8be2017-12-20 11:49:56 -080016067 hdd_stop_adapter(hdd_ctx, adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080016068 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016069 wdev->iftype = type;
16070 /*Check for sub-string p2p to confirm its a p2p interface */
16071 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080016072 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016073 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080016074 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080016075 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080016076 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016077 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080016078 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016079 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080016080 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016081 }
Jeff Johnsonb9424862017-10-30 08:49:35 -070016082 memset(&adapter->session, 0, sizeof(adapter->session));
Krunal Soni8c37e322016-02-03 16:08:37 -080016083 hdd_set_station_ops(adapter->dev);
Jeff Johnson20227a92018-03-13 09:41:05 -070016084
16085 roam_profile = hdd_roam_profile(adapter);
16086 roam_profile->pAddIEScan = adapter->scan_info.scan_add_ie.addIEdata;
16087 roam_profile->nAddIEScanLength =
Jeff Johnson37fa0402017-10-28 12:42:29 -070016088 adapter->scan_info.scan_add_ie.length;
Krunal Soni8c37e322016-02-03 16:08:37 -080016089 if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib51eec72017-11-20 21:53:01 -080016090 status = hdd_start_station_adapter(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070016091 roam_profile->BSSType = eCSR_BSS_TYPE_START_IBSS;
16092 roam_profile->phyMode =
Krunal Soni8c37e322016-02-03 16:08:37 -080016093 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
16094 }
Dustin Browne74003f2018-03-14 12:51:58 -070016095 hdd_exit();
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070016096
16097 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016098}
16099
16100static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
16101 struct net_device *dev,
16102 struct bss_parameters *params)
16103{
16104 int ret;
16105
16106 cds_ssr_protect(__func__);
16107 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
16108 cds_ssr_unprotect(__func__);
16109
16110 return ret;
16111}
16112
Rajeev Kumar98edb772016-01-19 12:42:19 -080016113/**
16114 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
16115 * @wiphy: Pointer to the wiphy structure
16116 * @ndev: Pointer to the net device
16117 * @type: Interface type
16118 * @flags: Flags for change interface
16119 * @params: Pointer to change interface parameters
16120 *
16121 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016122 */
16123static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
16124 struct net_device *ndev,
16125 enum nl80211_iftype type,
16126 u32 *flags,
16127 struct vif_params *params)
16128{
16129 struct wireless_dev *wdev;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016130 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070016131 struct hdd_context *hdd_ctx;
Jeff Johnson61b5e982018-03-15 11:33:31 -070016132 struct csr_roam_profile *roam_profile = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016133 eCsrRoamBssType LastBSSType;
16134 struct hdd_config *pConfig = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016135 int status;
16136
Dustin Brown491d54b2018-03-14 12:39:11 -070016137 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016138
Anurag Chouhan6d760662016-02-20 16:05:43 +053016139 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070016140 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016141 return -EINVAL;
16142 }
16143
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016144 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070016145 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016146 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016147 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016148
Nachiket Kukade08b9f292017-11-17 18:27:37 +053016149 if (cds_is_fw_down()) {
16150 hdd_err("Ignore if FW is already down");
16151 return -EINVAL;
16152 }
16153
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016154 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016155 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
Jeff Johnson1b780e42017-10-31 14:11:45 -070016156 adapter->session_id, type));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016157
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016158 hdd_debug("Device_mode = %d, IFTYPE = 0x%x",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016159 adapter->device_mode, type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016160
Dustin Browne7e71d32018-05-11 16:00:08 -070016161 status = hdd_wlan_start_modules(hdd_ctx, false);
Arun Khandavallifae92942016-08-01 13:31:08 +053016162 if (status) {
16163 hdd_err("Failed to start modules");
16164 return -EINVAL;
16165 }
16166
Jeff Johnsonb8944722017-09-03 09:03:19 -070016167 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016168 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
16169 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070016170 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016171 return -EINVAL;
16172 }
16173
Jeff Johnsonb8944722017-09-03 09:03:19 -070016174 pConfig = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016175 wdev = ndev->ieee80211_ptr;
16176
16177 /* Reset the current device mode bit mask */
Jeff Johnsonb8944722017-09-03 09:03:19 -070016178 policy_mgr_clear_concurrency_mode(hdd_ctx->hdd_psoc,
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016179 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016180
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016181 hdd_notify_teardown_tdls_links(adapter->hdd_vdev);
16182 if ((adapter->device_mode == QDF_STA_MODE) ||
16183 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
16184 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
16185 (adapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016186
Jeff Johnson20227a92018-03-13 09:41:05 -070016187 roam_profile = hdd_roam_profile(adapter);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016188 LastBSSType = roam_profile->BSSType;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016189
16190 switch (type) {
16191 case NL80211_IFTYPE_STATION:
16192 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080016193 case NL80211_IFTYPE_ADHOC:
16194 if (type == NL80211_IFTYPE_ADHOC) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016195 hdd_deregister_tx_flow_control(adapter);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016196 hdd_debug("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080016197 }
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070016198 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
Krunal Soni8c37e322016-02-03 16:08:37 -080016199 type);
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070016200 if (status) {
16201 hdd_err("Failed to change iface to new mode:%d status %d",
16202 type, status);
16203 return status;
16204 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016205 if (hdd_start_adapter(adapter)) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053016206 hdd_err("Failed to start adapter :%d",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016207 adapter->device_mode);
Arun Khandavallib2f6c262016-08-18 19:07:19 +053016208 return -EINVAL;
16209 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016210 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016211 case NL80211_IFTYPE_AP:
16212 case NL80211_IFTYPE_P2P_GO:
16213 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016214 hdd_debug("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016215 (type ==
16216 NL80211_IFTYPE_AP) ? "SoftAP" :
16217 "P2pGo");
16218
16219 /* Cancel any remain on channel for GO mode */
16220 if (NL80211_IFTYPE_P2P_GO == type) {
16221 wlan_hdd_cancel_existing_remain_on_channel
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016222 (adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016223 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016224
Dustin Browndb2a8be2017-12-20 11:49:56 -080016225 hdd_stop_adapter(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016226 /* De-init the adapter */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016227 hdd_deinit_adapter(hdd_ctx, adapter, true);
Jeff Johnsonb9424862017-10-30 08:49:35 -070016228 memset(&adapter->session, 0,
16229 sizeof(adapter->session));
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016230 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016231 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080016232 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
16233 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016234
16235 /*
16236 * Fw will take care incase of concurrency
16237 */
16238
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016239 if ((QDF_SAP_MODE == adapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016240 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016241 /* To meet Android requirements create
16242 * a randomized MAC address of the
16243 * form 02:1A:11:Fx:xx:xx
16244 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016245 get_random_bytes(&ndev->dev_addr[3], 3);
16246 ndev->dev_addr[0] = 0x02;
16247 ndev->dev_addr[1] = 0x1A;
16248 ndev->dev_addr[2] = 0x11;
16249 ndev->dev_addr[3] |= 0xF0;
Jeff Johnson1e851a12017-10-28 14:36:12 -070016250 memcpy(adapter->mac_addr.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016251 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053016252 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016253 pr_info("wlan: Generated HotSpot BSSID "
16254 MAC_ADDRESS_STR "\n",
16255 MAC_ADDR_ARRAY(ndev->dev_addr));
16256 }
16257
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016258 hdd_set_ap_ops(adapter->dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016259
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016260 if (hdd_start_adapter(adapter)) {
Arun Khandavallifae92942016-08-01 13:31:08 +053016261 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016262 return -EINVAL;
16263 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016264 /* Interface type changed update in wiphy structure */
16265 if (wdev) {
16266 wdev->iftype = type;
16267 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070016268 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016269 return -EINVAL;
16270 }
16271 goto done;
16272 }
16273
16274 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016275 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016276 return -EOPNOTSUPP;
16277 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016278 } else if ((adapter->device_mode == QDF_SAP_MODE) ||
16279 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016280 switch (type) {
16281 case NL80211_IFTYPE_STATION:
16282 case NL80211_IFTYPE_P2P_CLIENT:
16283 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080016284 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
16285 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016286 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016287 return status;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016288 if (hdd_start_adapter(adapter)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016289 hdd_err("Failed to start adapter: %d",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016290 adapter->device_mode);
Arun Khandavallib2f6c262016-08-18 19:07:19 +053016291 return -EINVAL;
16292 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016293 goto done;
16294
16295 case NL80211_IFTYPE_AP:
16296 case NL80211_IFTYPE_P2P_GO:
16297 wdev->iftype = type;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016298 adapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080016299 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016300 goto done;
16301
16302 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016303 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016304 return -EOPNOTSUPP;
16305 }
16306 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016307 hdd_err("Unsupported device mode: %d",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016308 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016309 return -EOPNOTSUPP;
16310 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016311done:
16312 /* Set bitmask based on updated value */
Jeff Johnsonb8944722017-09-03 09:03:19 -070016313 policy_mgr_set_concurrency_mode(hdd_ctx->hdd_psoc,
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016314 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016315
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016316 hdd_lpass_notify_mode_change(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016317
Dustin Browne74003f2018-03-14 12:51:58 -070016318 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016319 return 0;
16320}
16321
Dustin Brown9ed30a52017-08-16 13:59:38 -070016322#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
Rajeev Kumar98edb772016-01-19 12:42:19 -080016323/**
16324 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
16325 * @wiphy: Pointer to the wiphy structure
16326 * @ndev: Pointer to the net device
16327 * @type: Interface type
16328 * @flags: Flags for change interface
16329 * @params: Pointer to change interface parameters
16330 *
16331 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016332 */
16333static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
16334 struct net_device *ndev,
16335 enum nl80211_iftype type,
16336 u32 *flags,
16337 struct vif_params *params)
16338{
16339 int ret;
16340
16341 cds_ssr_protect(__func__);
16342 ret =
16343 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
16344 cds_ssr_unprotect(__func__);
16345
16346 return ret;
16347}
Dustin Brown9ed30a52017-08-16 13:59:38 -070016348#else
16349static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
16350 struct net_device *ndev,
16351 enum nl80211_iftype type,
16352 struct vif_params *params)
16353{
16354 int ret;
16355
16356 cds_ssr_protect(__func__);
16357 ret = __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type,
16358 &params->flags, params);
16359 cds_ssr_unprotect(__func__);
16360
16361 return ret;
16362}
16363#endif /* KERNEL_VERSION(4, 12, 0) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016364
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016365/**
16366 * __wlan_hdd_change_station() - change station
16367 * @wiphy: Pointer to the wiphy structure
16368 * @dev: Pointer to the net device.
16369 * @mac: bssid
16370 * @params: Pointer to station parameters
16371 *
16372 * Return: 0 for success, error number on failure.
16373 */
16374#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
16375static int __wlan_hdd_change_station(struct wiphy *wiphy,
16376 struct net_device *dev,
16377 const uint8_t *mac,
16378 struct station_parameters *params)
16379#else
16380static int __wlan_hdd_change_station(struct wiphy *wiphy,
16381 struct net_device *dev,
16382 uint8_t *mac,
16383 struct station_parameters *params)
16384#endif
16385{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016386 QDF_STATUS status = QDF_STATUS_SUCCESS;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016387 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070016388 struct hdd_context *hdd_ctx;
Jeff Johnsond377dce2017-10-04 10:32:42 -070016389 struct hdd_station_ctx *sta_ctx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053016390 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016391 int ret;
16392
Dustin Brown491d54b2018-03-14 12:39:11 -070016393 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016394
Anurag Chouhan6d760662016-02-20 16:05:43 +053016395 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016396 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016397 return -EINVAL;
16398 }
16399
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016400 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016401 TRACE_CODE_HDD_CHANGE_STATION,
Jeff Johnson1b780e42017-10-31 14:11:45 -070016402 adapter->session_id, params->listen_interval));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016403
Jeff Johnson1b780e42017-10-31 14:11:45 -070016404 if (wlan_hdd_validate_session_id(adapter->session_id)) {
16405 hdd_err("invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016406 return -EINVAL;
16407 }
16408
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016409 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070016410 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016411 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016412 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016413
Jeff Johnsond377dce2017-10-04 10:32:42 -070016414 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016415
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016416 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016417
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016418 if ((adapter->device_mode == QDF_SAP_MODE) ||
16419 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016420 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
16421 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016422 hdd_softap_change_sta_state(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016423 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080016424 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016425
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016426 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016427 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016428 return -EINVAL;
16429 }
16430 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016431 } else if ((adapter->device_mode == QDF_STA_MODE) ||
16432 (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016433 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud1a28462017-09-06 22:55:48 +080016434#if defined(FEATURE_WLAN_TDLS)
Jeff Johnsonb8944722017-09-03 09:03:19 -070016435 ret = wlan_cfg80211_tdls_update_peer(hdd_ctx->hdd_pdev,
Frank Liud4b2fa02017-03-29 11:46:48 +080016436 dev, mac, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016437#endif
Frank Liud4b2fa02017-03-29 11:46:48 +080016438 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016439 }
Dustin Browne74003f2018-03-14 12:51:58 -070016440 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016441 return ret;
16442}
16443
16444/**
16445 * wlan_hdd_change_station() - cfg80211 change station handler function
16446 * @wiphy: Pointer to the wiphy structure
16447 * @dev: Pointer to the net device.
16448 * @mac: bssid
16449 * @params: Pointer to station parameters
16450 *
16451 * This is the cfg80211 change station handler function which invokes
16452 * the internal function @__wlan_hdd_change_station with
16453 * SSR protection.
16454 *
16455 * Return: 0 for success, error number on failure.
16456 */
16457#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
16458static int wlan_hdd_change_station(struct wiphy *wiphy,
16459 struct net_device *dev,
16460 const u8 *mac,
16461 struct station_parameters *params)
16462#else
16463static int wlan_hdd_change_station(struct wiphy *wiphy,
16464 struct net_device *dev,
16465 u8 *mac,
16466 struct station_parameters *params)
16467#endif
16468{
16469 int ret;
16470
16471 cds_ssr_protect(__func__);
16472 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
16473 cds_ssr_unprotect(__func__);
16474
16475 return ret;
16476}
16477
16478/*
16479 * FUNCTION: __wlan_hdd_cfg80211_add_key
16480 * This function is used to initialize the key information
16481 */
16482static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
16483 struct net_device *ndev,
16484 u8 key_index, bool pairwise,
16485 const u8 *mac_addr,
16486 struct key_params *params)
16487{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016488 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016489 tCsrRoamSetKey setKey;
16490 int status;
Krunal Sonibfd05492017-10-03 15:48:37 -070016491 uint32_t roamId = INVALID_ROAM_ID;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053016492 QDF_STATUS qdf_ret_status;
Jeff Johnsonb8944722017-09-03 09:03:19 -070016493 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016494
Dustin Brown491d54b2018-03-14 12:39:11 -070016495 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016496
Anurag Chouhan6d760662016-02-20 16:05:43 +053016497 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016498 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016499 return -EINVAL;
16500 }
16501
Jeff Johnson1b780e42017-10-31 14:11:45 -070016502 if (wlan_hdd_validate_session_id(adapter->session_id)) {
16503 hdd_err("Invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016504 return -EINVAL;
16505 }
16506
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016507 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016508 TRACE_CODE_HDD_CFG80211_ADD_KEY,
Jeff Johnson1b780e42017-10-31 14:11:45 -070016509 adapter->session_id, params->key_len));
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016510 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070016511 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016512
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016513 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016514 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016515
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016516 hdd_debug("Device_mode %s(%d)",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016517 hdd_device_mode_to_string(adapter->device_mode),
16518 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016519
16520 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016521 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016522
16523 return -EINVAL;
16524 }
16525
16526 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016527 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016528
16529 return -EINVAL;
16530 }
16531
Jeff Johnsonb05f4fd2017-10-18 15:08:21 -070016532 if (CSR_MAX_RSC_LEN < params->seq_len) {
16533 hdd_err("Invalid seq length %d", params->seq_len);
16534
16535 return -EINVAL;
16536 }
16537
16538 hdd_debug("key index %d, key length %d, seq length %d",
16539 key_index, params->key_len, params->seq_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016540
16541 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016542 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016543 setKey.keyId = key_index;
16544 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016545 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Jeff Johnsonb05f4fd2017-10-18 15:08:21 -070016546 qdf_mem_copy(&setKey.keyRsc[0], params->seq, params->seq_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016547
16548 switch (params->cipher) {
16549 case WLAN_CIPHER_SUITE_WEP40:
16550 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
16551 break;
16552
16553 case WLAN_CIPHER_SUITE_WEP104:
16554 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
16555 break;
16556
16557 case WLAN_CIPHER_SUITE_TKIP:
16558 {
16559 u8 *pKey = &setKey.Key[0];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016560
Srinivas Girigowda576b2352017-08-25 14:44:26 -070016561 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016562 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016563
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016564 /* Supplicant sends the 32bytes key in this order
16565 *
16566 * |--------------|----------|----------|
16567 * | Tk1 |TX-MIC | RX Mic |
16568 * |--------------|----------|----------|
16569 * <---16bytes---><--8bytes--><--8bytes-->
16570 *
16571 * Sme expects the 32 bytes key to be in the below order
16572 *
16573 * |--------------|----------|----------|
16574 * | Tk1 |RX-MIC | TX Mic |
16575 * |--------------|----------|----------|
16576 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016577 */
16578 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016579 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016580
16581 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016582 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016583
16584 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016585 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016586
16587 break;
16588 }
16589
16590 case WLAN_CIPHER_SUITE_CCMP:
16591 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
16592 break;
16593
16594#ifdef FEATURE_WLAN_WAPI
16595 case WLAN_CIPHER_SUITE_SMS4:
16596 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016597 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016598 wlan_hdd_cfg80211_set_key_wapi(adapter, key_index,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016599 mac_addr, params->key,
16600 params->key_len);
16601 return 0;
16602 }
16603#endif
16604
16605#ifdef FEATURE_WLAN_ESE
16606 case WLAN_CIPHER_SUITE_KRK:
16607 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
16608 break;
16609#ifdef WLAN_FEATURE_ROAM_OFFLOAD
16610 case WLAN_CIPHER_SUITE_BTK:
16611 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
16612 break;
16613#endif
16614#endif
16615
16616#ifdef WLAN_FEATURE_11W
16617 case WLAN_CIPHER_SUITE_AES_CMAC:
16618 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
16619 break;
Padma, Santhosh Kumar4117d7a2017-12-20 17:39:33 +053016620#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
16621 case WLAN_CIPHER_SUITE_BIP_GMAC_128:
16622 setKey.encType = eCSR_ENCRYPT_TYPE_AES_GMAC_128;
16623 break;
16624 case WLAN_CIPHER_SUITE_BIP_GMAC_256:
16625 setKey.encType = eCSR_ENCRYPT_TYPE_AES_GMAC_256;
16626 break;
16627#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016628#endif
Mukul Sharma05504ac2017-06-08 12:35:53 +053016629 case WLAN_CIPHER_SUITE_GCMP:
16630 setKey.encType = eCSR_ENCRYPT_TYPE_AES_GCMP;
16631 break;
16632 case WLAN_CIPHER_SUITE_GCMP_256:
16633 setKey.encType = eCSR_ENCRYPT_TYPE_AES_GCMP_256;
16634 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016635
16636 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016637 hdd_err("Unsupported cipher type: %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016638 return -EOPNOTSUPP;
16639 }
16640
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016641 hdd_debug("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016642
16643 if (!pairwise) {
16644 /* set group key */
Jeff Johnson96aa2ac2017-10-18 15:55:36 -070016645 hdd_debug("setting Broadcast key");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016646 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053016647 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016648 } else {
16649 /* set pairwise key */
Jeff Johnson96aa2ac2017-10-18 15:55:36 -070016650 hdd_debug("setting pairwise key");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016651 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016652 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016653 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016654 if ((QDF_IBSS_MODE == adapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016655 /* if a key is already installed, block all subsequent ones */
Jeff Johnsonb9424862017-10-30 08:49:35 -070016656 if (adapter->session.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016657 hdd_debug("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016658 return 0;
16659 }
16660
16661 setKey.keyDirection = eSIR_TX_RX;
16662 /*Set the group key */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016663 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -070016664 adapter->session_id, &setKey, &roamId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016665
16666 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016667 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016668 return -EINVAL;
16669 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016670 /* Save the keys here and call sme_roam_set_key for setting
16671 * the PTK after peer joins the IBSS network
16672 */
Jeff Johnsonb9424862017-10-30 08:49:35 -070016673 qdf_mem_copy(&adapter->session.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016674 &setKey, sizeof(tCsrRoamSetKey));
16675
Jeff Johnsonb9424862017-10-30 08:49:35 -070016676 adapter->session.station.ibss_enc_key_installed = 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016677 return status;
16678 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016679 if ((adapter->device_mode == QDF_SAP_MODE) ||
16680 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Nachiket Kukaded9152832017-10-16 16:18:22 +053016681 struct hdd_hostapd_state *hostapd_state =
16682 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
16683 struct hdd_ap_ctx *ap_ctx =
16684 WLAN_HDD_GET_AP_CTX_PTR(adapter);
16685
Jeff Johnson0f9f87b2017-10-28 09:21:06 -070016686 if (hostapd_state->bss_state == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070016687 status = wlansap_set_key_sta(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016688 WLAN_HDD_GET_SAP_CTX_PTR(adapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016689 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016690 hdd_err("wlansap_set_key_sta failed status: %d",
16691 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016692 }
16693 }
16694
Jeff Johnson413c15f2017-10-27 18:56:35 -070016695 /* Save the key in ap ctx for use on START_BSS and restart */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016696 if (pairwise ||
16697 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
16698 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Jeff Johnson3d731362017-10-27 19:06:41 -070016699 qdf_mem_copy(&ap_ctx->wep_key[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016700 sizeof(tCsrRoamSetKey));
16701 else
Jeff Johnson413c15f2017-10-27 18:56:35 -070016702 qdf_mem_copy(&ap_ctx->group_key, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016703 sizeof(tCsrRoamSetKey));
16704
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016705 } else if ((adapter->device_mode == QDF_STA_MODE) ||
16706 (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Jeff Johnsond377dce2017-10-04 10:32:42 -070016707 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016708 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070016709 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016710
16711 if (!pairwise) {
16712 /* set group key */
Jeff Johnsonaf2ae4b2017-11-01 11:38:50 -070016713 if (sta_ctx->roam_info.defer_key_complete) {
Jeff Johnson96aa2ac2017-10-18 15:55:36 -070016714 hdd_debug("Perform Set key Complete");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016715 hdd_perform_roam_set_key_complete(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016716 }
16717 }
16718
Jeff Johnson20227a92018-03-13 09:41:05 -070016719 roam_profile = hdd_roam_profile(adapter);
16720 roam_profile->Keys.KeyLength[key_index] = params->key_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016721
Jeff Johnson20227a92018-03-13 09:41:05 -070016722 roam_profile->Keys.defaultIndex = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016723
Jeff Johnson20227a92018-03-13 09:41:05 -070016724 qdf_mem_copy(&roam_profile->Keys.KeyMaterial[key_index][0],
16725 params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016726
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016727 hdd_debug("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016728 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
16729 setKey.keyDirection);
16730
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016731 /* The supplicant may attempt to set the PTK once
16732 * pre-authentication is done. Save the key in the
16733 * UMAC and include it in the ADD BSS request
16734 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016735 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -070016736 adapter->session_id, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053016737 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016738 hdd_debug("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016739 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053016740 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016741 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016742 return -EINVAL;
16743 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016744
16745 /* issue set key request to SME */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016746 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -070016747 adapter->session_id, &setKey, &roamId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016748
16749 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016750 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016751 return -EINVAL;
16752 }
16753
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016754 /* in case of IBSS as there was no information
16755 * available about WEP keys during IBSS join, group
Jeff Johnson5e19a942018-05-06 15:37:39 -070016756 * key initialized with NULL key, so re-initialize
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016757 * group key with correct value
16758 */
Jeff Johnson20227a92018-03-13 09:41:05 -070016759 if ((eCSR_BSS_TYPE_START_IBSS == roam_profile->BSSType) &&
Jeff Johnson37ecea42018-03-18 17:54:40 -070016760 !((HDD_AUTH_KEY_MGMT_802_1X ==
16761 (sta_ctx->auth_key_mgmt & HDD_AUTH_KEY_MGMT_802_1X))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016762 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
Jeff Johnsond377dce2017-10-04 10:32:42 -070016763 sta_ctx->conn_info.authType)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016764 )
16765 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
16766 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
16767 )
16768 ) {
16769 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053016770 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016771
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016772 hdd_debug("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016773 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
16774 setKey.keyDirection);
16775
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016776 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -070016777 adapter->session_id, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016778 &roamId);
16779
16780 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016781 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016782 return -EINVAL;
16783 }
16784 }
16785 }
Dustin Browne74003f2018-03-14 12:51:58 -070016786 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016787 return 0;
16788}
16789
16790static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
16791 struct net_device *ndev,
16792 u8 key_index, bool pairwise,
16793 const u8 *mac_addr,
16794 struct key_params *params)
16795{
16796 int ret;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070016797
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016798 cds_ssr_protect(__func__);
16799 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
16800 mac_addr, params);
16801 cds_ssr_unprotect(__func__);
16802
16803 return ret;
16804}
16805
16806/*
16807 * FUNCTION: __wlan_hdd_cfg80211_get_key
16808 * This function is used to get the key information
16809 */
16810static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
16811 struct net_device *ndev,
16812 u8 key_index, bool pairwise,
16813 const u8 *mac_addr, void *cookie,
16814 void (*callback)(void *cookie,
16815 struct key_params *)
16816 )
16817{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016818 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson61b5e982018-03-15 11:33:31 -070016819 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016820 struct key_params params;
16821
Dustin Brown491d54b2018-03-14 12:39:11 -070016822 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016823
Anurag Chouhan6d760662016-02-20 16:05:43 +053016824 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016825 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016826 return -EINVAL;
16827 }
16828
Jiachao Wud58cfc92017-12-27 14:15:23 +080016829 if (wlan_hdd_validate_session_id(adapter->session_id)) {
16830 hdd_err("Invalid session id: %d", adapter->session_id);
16831 return -EINVAL;
16832 }
16833
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016834 hdd_debug("Device_mode %s(%d)",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016835 hdd_device_mode_to_string(adapter->device_mode),
16836 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016837
16838 memset(&params, 0, sizeof(params));
16839
16840 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016841 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016842 return -EINVAL;
16843 }
16844
Nachiket Kukaded9152832017-10-16 16:18:22 +053016845 if ((adapter->device_mode == QDF_SAP_MODE) ||
16846 (adapter->device_mode == QDF_P2P_GO_MODE)) {
16847 struct hdd_ap_ctx *ap_ctx =
16848 WLAN_HDD_GET_AP_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070016849
Nachiket Kukaded9152832017-10-16 16:18:22 +053016850 roam_profile =
16851 wlan_sap_get_roam_profile(ap_ctx->sap_context);
16852 } else {
Jeff Johnson20227a92018-03-13 09:41:05 -070016853 roam_profile = hdd_roam_profile(adapter);
Nachiket Kukaded9152832017-10-16 16:18:22 +053016854 }
16855
Jiachao Wud58cfc92017-12-27 14:15:23 +080016856 if (roam_profile == NULL) {
16857 hdd_err("Get roam profile failed!");
16858 return -EINVAL;
16859 }
16860
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016861 switch (roam_profile->EncryptionType.encryptionType[0]) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016862 case eCSR_ENCRYPT_TYPE_NONE:
16863 params.cipher = IW_AUTH_CIPHER_NONE;
16864 break;
16865
16866 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
16867 case eCSR_ENCRYPT_TYPE_WEP40:
16868 params.cipher = WLAN_CIPHER_SUITE_WEP40;
16869 break;
16870
16871 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
16872 case eCSR_ENCRYPT_TYPE_WEP104:
16873 params.cipher = WLAN_CIPHER_SUITE_WEP104;
16874 break;
16875
16876 case eCSR_ENCRYPT_TYPE_TKIP:
16877 params.cipher = WLAN_CIPHER_SUITE_TKIP;
16878 break;
16879
16880 case eCSR_ENCRYPT_TYPE_AES:
16881 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
16882 break;
Mukul Sharma05504ac2017-06-08 12:35:53 +053016883 case eCSR_ENCRYPT_TYPE_AES_GCMP:
16884 params.cipher = WLAN_CIPHER_SUITE_GCMP;
16885 break;
16886 case eCSR_ENCRYPT_TYPE_AES_GCMP_256:
16887 params.cipher = WLAN_CIPHER_SUITE_GCMP_256;
16888 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016889 default:
16890 params.cipher = IW_AUTH_CIPHER_NONE;
16891 break;
16892 }
16893
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016894 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016895 TRACE_CODE_HDD_CFG80211_GET_KEY,
Jeff Johnson1b780e42017-10-31 14:11:45 -070016896 adapter->session_id, params.cipher));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016897
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016898 params.key_len = roam_profile->Keys.KeyLength[key_index];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016899 params.seq_len = 0;
16900 params.seq = NULL;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016901 params.key = &roam_profile->Keys.KeyMaterial[key_index][0];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016902 callback(cookie, &params);
16903
Dustin Browne74003f2018-03-14 12:51:58 -070016904 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016905 return 0;
16906}
16907
16908static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
16909 struct net_device *ndev,
16910 u8 key_index, bool pairwise,
16911 const u8 *mac_addr, void *cookie,
16912 void (*callback)(void *cookie,
16913 struct key_params *)
16914 )
16915{
16916 int ret;
16917
16918 cds_ssr_protect(__func__);
16919 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
16920 mac_addr, cookie, callback);
16921 cds_ssr_unprotect(__func__);
16922
16923 return ret;
16924}
16925
16926/**
16927 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
16928 * @wiphy: wiphy interface context
16929 * @ndev: pointer to net device
16930 * @key_index: Key index used in 802.11 frames
16931 * @unicast: true if it is unicast key
16932 * @multicast: true if it is multicast key
16933 *
16934 * This function is required for cfg80211_ops API.
16935 * It is used to delete the key information
16936 * Underlying hardware implementation does not have API to delete the
16937 * encryption key. It is automatically deleted when the peer is
16938 * removed. Hence this function currently does nothing.
16939 * Future implementation may interprete delete key operation to
16940 * replacing the key with a random junk value, effectively making it
16941 * useless.
16942 *
16943 * Return: status code, always 0.
16944 */
16945
16946static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
16947 struct net_device *ndev,
16948 u8 key_index,
16949 bool pairwise, const u8 *mac_addr)
16950{
Dustin Browne74003f2018-03-14 12:51:58 -070016951 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016952 return 0;
16953}
16954
16955/**
16956 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
16957 * @wiphy: Pointer to wiphy structure.
16958 * @dev: Pointer to net_device structure.
16959 * @key_index: key index
16960 * @pairwise: pairwise
16961 * @mac_addr: mac address
16962 *
16963 * This is the cfg80211 delete key handler function which invokes
16964 * the internal function @__wlan_hdd_cfg80211_del_key with
16965 * SSR protection.
16966 *
16967 * Return: 0 for success, error number on failure.
16968 */
16969static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
16970 struct net_device *dev,
16971 u8 key_index,
16972 bool pairwise, const u8 *mac_addr)
16973{
16974 int ret;
16975
16976 cds_ssr_protect(__func__);
16977 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
16978 pairwise, mac_addr);
16979 cds_ssr_unprotect(__func__);
16980
16981 return ret;
16982}
16983
Hu Wangc3148842017-06-20 19:03:29 +080016984#ifdef FEATURE_WLAN_WAPI
16985static bool hdd_is_wapi_enc_type(eCsrEncryptionType ucEncryptionType)
16986{
16987 if (ucEncryptionType == eCSR_ENCRYPT_TYPE_WPI)
16988 return true;
16989
16990 return false;
16991}
16992#else
16993static bool hdd_is_wapi_enc_type(eCsrEncryptionType ucEncryptionType)
16994{
16995 return false;
16996}
16997#endif
16998
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016999/*
17000 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
17001 * This function is used to set the default tx key index
17002 */
17003static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
17004 struct net_device *ndev,
17005 u8 key_index,
17006 bool unicast, bool multicast)
17007{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017008 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070017009 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017010 int status;
17011
Dustin Brown491d54b2018-03-14 12:39:11 -070017012 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017013
Anurag Chouhan6d760662016-02-20 16:05:43 +053017014 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070017015 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017016 return -EINVAL;
17017 }
17018
Jeff Johnson1b780e42017-10-31 14:11:45 -070017019 if (wlan_hdd_validate_session_id(adapter->session_id)) {
17020 hdd_err("Invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053017021 return -EINVAL;
17022 }
17023
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053017024 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017025 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
Jeff Johnson1b780e42017-10-31 14:11:45 -070017026 adapter->session_id, key_index));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017027
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017028 hdd_debug("Device_mode %s(%d) key_index = %d",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017029 hdd_device_mode_to_string(adapter->device_mode),
17030 adapter->device_mode, key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017031
17032 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017033 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017034 return -EINVAL;
17035 }
17036
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017037 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070017038 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017039
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053017040 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017041 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017042
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017043 if ((adapter->device_mode == QDF_STA_MODE) ||
17044 (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Nachiket Kukaded9152832017-10-16 16:18:22 +053017045 struct hdd_station_ctx *sta_ctx =
17046 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070017047 struct csr_roam_profile *roam_profile;
17048
17049 roam_profile = hdd_roam_profile(adapter);
Nachiket Kukaded9152832017-10-16 16:18:22 +053017050
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017051 if ((eCSR_ENCRYPT_TYPE_TKIP !=
Jeff Johnsond377dce2017-10-04 10:32:42 -070017052 sta_ctx->conn_info.ucEncryptionType) &&
Hu Wangc3148842017-06-20 19:03:29 +080017053 !hdd_is_wapi_enc_type(
Jeff Johnsond377dce2017-10-04 10:32:42 -070017054 sta_ctx->conn_info.ucEncryptionType) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017055 (eCSR_ENCRYPT_TYPE_AES !=
Jeff Johnsond377dce2017-10-04 10:32:42 -070017056 sta_ctx->conn_info.ucEncryptionType) &&
Mukul Sharma05504ac2017-06-08 12:35:53 +053017057 (eCSR_ENCRYPT_TYPE_AES_GCMP !=
Jeff Johnsond377dce2017-10-04 10:32:42 -070017058 sta_ctx->conn_info.ucEncryptionType) &&
Mukul Sharma05504ac2017-06-08 12:35:53 +053017059 (eCSR_ENCRYPT_TYPE_AES_GCMP_256 !=
Jeff Johnsond377dce2017-10-04 10:32:42 -070017060 sta_ctx->conn_info.ucEncryptionType)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017061 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080017062 * then update the default key index
17063 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017064
17065 tCsrRoamSetKey setKey;
Krunal Sonibfd05492017-10-03 15:48:37 -070017066 uint32_t roamId = INVALID_ROAM_ID;
Jeff Johnson20227a92018-03-13 09:41:05 -070017067 tCsrKeys *Keys = &roam_profile->Keys;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017068
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017069 hdd_debug("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017070
17071 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053017072 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017073 setKey.keyId = key_index;
17074 setKey.keyLength = Keys->KeyLength[key_index];
17075
Anurag Chouhan600c3a02016-03-01 10:33:54 +053017076 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017077 &Keys->KeyMaterial[key_index][0],
17078 Keys->KeyLength[key_index]);
17079
17080 setKey.keyDirection = eSIR_TX_RX;
17081
Anurag Chouhanc5548422016-02-24 18:33:27 +053017082 qdf_copy_macaddr(&setKey.peerMac,
Jeff Johnsond377dce2017-10-04 10:32:42 -070017083 &sta_ctx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017084
17085 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
Jeff Johnson20227a92018-03-13 09:41:05 -070017086 roam_profile->EncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017087 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080017088 /* In the case of dynamic wep
17089 * supplicant hardcodes DWEP type to
17090 * eCSR_ENCRYPT_TYPE_WEP104 even
17091 * though ap is configured for WEP-40
17092 * encryption. In this canse the key
17093 * length is 5 but the encryption type
17094 * is 104 hence checking the key
Jeff Johnsonfe8e9492018-05-06 15:40:52 -070017095 * length(5) and encryption type(104)
Jeff Johnsonf3826e12017-01-12 09:49:40 -080017096 * and switching encryption type to 40
17097 */
Jeff Johnson20227a92018-03-13 09:41:05 -070017098 roam_profile->EncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017099 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
Jeff Johnson20227a92018-03-13 09:41:05 -070017100 roam_profile->mcEncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017101 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
17102 }
17103
17104 setKey.encType =
Jeff Johnson20227a92018-03-13 09:41:05 -070017105 roam_profile->EncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017106 encryptionType[0];
17107
17108 /* Issue set key request */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017109 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -070017110 adapter->session_id, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017111 &roamId);
17112
17113 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017114 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017115 status);
17116 return -EINVAL;
17117 }
17118 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017119 } else if (QDF_SAP_MODE == adapter->device_mode) {
Nachiket Kukaded9152832017-10-16 16:18:22 +053017120 struct hdd_ap_ctx *ap_ctx =
17121 WLAN_HDD_GET_AP_CTX_PTR(adapter);
Jeff Johnson61b5e982018-03-15 11:33:31 -070017122 struct csr_roam_profile *profile =
Nachiket Kukaded9152832017-10-16 16:18:22 +053017123 wlan_sap_get_roam_profile(ap_ctx->sap_context);
17124
17125 if (!profile) {
17126 hdd_err("Failed to get SAP Roam Profile");
17127 return -EINVAL;
17128 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017129 /* In SoftAp mode setting key direction for default mode */
17130 if ((eCSR_ENCRYPT_TYPE_TKIP !=
Nachiket Kukaded9152832017-10-16 16:18:22 +053017131 profile->EncryptionType.encryptionType[0]) &&
Mukul Sharma05504ac2017-06-08 12:35:53 +053017132 (eCSR_ENCRYPT_TYPE_AES !=
Nachiket Kukaded9152832017-10-16 16:18:22 +053017133 profile->EncryptionType.encryptionType[0]) &&
Mukul Sharma05504ac2017-06-08 12:35:53 +053017134 (eCSR_ENCRYPT_TYPE_AES_GCMP !=
Nachiket Kukaded9152832017-10-16 16:18:22 +053017135 profile->EncryptionType.encryptionType[0]) &&
Mukul Sharma05504ac2017-06-08 12:35:53 +053017136 (eCSR_ENCRYPT_TYPE_AES_GCMP_256 !=
Nachiket Kukaded9152832017-10-16 16:18:22 +053017137 profile->EncryptionType.encryptionType[0])) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017138 /* Saving key direction for default key index to TX default */
Nachiket Kukaded9152832017-10-16 16:18:22 +053017139 ap_ctx->wep_key[key_index].keyDirection =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017140 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017141 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053017142 key_index);
Nachiket Kukaded9152832017-10-16 16:18:22 +053017143 ap_ctx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017144 }
17145 }
17146
Dustin Browne74003f2018-03-14 12:51:58 -070017147 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017148 return status;
17149}
17150
17151static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
17152 struct net_device *ndev,
17153 u8 key_index,
17154 bool unicast, bool multicast)
17155{
17156 int ret;
Jeff Johnson4f7f7c62017-10-05 08:53:41 -070017157
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017158 cds_ssr_protect(__func__);
17159 ret =
17160 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
17161 multicast);
17162 cds_ssr_unprotect(__func__);
17163
17164 return ret;
17165}
17166
Abhishek Singhc9941602016-08-09 16:06:22 +053017167/*
Abhishek Singhc9941602016-08-09 16:06:22 +053017168 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
17169 * interface that BSS might have been lost.
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017170 * @adapter: adaptor
Abhishek Singhc9941602016-08-09 16:06:22 +053017171 * @bssid: bssid which might have been lost
17172 *
17173 * Return: bss which is unlinked from kernel cache
17174 */
17175struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017176 struct hdd_adapter *adapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017177{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017178 struct net_device *dev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017179 struct wireless_dev *wdev = dev->ieee80211_ptr;
17180 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017181 struct cfg80211_bss *bss = NULL;
17182
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053017183 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053017184 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017185 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070017186 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017187 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017188 hdd_debug("cfg80211_unlink_bss called for BSSID "
Abhishek Singhc9941602016-08-09 16:06:22 +053017189 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017190 cfg80211_unlink_bss(wiphy, bss);
17191 }
17192 return bss;
17193}
17194
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017195#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017196static inline int
17197wlan_hdd_get_frame_len(struct bss_description *bss_desc)
17198{
17199 return GET_IE_LEN_IN_BSS(bss_desc->length) + sizeof(qcom_ie_age);
17200}
17201
17202static inline void wlan_hdd_add_age_ie(struct ieee80211_mgmt *mgmt,
Abhishek Singhf1c16762018-03-07 10:48:46 +053017203 uint32_t *ie_length, struct bss_description *bss_desc)
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017204{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017205 qcom_ie_age *qie_age = NULL;
Nachiket Kukade348ede72017-04-28 16:34:24 +053017206
17207 /*
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017208 * GPS Requirement: need age ie per entry. Using vendor specific.
17209 * Assuming this is the last IE, copy at the end
Nachiket Kukade348ede72017-04-28 16:34:24 +053017210 */
Abhishek Singhf1c16762018-03-07 10:48:46 +053017211 *ie_length -= sizeof(qcom_ie_age);
17212 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + *ie_length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017213 qie_age->element_id = QCOM_VENDOR_IE_ID;
17214 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
17215 qie_age->oui_1 = QCOM_OUI1;
17216 qie_age->oui_2 = QCOM_OUI2;
17217 qie_age->oui_3 = QCOM_OUI3;
17218 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053017219 /*
17220 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
17221 * all bss related timestamp is in units of ms. Due to this when scan
17222 * results are sent to lowi the scan age is high.To address this,
17223 * send age in units of 1/10 ms.
17224 */
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017225 qie_age->age = (uint32_t)(qdf_mc_timer_get_system_time() -
17226 bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017227 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070017228 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
17229 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070017230 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
17231 sizeof(qie_age->seq_ctrl));
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017232}
17233#else
17234static inline int
17235wlan_hdd_get_frame_len(struct bss_description *bss_desc)
17236{
17237 return GET_IE_LEN_IN_BSS(bss_desc->length);
17238}
17239static inline void wlan_hdd_add_age_ie(struct ieee80211_mgmt *mgmt,
Abhishek Singhf1c16762018-03-07 10:48:46 +053017240 uint32_t *ie_length, struct bss_description *bss_desc)
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017241{
17242}
17243#endif /* WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017244
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017245
17246struct cfg80211_bss *
17247wlan_hdd_inform_bss_frame(struct hdd_adapter *adapter,
17248 struct bss_description *bss_desc)
17249{
17250 struct wireless_dev *wdev = adapter->dev->ieee80211_ptr;
17251 struct wiphy *wiphy = wdev->wiphy;
Abhishek Singhf1c16762018-03-07 10:48:46 +053017252 uint32_t ie_length = wlan_hdd_get_frame_len(bss_desc);
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017253 const char *ie =
17254 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
17255 uint32_t freq, i;
17256 struct cfg80211_bss *bss_status = NULL;
17257 struct hdd_context *hdd_ctx;
17258 struct timespec ts;
17259 struct hdd_config *cfg_param;
17260 struct wlan_cfg80211_inform_bss bss_data = {0};
17261
17262 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
17263 /*
17264 * wlan_hdd_validate_context should not be used here, In validate ctx
17265 * start_modules_in_progress or stop_modules_in_progress is validated,
17266 * If the start_modules_in_progress is set to true means the interface
17267 * is not UP yet if the stop_modules_in_progress means that interface
17268 * is already down. So in both the two scenario's driver should not be
17269 * informing bss to kernel. Hence removing the validate context.
17270 */
17271
17272 if (!hdd_ctx || !hdd_ctx->config) {
17273 hdd_debug("HDD context is Null");
17274 return NULL;
17275 }
17276
17277 if (cds_is_driver_recovering() ||
17278 cds_is_load_or_unload_in_progress()) {
17279 hdd_debug("Recovery or load/unload in progress. State: 0x%x",
17280 cds_get_driver_state());
17281 return NULL;
17282 }
17283
17284 cfg_param = hdd_ctx->config;
17285 bss_data.frame_len = ie_length + offsetof(struct ieee80211_mgmt,
17286 u.probe_resp.variable);
17287 bss_data.mgmt = qdf_mem_malloc(bss_data.frame_len);
17288 if (!bss_data.mgmt) {
17289 hdd_err("memory allocation failed");
17290 return NULL;
17291 }
17292
17293 memcpy(bss_data.mgmt->bssid, bss_desc->bssId, ETH_ALEN);
17294
17295 /* Android does not want the timestamp from the frame.
17296 * Instead it wants a monotonic increasing value
17297 */
17298 get_monotonic_boottime(&ts);
17299 bss_data.mgmt->u.probe_resp.timestamp =
17300 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
17301
17302 bss_data.mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
17303 bss_data.mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
17304
Abhishek Singhf1c16762018-03-07 10:48:46 +053017305 wlan_hdd_add_age_ie(bss_data.mgmt, &ie_length, bss_desc);
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017306
17307 memcpy(bss_data.mgmt->u.probe_resp.variable, ie, ie_length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017308 if (bss_desc->fProbeRsp) {
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017309 bss_data.mgmt->frame_control |=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017310 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
17311 } else {
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017312 bss_data.mgmt->frame_control |=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017313 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
17314 }
17315
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017316 if (bss_desc->channelId <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070017317 (wiphy->bands[HDD_NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017318 freq =
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017319 ieee80211_channel_to_frequency(bss_desc->channelId,
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -070017320 HDD_NL80211_BAND_2GHZ);
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017321 } else if ((bss_desc->channelId > ARRAY_SIZE(hdd_channels_2_4_ghz))
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070017322 && (wiphy->bands[HDD_NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017323 freq =
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017324 ieee80211_channel_to_frequency(bss_desc->channelId,
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -070017325 HDD_NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017326 } else {
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017327 hdd_err("Invalid channel: %d", bss_desc->channelId);
17328 qdf_mem_free(bss_data.mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017329 return NULL;
17330 }
17331
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017332 bss_data.chan = ieee80211_get_channel(wiphy, freq);
17333 if (!bss_data.chan) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053017334 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017335 bss_desc->channelId, freq);
17336 qdf_mem_free(bss_data.mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017337 return NULL;
17338 }
17339
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017340 /*
17341 * Based on .ini configuration, raw rssi can be reported for bss.
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070017342 * Raw rssi is typically used for estimating power.
17343 */
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017344 bss_data.rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070017345 bss_desc->rssi;
17346
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017347 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017348 bss_data.rssi = QDF_MIN(bss_data.rssi, 0) * 100;
17349
17350 bss_data.boottime_ns = bss_desc->scansystimensec;
17351
17352 /* Set all per chain rssi as invalid */
17353 for (i = 0; i < WLAN_MGMT_TXRX_HOST_MAX_ANTENNA; i++)
17354 bss_data.per_chain_snr[i] = WLAN_INVALID_PER_CHAIN_RSSI;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017355
Srinivas Girigowdac06543c2017-03-09 15:10:03 -080017356 hdd_debug("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017357 MAC_ADDR_ARRAY(bss_data.mgmt->bssid), bss_data.chan->center_freq,
17358 (int)(bss_data.rssi / 100),
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070017359 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017360
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017361 bss_status = wlan_cfg80211_inform_bss_frame_data(wiphy, &bss_data);
Jeff Johnsonb8944722017-09-03 09:03:19 -070017362 hdd_ctx->beacon_probe_rsp_cnt_per_scan++;
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017363 qdf_mem_free(bss_data.mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017364 return bss_status;
17365}
17366
17367/**
17368 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017369 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070017370 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017371 *
17372 * This function is used to update the BSS data base of CFG8011
17373 *
17374 * Return: struct cfg80211_bss pointer
17375 */
Jeff Johnson172237b2017-11-07 15:32:59 -080017376struct cfg80211_bss *
17377wlan_hdd_cfg80211_update_bss_db(struct hdd_adapter *adapter,
17378 struct csr_roam_info *roam_info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017379{
17380 tCsrRoamConnectedProfile roamProfile;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017381 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017382 struct cfg80211_bss *bss = NULL;
17383
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017384 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
Jeff Johnson1b780e42017-10-31 14:11:45 -070017385 sme_roam_get_connect_profile(hHal, adapter->session_id, &roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017386
17387 if (NULL != roamProfile.pBssDesc) {
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017388 bss = wlan_hdd_inform_bss_frame(adapter, roamProfile.pBssDesc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017389
17390 if (NULL == bss)
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017391 hdd_debug("wlan_hdd_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017392
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080017393 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017394 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070017395 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017396 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017397 return bss;
17398}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017399
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017400/**
17401 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017402 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070017403 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017404 * @index: Index
17405 * @preauth: Preauth flag
17406 *
17407 * This function is used to notify the supplicant of a new PMKSA candidate.
Deepak Dhamdhere828f1892017-02-09 11:51:19 -080017408 * PMK value is notified to supplicant whether PMK caching or OKC is enabled
17409 * in firmware or not. Supplicant needs this value becaue it uses PMK caching
17410 * by default.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017411 *
17412 * Return: 0 for success, non-zero for failure
17413 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017414int wlan_hdd_cfg80211_pmksa_candidate_notify(struct hdd_adapter *adapter,
Jeff Johnson172237b2017-11-07 15:32:59 -080017415 struct csr_roam_info *roam_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017416 int index, bool preauth)
17417{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017418 struct net_device *dev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017419
Dustin Brown491d54b2018-03-14 12:39:11 -070017420 hdd_enter();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017421 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017422
Jeff Johnsonfd060852017-10-04 10:50:51 -070017423 if (NULL == roam_info) {
17424 hdd_err("roam_info is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017425 return -EINVAL;
17426 }
17427
Dustin Brown5e89ef82018-03-14 11:50:23 -070017428 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Deepak Dhamdhere828f1892017-02-09 11:51:19 -080017429 cfg80211_pmksa_candidate_notify(dev, index,
Jeff Johnsonfd060852017-10-04 10:50:51 -070017430 roam_info->bssid.bytes,
Deepak Dhamdhere828f1892017-02-09 11:51:19 -080017431 preauth, GFP_KERNEL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017432 return 0;
17433}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017434
17435#ifdef FEATURE_WLAN_LFR_METRICS
17436/**
17437 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017438 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070017439 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017440 *
17441 * 802.11r/LFR metrics reporting function to report preauth initiation
17442 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053017443 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017444 */
17445#define MAX_LFR_METRICS_EVENT_LENGTH 100
Jeff Johnson172237b2017-11-07 15:32:59 -080017446QDF_STATUS
17447wlan_hdd_cfg80211_roam_metrics_preauth(struct hdd_adapter *adapter,
17448 struct csr_roam_info *roam_info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017449{
17450 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
17451 union iwreq_data wrqu;
17452
Dustin Brown491d54b2018-03-14 12:39:11 -070017453 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017454
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017455 if (NULL == adapter) {
17456 hdd_err("adapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017457 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017458 }
17459
17460 /* create the event */
17461 memset(&wrqu, 0, sizeof(wrqu));
17462 memset(metrics_notification, 0, sizeof(metrics_notification));
17463
17464 wrqu.data.pointer = metrics_notification;
17465 wrqu.data.length = scnprintf(metrics_notification,
17466 sizeof(metrics_notification),
17467 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
Jeff Johnsonfd060852017-10-04 10:50:51 -070017468 MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017469
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017470 wireless_send_event(adapter->dev, IWEVCUSTOM, &wrqu,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017471 metrics_notification);
17472
Dustin Browne74003f2018-03-14 12:51:58 -070017473 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017474
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017475 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017476}
17477
17478/**
17479 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017480 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070017481 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017482 * @preauth_status: Preauth status
17483 *
17484 * 802.11r/LFR metrics reporting function to report handover initiation
17485 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053017486 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017487 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017488QDF_STATUS
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017489wlan_hdd_cfg80211_roam_metrics_preauth_status(struct hdd_adapter *adapter,
Jeff Johnson172237b2017-11-07 15:32:59 -080017490 struct csr_roam_info *roam_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017491 bool preauth_status)
17492{
17493 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
17494 union iwreq_data wrqu;
17495
Dustin Brown491d54b2018-03-14 12:39:11 -070017496 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017497
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017498 if (NULL == adapter) {
17499 hdd_err("adapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017500 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017501 }
17502
17503 /* create the event */
17504 memset(&wrqu, 0, sizeof(wrqu));
17505 memset(metrics_notification, 0, sizeof(metrics_notification));
17506
17507 scnprintf(metrics_notification, sizeof(metrics_notification),
17508 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
Jeff Johnsonfd060852017-10-04 10:50:51 -070017509 MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017510
17511 if (1 == preauth_status)
17512 strlcat(metrics_notification, " true",
17513 sizeof(metrics_notification));
17514 else
17515 strlcat(metrics_notification, " false",
17516 sizeof(metrics_notification));
17517
17518 wrqu.data.pointer = metrics_notification;
17519 wrqu.data.length = strlen(metrics_notification);
17520
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017521 wireless_send_event(adapter->dev, IWEVCUSTOM, &wrqu,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017522 metrics_notification);
17523
Dustin Browne74003f2018-03-14 12:51:58 -070017524 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017525
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017526 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017527}
17528
17529/**
17530 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017531 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070017532 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017533 *
17534 * 802.11r/LFR metrics reporting function to report handover initiation
17535 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053017536 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017537 */
Jeff Johnson172237b2017-11-07 15:32:59 -080017538QDF_STATUS
17539wlan_hdd_cfg80211_roam_metrics_handover(struct hdd_adapter *adapter,
17540 struct csr_roam_info *roam_info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017541{
17542 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
17543 union iwreq_data wrqu;
17544
Dustin Brown491d54b2018-03-14 12:39:11 -070017545 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017546
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017547 if (NULL == adapter) {
17548 hdd_err("adapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017549 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017550 }
17551
17552 /* create the event */
17553 memset(&wrqu, 0, sizeof(wrqu));
17554 memset(metrics_notification, 0, sizeof(metrics_notification));
17555
17556 wrqu.data.pointer = metrics_notification;
17557 wrqu.data.length = scnprintf(metrics_notification,
17558 sizeof(metrics_notification),
17559 "QCOM: LFR_PREAUTH_HANDOVER "
17560 MAC_ADDRESS_STR,
Jeff Johnsonfd060852017-10-04 10:50:51 -070017561 MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017562
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017563 wireless_send_event(adapter->dev, IWEVCUSTOM, &wrqu,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017564 metrics_notification);
17565
Dustin Browne74003f2018-03-14 12:51:58 -070017566 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017567
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017568 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017569}
17570#endif
17571
Nirav Shah73713f72018-05-17 14:50:41 +053017572#ifdef FEATURE_MONITOR_MODE_SUPPORT
17573static
17574void hdd_mon_select_cbmode(struct hdd_adapter *adapter,
17575 uint8_t operationChannel,
17576 struct ch_params *ch_params)
17577{
17578 struct hdd_station_ctx *station_ctx =
17579 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
17580 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
17581 enum hdd_dot11_mode hdd_dot11_mode;
17582 uint8_t ini_dot11_mode =
17583 (WLAN_HDD_GET_CTX(adapter))->config->dot11Mode;
17584
17585 hdd_debug("Dot11Mode is %u", ini_dot11_mode);
17586 switch (ini_dot11_mode) {
17587 case eHDD_DOT11_MODE_AUTO:
17588 case eHDD_DOT11_MODE_11ax:
17589 case eHDD_DOT11_MODE_11ax_ONLY:
17590 if (sme_is_feature_supported_by_fw(DOT11AX))
17591 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
17592 else if (sme_is_feature_supported_by_fw(DOT11AC))
17593 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
17594 else
17595 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
17596 break;
17597 case eHDD_DOT11_MODE_11ac:
17598 case eHDD_DOT11_MODE_11ac_ONLY:
17599 if (sme_is_feature_supported_by_fw(DOT11AC))
17600 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
17601 else
17602 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
17603 break;
17604 case eHDD_DOT11_MODE_11n:
17605 case eHDD_DOT11_MODE_11n_ONLY:
17606 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
17607 break;
17608 default:
17609 hdd_dot11_mode = ini_dot11_mode;
17610 break;
17611 }
17612 ch_info->channel_width = ch_params->ch_width;
17613 ch_info->phy_mode =
17614 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
17615 ch_info->channel = operationChannel;
17616 ch_info->cb_mode = ch_params->ch_width;
17617 hdd_debug("ch_info width %d, phymode %d channel %d",
17618 ch_info->channel_width, ch_info->phy_mode,
17619 ch_info->channel);
17620}
17621#else
17622static
17623void hdd_mon_select_cbmode(struct hdd_adapter *adapter,
17624 uint8_t operationChannel,
17625 struct ch_params *ch_params)
17626{
17627}
17628#endif
17629
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017630/**
17631 * hdd_select_cbmode() - select channel bonding mode
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017632 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017633 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017634 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017635 *
17636 * Return: none
17637 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017638void hdd_select_cbmode(struct hdd_adapter *adapter, uint8_t operationChannel,
Amar Singhal5cccafe2017-02-15 12:42:58 -080017639 struct ch_params *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017640{
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017641 uint8_t sec_ch = 0;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017642 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017643
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017644 /*
17645 * CDS api expects secondary channel for calculating
17646 * the channel params
17647 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017648 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017649 (WLAN_REG_IS_24GHZ_CH(operationChannel))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017650 if (operationChannel >= 1 && operationChannel <= 5)
17651 sec_ch = operationChannel + 4;
17652 else if (operationChannel >= 6 && operationChannel <= 13)
17653 sec_ch = operationChannel - 4;
17654 }
17655
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017656 /* This call decides required channel bonding mode */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017657 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, operationChannel,
17658 sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017659
Nirav Shah73713f72018-05-17 14:50:41 +053017660 if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE)
17661 hdd_mon_select_cbmode(adapter, operationChannel, ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017662}
17663
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017664/**
17665 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
17666 * @adapter: STA adapter
17667 * @roam_profile: STA roam profile
17668 *
17669 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
17670 *
17671 * Return: false if sta-sap conc is not allowed, else return true
17672 */
Jeff Johnson61b5e982018-03-15 11:33:31 -070017673static
17674bool wlan_hdd_handle_sap_sta_dfs_conc(struct hdd_adapter *adapter,
17675 struct csr_roam_profile *roam_profile)
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017676{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070017677 struct hdd_context *hdd_ctx;
Jeff Johnsone5006672017-08-29 14:39:02 -070017678 struct hdd_adapter *ap_adapter;
Jeff Johnson87251032017-08-29 13:31:11 -070017679 struct hdd_ap_ctx *hdd_ap_ctx;
Jeff Johnsonca2530c2017-09-30 18:25:40 -070017680 struct hdd_hostapd_state *hostapd_state;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017681 uint8_t channel = 0;
17682 QDF_STATUS status;
17683
17684 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
17685 if (!hdd_ctx) {
17686 hdd_err("HDD context is NULL");
17687 return true;
17688 }
17689
17690 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
17691 /* probably no sap running, no handling required */
17692 if (ap_adapter == NULL)
17693 return true;
17694
17695 /*
17696 * sap is not in started state, so it is fine to go ahead with sta.
17697 * if sap is currently doing CAC then don't allow sta to go further.
17698 */
17699 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
17700 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
17701 return true;
17702
17703 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
17704 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
17705 return false;
17706 }
17707
17708 /*
17709 * log and return error, if we allow STA to go through, we don't
17710 * know what is going to happen better stop sta connection
17711 */
17712 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
17713 if (NULL == hdd_ap_ctx) {
17714 hdd_err("AP context not found");
17715 return false;
17716 }
17717
17718 /* sap is on non-dfs channel, nothing to handle */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017719 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
Jeff Johnson01206862017-10-27 20:55:59 -070017720 hdd_ap_ctx->operating_channel)) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017721 hdd_info("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017722 return true;
17723 }
17724 /*
17725 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053017726 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017727 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017728 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->hdd_psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017729 roam_profile, &channel);
17730
Nitesh Shah59774522016-09-16 15:14:21 +053017731 /*
17732 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
17733 * channels for roaming case.
17734 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017735 if (WLAN_REG_IS_24GHZ_CH(channel)) {
17736 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053017737 return true;
17738 }
17739
17740 /*
Jeff Johnsondcf84ce2017-10-05 09:26:24 -070017741 * If channel is 0 or DFS or LTE unsafe then better to call pcl and
Tushnim Bhattacharyya9a929992017-06-18 00:59:09 -070017742 * find out the best channel. If channel is non-dfs 5 GHz then
17743 * better move SAP to STA's channel to make scc, so we have room
17744 * for 3port MCC scenario.
Nitesh Shah59774522016-09-16 15:14:21 +053017745 */
Tushnim Bhattacharyya9a929992017-06-18 00:59:09 -070017746 if ((0 == channel) || wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel) ||
17747 !policy_mgr_is_safe_channel(hdd_ctx->hdd_psoc, channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017748 channel = policy_mgr_get_nondfs_preferred_channel(
17749 hdd_ctx->hdd_psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017750
17751 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
17752 qdf_event_reset(&hostapd_state->qdf_event);
17753 status = wlansap_set_channel_change_with_csa(
17754 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
Jeff Johnson91df29d2017-10-27 19:29:50 -070017755 hdd_ap_ctx->sap_config.ch_width_orig, false);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017756
17757 if (QDF_STATUS_SUCCESS != status) {
17758 hdd_err("Set channel with CSA IE failed, can't allow STA");
17759 return false;
17760 }
17761
17762 /*
17763 * wait here for SAP to finish the channel switch. When channel
17764 * switch happens, SAP sends few beacons with CSA_IE. After
17765 * successfully Transmission of those beacons, it will move its
17766 * state from started to disconnected and move to new channel.
17767 * once it moves to new channel, sap again moves its state
17768 * machine from disconnected to started and set this event.
17769 * wait for 10 secs to finish this.
17770 */
Nachiket Kukade0396b732017-11-14 16:35:16 +053017771 status = qdf_wait_for_event_completion(&hostapd_state->qdf_event, 10000);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017772 if (!QDF_IS_STATUS_SUCCESS(status)) {
17773 hdd_err("wait for qdf_event failed, STA not allowed!!");
17774 return false;
17775 }
17776
17777 return true;
17778}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017779
Abhishek Singhcfb44482017-03-10 12:42:37 +053017780#ifdef WLAN_FEATURE_11W
17781/**
17782 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
17783 * @roam_profile: pointer to roam profile
17784 *
17785 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
17786 * or pmf=2 is an explicit configuration in the supplicant
17787 * configuration, drop the connection request.
17788 *
17789 * Return: 0 if check result is valid, otherwise return error code
17790 */
Jeff Johnson61b5e982018-03-15 11:33:31 -070017791static
17792int wlan_hdd_cfg80211_check_pmf_valid(struct csr_roam_profile *roam_profile)
Abhishek Singhcfb44482017-03-10 12:42:37 +053017793{
17794 if (roam_profile->MFPEnabled &&
Jeff Johnson20227a92018-03-13 09:41:05 -070017795 !(roam_profile->MFPRequired || roam_profile->MFPCapable)) {
Abhishek Singhcfb44482017-03-10 12:42:37 +053017796 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
17797 roam_profile->MFPEnabled,
17798 roam_profile->MFPRequired,
17799 roam_profile->MFPCapable);
17800 return -EINVAL;
17801 }
17802 return 0;
17803}
17804#else
17805static inline
Jeff Johnson61b5e982018-03-15 11:33:31 -070017806int wlan_hdd_cfg80211_check_pmf_valid(struct csr_roam_profile *roam_profile)
Abhishek Singhcfb44482017-03-10 12:42:37 +053017807{
17808 return 0;
17809}
17810#endif
17811
Krunal Soni31949422016-07-29 17:17:53 -070017812/**
17813 * wlan_hdd_cfg80211_connect_start() - to start the association process
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017814 * @adapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070017815 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017816 * @ssid_len: Length of ssid
17817 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070017818 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017819 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017820 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017821 *
17822 * This function is used to start the association process
17823 *
17824 * Return: 0 for success, non-zero for failure
17825 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017826static int wlan_hdd_cfg80211_connect_start(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017827 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070017828 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017829 u8 operatingChannel,
17830 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017831{
17832 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080017833 QDF_STATUS qdf_status;
Jeff Johnsonb8944722017-09-03 09:03:19 -070017834 struct hdd_context *hdd_ctx;
Jeff Johnson40dae4e2017-08-29 14:00:25 -070017835 struct hdd_station_ctx *hdd_sta_ctx;
Krunal Sonibfd05492017-10-03 15:48:37 -070017836 uint32_t roamId = INVALID_ROAM_ID;
Jeff Johnson61b5e982018-03-15 11:33:31 -070017837 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017838 eCsrAuthType RSNAuthType;
17839 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053017840 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017841
Dustin Brown491d54b2018-03-14 12:39:11 -070017842 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017843
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017844 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
17845 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017846
Jeff Johnsonb8944722017-09-03 09:03:19 -070017847 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053017848 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017849 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017850
17851 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070017852 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017853 status = -EINVAL;
17854 goto ret_status;
17855 }
17856
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017857 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017858 hdd_err("Connection refused: conn in progress");
17859 status = -EINVAL;
17860 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017861 }
17862
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017863 hdd_notify_teardown_tdls_links(adapter->hdd_vdev);
Nitesh Shah273e4e52017-04-03 12:53:36 +053017864
Anurag Chouhand939d3d2016-07-20 17:45:48 +053017865 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
17866 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017867
Jeff Johnson20227a92018-03-13 09:41:05 -070017868 roam_profile = hdd_roam_profile(adapter);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017869 if (roam_profile) {
Jeff Johnsond377dce2017-10-04 10:32:42 -070017870 struct hdd_station_ctx *sta_ctx;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070017871
Jeff Johnsond377dce2017-10-04 10:32:42 -070017872 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017873
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017874 /* Restart the opportunistic timer
17875 *
17876 * If hw_mode_change_in_progress is true, then wait
17877 * till firmware sends the callback for hw_mode change.
17878 *
17879 * Else set connect_in_progress as true and proceed.
17880 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017881 policy_mgr_restart_opportunistic_timer(
Jeff Johnsonb8944722017-09-03 09:03:19 -070017882 hdd_ctx->hdd_psoc, false);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017883 if (policy_mgr_is_hw_mode_change_in_progress(
Jeff Johnsonb8944722017-09-03 09:03:19 -070017884 hdd_ctx->hdd_psoc)) {
Abhishek Singh471652b2017-04-14 12:28:32 +053017885 qdf_status = policy_mgr_wait_for_connection_update(
Jeff Johnsonb8944722017-09-03 09:03:19 -070017886 hdd_ctx->hdd_psoc);
Abhishek Singh471652b2017-04-14 12:28:32 +053017887 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017888 hdd_err("qdf wait for event failed!!");
17889 status = -EINVAL;
17890 goto ret_status;
17891 }
17892 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017893 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017894
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017895 if (HDD_WMM_USER_MODE_NO_QOS ==
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017896 (WLAN_HDD_GET_CTX(adapter))->config->WmmMode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017897 /*QoS not enabled in cfg file */
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017898 roam_profile->uapsd_mask = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017899 } else {
17900 /*QoS enabled, update uapsd mask from cfg file */
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017901 roam_profile->uapsd_mask =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017902 (WLAN_HDD_GET_CTX(adapter))->config->UapsdMask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017903 }
17904
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017905 roam_profile->SSIDs.numOfSSIDs = 1;
17906 roam_profile->SSIDs.SSIDList->SSID.length = ssid_len;
17907 qdf_mem_zero(roam_profile->SSIDs.SSIDList->SSID.ssId,
17908 sizeof(roam_profile->SSIDs.SSIDList->SSID.ssId));
17909 qdf_mem_copy((void *)(roam_profile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017910 ssid, ssid_len);
17911
Abhishek Singh1f217ec2017-12-22 11:48:27 +053017912 roam_profile->supplicant_disabled_roaming = false;
Varun Reddy Yeturue5a35d12017-10-20 11:26:57 -070017913
Abhishek Singh3c9910e2017-01-06 17:56:47 +053017914 /* cleanup bssid hint */
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017915 qdf_mem_zero(roam_profile->bssid_hint.bytes,
Abhishek Singh3c9910e2017-01-06 17:56:47 +053017916 QDF_MAC_ADDR_SIZE);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017917 qdf_mem_zero((void *)(roam_profile->BSSIDs.bssid),
Abhishek Singh3c9910e2017-01-06 17:56:47 +053017918 QDF_MAC_ADDR_SIZE);
17919
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017920 if (bssid) {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017921 roam_profile->BSSIDs.numOfBSSIDs = 1;
Varun Reddy Yeturue5a35d12017-10-20 11:26:57 -070017922 roam_profile->supplicant_disabled_roaming = true;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017923 qdf_mem_copy((void *)(roam_profile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053017924 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070017925 /*
Jeff Johnsonfa7d9602018-05-06 11:25:31 -070017926 * Save BSSID in separate variable as
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017927 * roam_profile's BSSID is getting zeroed out in the
Krunal Soni31949422016-07-29 17:17:53 -070017928 * association process. In case of join failure
17929 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017930 */
Jeff Johnson731bc322017-10-14 19:53:44 -070017931 qdf_mem_copy(sta_ctx->requested_bssid.bytes,
17932 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017933 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017934 } else if (bssid_hint) {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017935 qdf_mem_copy(roam_profile->bssid_hint.bytes,
Abhishek Singh3c9910e2017-01-06 17:56:47 +053017936 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070017937 /*
17938 * Save BSSID in a separate variable as
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017939 * roam_profile's BSSID is getting zeroed out in the
Krunal Soni31949422016-07-29 17:17:53 -070017940 * association process. In case of join failure
17941 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017942 */
Jeff Johnson731bc322017-10-14 19:53:44 -070017943 qdf_mem_copy(sta_ctx->requested_bssid.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053017944 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017945 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070017946 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017947 }
17948
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017949 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017950 roam_profile->SSIDs.SSIDList->SSID.length,
17951 roam_profile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017952 operatingChannel);
17953
Jeff Johnsonce4a8342017-10-14 13:12:22 -070017954 if (hdd_sta_ctx->wpa_versions) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017955 hdd_set_genie_to_csr(adapter, &RSNAuthType);
17956 hdd_set_csr_auth_type(adapter, RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017957 }
17958#ifdef FEATURE_WLAN_WAPI
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070017959 if (adapter->wapi_info.wapi_mode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017960 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070017961 switch (adapter->wapi_info.wapi_auth_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017962 case WAPI_AUTH_MODE_PSK:
17963 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017964 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070017965 adapter->wapi_info.wapi_auth_mode);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017966 roam_profile->AuthType.authType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017967 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
17968 break;
17969 }
17970 case WAPI_AUTH_MODE_CERT:
17971 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017972 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070017973 adapter->wapi_info.wapi_auth_mode);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017974 roam_profile->AuthType.authType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017975 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
17976 break;
17977 }
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070017978 default:
17979 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017980 } /* End of switch */
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070017981 if (adapter->wapi_info.wapi_auth_mode ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017982 WAPI_AUTH_MODE_PSK
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070017983 || adapter->wapi_info.wapi_auth_mode ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017984 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017985 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017986 roam_profile->AuthType.numEntries = 1;
17987 roam_profile->EncryptionType.numEntries = 1;
17988 roam_profile->EncryptionType.encryptionType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017989 eCSR_ENCRYPT_TYPE_WPI;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017990 roam_profile->mcEncryptionType.numEntries = 1;
17991 roam_profile->mcEncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017992 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
17993 }
17994 }
Krunal Soni31949422016-07-29 17:17:53 -070017995#endif
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017996 pmo_ucfg_flush_gtk_offload_req(adapter->hdd_vdev);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017997 roam_profile->csrPersona = adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017998
17999 if (operatingChannel) {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018000 roam_profile->ChannelInfo.ChannelList =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018001 &operatingChannel;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018002 roam_profile->ChannelInfo.numOfChannels = 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018003 } else {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018004 roam_profile->ChannelInfo.ChannelList = NULL;
18005 roam_profile->ChannelInfo.numOfChannels = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018006 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018007 if ((QDF_IBSS_MODE == adapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018008 && operatingChannel) {
18009 /*
18010 * Need to post the IBSS power save parameters
18011 * to WMA. WMA will configure this parameters
18012 * to firmware if power save is enabled by the
18013 * firmware.
18014 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018015 qdf_status = hdd_set_ibss_power_save_params(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018016
Abhishek Singh471652b2017-04-14 12:28:32 +053018017 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018018 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018019 status = -EINVAL;
18020 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018021 }
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018022 roam_profile->ch_params.ch_width =
Naveen Rawatc77e6e72016-08-05 15:19:03 -070018023 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053018024 /*
18025 * In IBSS mode while operating in 2.4 GHz,
18026 * the device supports only 20 MHz.
18027 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070018028 if (WLAN_REG_IS_24GHZ_CH(operatingChannel))
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018029 roam_profile->ch_params.ch_width =
Nitesh Shah87335a52016-09-05 15:47:32 +053018030 CH_WIDTH_20MHZ;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018031 hdd_select_cbmode(adapter, operatingChannel,
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018032 &roam_profile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018033 }
18034
Jeff Johnson20227a92018-03-13 09:41:05 -070018035 if (wlan_hdd_cfg80211_check_pmf_valid(roam_profile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018036 status = -EINVAL;
18037 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018038 }
18039
Krunal Soni31949422016-07-29 17:17:53 -070018040 /*
18041 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018042 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070018043 * enhancements, the supplicant is not issuing the scan command
18044 * now. So the unicast frames which are sent from the host are
18045 * not having the additional IEs. If it is P2P CLIENT and there
18046 * is no additional IE present in roamProfile, then use the
18047 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018048 */
18049
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018050 if ((adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018051 (!roam_profile->pAddIEScan)) {
18052 roam_profile->pAddIEScan =
Jeff Johnson37fa0402017-10-28 12:42:29 -070018053 &adapter->scan_info.scan_add_ie.addIEdata[0];
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018054 roam_profile->nAddIEScanLength =
Jeff Johnson37fa0402017-10-28 12:42:29 -070018055 adapter->scan_info.scan_add_ie.length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018056 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018057
Jeff Johnsonb8944722017-09-03 09:03:19 -070018058 if ((policy_mgr_is_hw_dbs_capable(hdd_ctx->hdd_psoc) == true)
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018059 && (false == wlan_hdd_handle_sap_sta_dfs_conc(adapter,
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018060 roam_profile))) {
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070018061 hdd_err("sap-sta conc will fail, can't allow sta");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018062 hdd_conn_set_connection_state(adapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070018063 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018064 status = -ENOMEM;
18065 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070018066 }
18067
Anurag Chouhan600c3a02016-03-01 10:33:54 +053018068 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018069 if (!sme_config) {
18070 hdd_err("unable to allocate sme_config");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018071 hdd_conn_set_connection_state(adapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070018072 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018073 status = -ENOMEM;
18074 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018075 }
Jeff Johnsonb8944722017-09-03 09:03:19 -070018076 sme_get_config_param(hdd_ctx->hHal, sme_config);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018077 /* These values are not sessionized. So, any change in these SME
18078 * configs on an older or parallel interface will affect the
18079 * cb mode. So, restoring the default INI params before starting
18080 * interfaces such as sta, cli etc.,
18081 */
18082 sme_config->csrConfig.channelBondingMode5GHz =
Jeff Johnsonb8944722017-09-03 09:03:19 -070018083 hdd_ctx->config->nChannelBondingMode5GHz;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018084 sme_config->csrConfig.channelBondingMode24GHz =
Jeff Johnsonb8944722017-09-03 09:03:19 -070018085 hdd_ctx->config->nChannelBondingMode24GHz;
18086 sme_update_config(hdd_ctx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053018087 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053018088 /*
18089 * Change conn_state to connecting before sme_roam_connect(),
18090 * because sme_roam_connect() has a direct path to call
18091 * hdd_sme_roam_callback(), which will change the conn_state
18092 * If direct path, conn_state will be accordingly changed to
18093 * NotConnected or Associated by either
18094 * hdd_association_completion_handler() or
18095 * hdd_dis_connect_handler() in sme_RoamCallback()if
18096 * sme_RomConnect is to be queued,
18097 * Connecting state will remain until it is completed.
18098 *
18099 * If connection state is not changed, connection state will
18100 * remain in eConnectionState_NotConnected state.
18101 * In hdd_association_completion_handler, "hddDisconInProgress"
18102 * is set to true if conn state is
18103 * eConnectionState_NotConnected.
18104 * If "hddDisconInProgress" is set to true then cfg80211 layer
18105 * is not informed of connect result indication which
18106 * is an issue.
18107 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018108 if (QDF_STA_MODE == adapter->device_mode ||
18109 QDF_P2P_CLIENT_MODE == adapter->device_mode)
18110 hdd_conn_set_connection_state(adapter,
Agrawal Ashish6b015762016-05-05 11:22:18 +053018111 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018112
Alok Kumarb64650c2018-03-23 17:05:11 +053018113 hdd_set_disconnect_status(adapter, false);
18114
Jingxiang Geb49aa302018-01-17 20:54:15 +080018115 qdf_runtime_pm_prevent_suspend(
18116 &hdd_ctx->runtime_context.connect);
Padma, Santhosh Kumarc88de482018-04-09 16:17:04 +053018117 hdd_prevent_suspend_timeout(HDD_WAKELOCK_CONNECT_COMPLETE,
Dustin Brownceed67e2017-05-26 11:57:31 -070018118 WIFI_POWER_EVENT_WAKELOCK_CONNECT);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018119 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -070018120 adapter->session_id, roam_profile,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018121 &roamId);
Abhishek Singh471652b2017-04-14 12:28:32 +053018122 if (QDF_IS_STATUS_ERROR(qdf_status))
18123 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018124
Rajeev Kumard31e1542017-01-13 14:37:42 -080018125 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018126 (QDF_STA_MODE == adapter->device_mode ||
18127 QDF_P2P_CLIENT_MODE == adapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018128 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080018129 "qdf_status %d. -> NotConnected",
Jeff Johnson1b780e42017-10-31 14:11:45 -070018130 adapter->session_id, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018131 /* change back to NotAssociated */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018132 hdd_conn_set_connection_state(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018133 eConnectionState_NotConnected);
Jingxiang Geb49aa302018-01-17 20:54:15 +080018134 qdf_runtime_pm_allow_suspend(
18135 &hdd_ctx->runtime_context.connect);
Dustin Brownceed67e2017-05-26 11:57:31 -070018136 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_CONNECT);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018137 }
18138
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018139 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080018140 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018141
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018142 roam_profile->ChannelInfo.ChannelList = NULL;
18143 roam_profile->ChannelInfo.numOfChannels = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018144
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018145 if ((QDF_STA_MODE == adapter->device_mode)
Jeff Johnsonb8944722017-09-03 09:03:19 -070018146 && policy_mgr_is_current_hwmode_dbs(hdd_ctx->hdd_psoc)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080018147 && !policy_mgr_is_hw_dbs_2x2_capable(
Jeff Johnsonb8944722017-09-03 09:03:19 -070018148 hdd_ctx->hdd_psoc)) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080018149 policy_mgr_get_channel_from_scan_result(
Jeff Johnsonb8944722017-09-03 09:03:19 -070018150 hdd_ctx->hdd_psoc,
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018151 roam_profile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080018152 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053018153 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080018154 policy_mgr_checkn_update_hw_mode_single_mac_mode(
Jeff Johnsonb8944722017-09-03 09:03:19 -070018155 hdd_ctx->hdd_psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053018156 }
18157
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018158 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018159 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018160 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018161 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018162 goto ret_status;
18163
18164conn_failure:
18165 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080018166 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018167
18168ret_status:
Dustin Browne74003f2018-03-14 12:51:58 -070018169 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018170 return status;
18171}
18172
18173/**
18174 * wlan_hdd_cfg80211_set_auth_type() - set auth type
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018175 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018176 * @auth_type: Auth type
18177 *
18178 * This function is used to set the authentication type (OPEN/SHARED).
18179 *
18180 * Return: 0 for success, non-zero for failure
18181 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018182static int wlan_hdd_cfg80211_set_auth_type(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018183 enum nl80211_auth_type auth_type)
18184{
Jeff Johnsond377dce2017-10-04 10:32:42 -070018185 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018186 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070018187 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018188
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018189 /*set authentication type */
18190 switch (auth_type) {
18191 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018192 hdd_debug("set authentication type to AUTOSWITCH");
Jeff Johnsond377dce2017-10-04 10:32:42 -070018193 sta_ctx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018194 break;
18195
18196 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018197 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018198 hdd_debug("set authentication type to OPEN");
Jeff Johnsond377dce2017-10-04 10:32:42 -070018199 sta_ctx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018200 break;
18201
18202 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018203 hdd_debug("set authentication type to SHARED");
Jeff Johnsond377dce2017-10-04 10:32:42 -070018204 sta_ctx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018205 break;
18206#ifdef FEATURE_WLAN_ESE
18207 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018208 hdd_debug("set authentication type to CCKM WPA");
Jeff Johnsond377dce2017-10-04 10:32:42 -070018209 sta_ctx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018210 break;
18211#endif
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053018212#if defined(WLAN_FEATURE_FILS_SK) && \
18213 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
18214 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018215 case NL80211_AUTHTYPE_FILS_SK:
Dustin Brown5e89ef82018-03-14 11:50:23 -070018216 hdd_debug("set authentication type to FILS SHARED");
Jeff Johnsond377dce2017-10-04 10:32:42 -070018217 sta_ctx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018218 break;
18219#endif
Padma, Santhosh Kumar07eb80b2017-07-05 16:10:06 +053018220 case NL80211_AUTHTYPE_SAE:
18221 hdd_debug("set authentication type to SAE");
18222 sta_ctx->conn_info.authType = eCSR_AUTH_TYPE_SAE;
18223 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018224 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018225 hdd_err("Unsupported authentication type: %d", auth_type);
Jeff Johnsond377dce2017-10-04 10:32:42 -070018226 sta_ctx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018227 return -EINVAL;
18228 }
18229
Jeff Johnson20227a92018-03-13 09:41:05 -070018230 roam_profile = hdd_roam_profile(adapter);
18231 roam_profile->AuthType.authType[0] = sta_ctx->conn_info.authType;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018232 return 0;
18233}
18234
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053018235#if defined(WLAN_FEATURE_FILS_SK) && \
18236 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
18237 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Jeff Johnson20227a92018-03-13 09:41:05 -070018238static bool hdd_validate_fils_info_ptr(struct csr_roam_profile *roam_profile)
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018239{
18240 struct cds_fils_connection_info *fils_con_info;
18241
Jeff Johnson20227a92018-03-13 09:41:05 -070018242 fils_con_info = roam_profile->fils_con_info;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018243 if (!fils_con_info) {
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018244 hdd_err("No valid Roam profile");
18245 return false;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018246 }
18247
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018248 return true;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018249}
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018250
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018251static enum eAniAuthType wlan_hdd_get_fils_auth_type(
18252 enum nl80211_auth_type auth)
18253{
18254 switch (auth) {
18255 case NL80211_AUTHTYPE_FILS_SK:
18256 return SIR_FILS_SK_WITHOUT_PFS;
18257 case NL80211_AUTHTYPE_FILS_SK_PFS:
18258 return SIR_FILS_SK_WITH_PFS;
18259 case NL80211_AUTHTYPE_FILS_PK:
18260 return SIR_FILS_PK_AUTH;
18261 default:
18262 return eSIR_DONOT_USE_AUTH_TYPE;
18263 }
18264}
18265
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080018266static bool wlan_hdd_fils_data_in_limits(struct cfg80211_connect_params *req)
18267{
18268 hdd_debug("seq=%d auth=%d lengths: user=%zu rrk=%zu realm=%zu",
18269 req->fils_erp_next_seq_num, req->auth_type,
18270 req->fils_erp_username_len, req->fils_erp_rrk_len,
18271 req->fils_erp_realm_len);
18272 if (!req->fils_erp_rrk_len || !req->fils_erp_realm_len ||
18273 !req->fils_erp_username_len ||
18274 req->fils_erp_rrk_len > FILS_MAX_RRK_LENGTH ||
18275 req->fils_erp_realm_len > FILS_MAX_REALM_LEN ||
18276 req->fils_erp_username_len > FILS_MAX_KEYNAME_NAI_LENGTH) {
18277 hdd_err("length incorrect, user=%zu rrk=%zu realm=%zu",
18278 req->fils_erp_username_len, req->fils_erp_rrk_len,
18279 req->fils_erp_realm_len);
18280 return false;
18281 }
18282
18283 return true;
18284}
18285
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018286/**
18287 * wlan_hdd_cfg80211_set_fils_config() - set fils config params during connect
18288 * @adapter: Pointer to adapter
18289 * @req: Pointer to fils parameters
18290 *
18291 * Return: 0 for success, non-zero for failure
18292 */
18293static int wlan_hdd_cfg80211_set_fils_config(struct hdd_adapter *adapter,
18294 struct cfg80211_connect_params *req)
18295{
Jeff Johnson61b5e982018-03-15 11:33:31 -070018296 struct csr_roam_profile *roam_profile;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018297 enum eAniAuthType auth_type;
18298 uint8_t *buf;
18299 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
18300
Jeff Johnson20227a92018-03-13 09:41:05 -070018301 roam_profile = hdd_roam_profile(adapter);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018302
18303 if (!hdd_ctx->config->is_fils_enabled) {
18304 hdd_err("FILS disabled");
18305 return -EINVAL;
18306 }
18307 hdd_clear_fils_connection_info(adapter);
18308 roam_profile->fils_con_info =
18309 qdf_mem_malloc(sizeof(*roam_profile->fils_con_info));
18310
18311 if (!roam_profile->fils_con_info) {
18312 hdd_err("failed to allocate memory");
18313 return -EINVAL;
18314 }
18315 /*
18316 * The initial connection for FILS may happen with an OPEN
18317 * auth type. Hence we need to allow the connection to go
18318 * through in that case as well. Below is_fils_connection
18319 * flag is propagated down to CSR and PE sessions through
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080018320 * the JOIN request. As the flag is used, do not free the
18321 * memory allocated to fils_con_info and return success.
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018322 */
18323 if (req->auth_type != NL80211_AUTHTYPE_FILS_SK) {
18324 roam_profile->fils_con_info->is_fils_connection = false;
18325 return 0;
18326 }
18327
18328 /*
18329 * Once above check is done, then we can check for valid FILS
18330 * auth types. Currently only NL80211_AUTHTYPE_FILS_SK is
18331 * supported. Once all auth types are supported, then we can
18332 * merge these 2 conditions into one.
18333 */
18334 auth_type = wlan_hdd_get_fils_auth_type(req->auth_type);
18335 if (auth_type == eSIR_DONOT_USE_AUTH_TYPE) {
18336 hdd_err("invalid auth type for fils %d", req->auth_type);
Varun Reddy Yeturu82e39cd2017-10-16 12:04:05 -070018337 goto fils_conn_fail;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018338 }
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080018339 if (!wlan_hdd_fils_data_in_limits(req))
Jeff Johnsonb8adae42018-02-27 16:12:00 -080018340 goto fils_conn_fail;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018341
18342 roam_profile->fils_con_info->is_fils_connection = true;
18343 roam_profile->fils_con_info->sequence_number =
18344 req->fils_erp_next_seq_num;
18345 roam_profile->fils_con_info->auth_type = auth_type;
18346
18347 roam_profile->fils_con_info->r_rk_length =
18348 req->fils_erp_rrk_len;
18349 if (req->fils_erp_rrk_len)
18350 qdf_mem_copy(roam_profile->fils_con_info->r_rk,
18351 req->fils_erp_rrk,
18352 roam_profile->fils_con_info->r_rk_length);
18353
18354 roam_profile->fils_con_info->realm_len = req->fils_erp_realm_len;
18355 if (req->fils_erp_realm_len)
18356 qdf_mem_copy(roam_profile->fils_con_info->realm,
18357 req->fils_erp_realm,
18358 roam_profile->fils_con_info->realm_len);
18359
18360 roam_profile->fils_con_info->key_nai_length =
18361 req->fils_erp_username_len + sizeof(char) +
18362 req->fils_erp_realm_len;
18363 hdd_debug("key_nai_length = %d",
18364 roam_profile->fils_con_info->key_nai_length);
Varun Reddy Yeturu82e39cd2017-10-16 12:04:05 -070018365 if (roam_profile->fils_con_info->key_nai_length >
18366 FILS_MAX_KEYNAME_NAI_LENGTH) {
18367 hdd_err("Do not allow FILS conn due to excess NAI Length %d",
18368 roam_profile->fils_con_info->key_nai_length);
18369 goto fils_conn_fail;
18370 }
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080018371 buf = roam_profile->fils_con_info->keyname_nai;
18372 qdf_mem_copy(buf, req->fils_erp_username, req->fils_erp_username_len);
18373 buf += req->fils_erp_username_len;
18374 *buf++ = '@';
18375 qdf_mem_copy(buf, req->fils_erp_realm, req->fils_erp_realm_len);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018376
18377 return 0;
Varun Reddy Yeturu82e39cd2017-10-16 12:04:05 -070018378
18379fils_conn_fail:
18380 if (roam_profile->fils_con_info) {
18381 qdf_mem_free(roam_profile->fils_con_info);
18382 roam_profile->fils_con_info = NULL;
18383 }
18384 return -EINVAL;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018385}
18386
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018387static bool wlan_hdd_is_akm_suite_fils(uint32_t key_mgmt)
18388{
18389 switch (key_mgmt) {
18390 case WLAN_AKM_SUITE_FILS_SHA256:
18391 case WLAN_AKM_SUITE_FILS_SHA384:
18392 case WLAN_AKM_SUITE_FT_FILS_SHA256:
18393 case WLAN_AKM_SUITE_FT_FILS_SHA384:
18394 return true;
18395 default:
18396 return false;
18397 }
18398}
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018399
18400static bool wlan_hdd_is_conn_type_fils(struct cfg80211_connect_params *req)
18401{
18402 enum nl80211_auth_type auth_type = req->auth_type;
18403 /*
18404 * Below n_akm_suites is defined as int in the kernel, even though it
18405 * is supposed to be unsigned.
18406 */
18407 int num_akm_suites = req->crypto.n_akm_suites;
18408 uint32_t key_mgmt = req->crypto.akm_suites[0];
18409 enum eAniAuthType fils_auth_type =
18410 wlan_hdd_get_fils_auth_type(req->auth_type);
18411
18412 hdd_debug("Num of AKM suites = %d", num_akm_suites);
18413 if (num_akm_suites <= 0)
18414 return false;
18415
18416 /*
18417 * Auth type will be either be OPEN or FILS type for a FILS connection
18418 */
18419 if ((auth_type != NL80211_AUTHTYPE_OPEN_SYSTEM) &&
18420 (fils_auth_type == eSIR_DONOT_USE_AUTH_TYPE)) {
18421 hdd_debug("Not a FILS auth type, auth = %d, fils auth = %d",
18422 auth_type, fils_auth_type);
18423 return false;
18424 }
18425
18426 if (!wlan_hdd_is_akm_suite_fils(key_mgmt)) {
18427 hdd_debug("Not a FILS AKM SUITE %d", key_mgmt);
18428 return false;
18429 }
18430
18431 return true;
18432}
18433
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018434#else
Jeff Johnson20227a92018-03-13 09:41:05 -070018435static bool hdd_validate_fils_info_ptr(struct csr_roam_profile *roam_profile)
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018436{
18437 return true;
18438}
18439
18440static int wlan_hdd_cfg80211_set_fils_config(struct hdd_adapter *adapter,
18441 struct cfg80211_connect_params *req)
18442{
18443 return 0;
18444}
18445
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018446static bool wlan_hdd_is_akm_suite_fils(uint32_t key_mgmt)
18447{
18448 return false;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018449}
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018450
18451static bool wlan_hdd_is_conn_type_fils(struct cfg80211_connect_params *req)
18452{
18453 return false;
18454}
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018455#endif
18456
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018457/**
18458 * wlan_hdd_set_akm_suite() - set key management type
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018459 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018460 * @key_mgmt: Key management type
18461 *
18462 * This function is used to set the key mgmt type(PSK/8021x).
18463 *
18464 * Return: 0 for success, non-zero for failure
18465 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018466static int wlan_hdd_set_akm_suite(struct hdd_adapter *adapter, u32 key_mgmt)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018467{
Jeff Johnson37ecea42018-03-18 17:54:40 -070018468 struct hdd_station_ctx *sta_ctx;
Jeff Johnson61b5e982018-03-15 11:33:31 -070018469 struct csr_roam_profile *roam_profile;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018470
Jeff Johnson20227a92018-03-13 09:41:05 -070018471 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018472
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018473 if (wlan_hdd_is_akm_suite_fils(key_mgmt) &&
Jeff Johnson20227a92018-03-13 09:41:05 -070018474 !hdd_validate_fils_info_ptr(roam_profile))
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018475 return -EINVAL;
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053018476#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018477#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053018478#endif
18479#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018480#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053018481#endif
Jeff Johnson37ecea42018-03-18 17:54:40 -070018482
18483 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
18484
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018485 /*set key mgmt type */
18486 switch (key_mgmt) {
18487 case WLAN_AKM_SUITE_PSK:
18488 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018489 case WLAN_AKM_SUITE_FT_PSK:
Abhishek Singh02cb9e02017-08-30 17:39:50 +053018490 case WLAN_AKM_SUITE_DPP_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018491 hdd_debug("setting key mgmt type to PSK");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018492 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_PSK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018493 break;
18494
18495 case WLAN_AKM_SUITE_8021X_SHA256:
18496 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018497 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018498 hdd_debug("setting key mgmt type to 8021x");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018499 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018500 break;
18501#ifdef FEATURE_WLAN_ESE
18502#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018503 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018504 hdd_debug("setting key mgmt type to CCKM");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018505 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_CCKM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018506 break;
18507#endif
18508#ifndef WLAN_AKM_SUITE_OSEN
18509#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
18510#endif
18511 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018512 hdd_debug("setting key mgmt type to OSEN");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018513 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018514 break;
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053018515#if defined(WLAN_FEATURE_FILS_SK) && \
18516 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
18517 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Sridhar Selvaraj6cf642f2017-08-21 14:28:10 +053018518 case WLAN_AKM_SUITE_FILS_SHA256:
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018519 hdd_debug("setting key mgmt type to FILS SHA256");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018520 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018521 roam_profile->fils_con_info->akm_type =
18522 eCSR_AUTH_TYPE_FILS_SHA256;
18523 break;
18524
18525 case WLAN_AKM_SUITE_FILS_SHA384:
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018526 hdd_debug("setting key mgmt type to FILS SHA384");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018527 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018528 roam_profile->fils_con_info->akm_type =
18529 eCSR_AUTH_TYPE_FILS_SHA384;
18530 break;
18531
18532 case WLAN_AKM_SUITE_FT_FILS_SHA256:
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018533 hdd_debug("setting key mgmt type to FILS FT SHA256");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018534 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018535 roam_profile->fils_con_info->akm_type =
18536 eCSR_AUTH_TYPE_FT_FILS_SHA256;
18537 break;
18538
18539 case WLAN_AKM_SUITE_FT_FILS_SHA384:
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018540 hdd_debug("setting key mgmt type to FILS FT SHA384");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018541 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018542 roam_profile->fils_con_info->akm_type =
18543 eCSR_AUTH_TYPE_FT_FILS_SHA384;
Sridhar Selvaraj6cf642f2017-08-21 14:28:10 +053018544 break;
18545#endif
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053018546
18547 case WLAN_AKM_SUITE_OWE:
18548 hdd_debug("setting key mgmt type to OWE");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018549 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053018550 break;
18551
Padma, Santhosh Kumare587a5c2017-12-21 12:44:46 +053018552 case WLAN_AKM_SUITE_EAP_SHA256:
18553 hdd_debug("setting key mgmt type to EAP_SHA256");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018554 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumare587a5c2017-12-21 12:44:46 +053018555 break;
18556 case WLAN_AKM_SUITE_EAP_SHA384:
18557 hdd_debug("setting key mgmt type to EAP_SHA384");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018558 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumare587a5c2017-12-21 12:44:46 +053018559 break;
18560
Padma, Santhosh Kumar07eb80b2017-07-05 16:10:06 +053018561 case WLAN_AKM_SUITE_SAE:
18562 hdd_debug("setting key mgmt type to SAE");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018563 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumar07eb80b2017-07-05 16:10:06 +053018564 break;
18565
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018566 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018567 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018568 return -EINVAL;
18569
18570 }
18571 return 0;
18572}
18573
18574/**
18575 * wlan_hdd_cfg80211_set_cipher() - set encryption type
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018576 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018577 * @cipher: Cipher type
18578 * @ucast: Unicast flag
18579 *
18580 * This function is used to set the encryption type
18581 * (NONE/WEP40/WEP104/TKIP/CCMP).
18582 *
18583 * Return: 0 for success, non-zero for failure
18584 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018585static int wlan_hdd_cfg80211_set_cipher(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018586 u32 cipher, bool ucast)
18587{
18588 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
Jeff Johnsond377dce2017-10-04 10:32:42 -070018589 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018590 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070018591 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018592
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018593 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018594 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018595 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
18596 } else {
18597
18598 /*set encryption method */
18599 switch (cipher) {
18600 case IW_AUTH_CIPHER_NONE:
18601 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
18602 break;
18603
18604 case WLAN_CIPHER_SUITE_WEP40:
18605 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
18606 break;
18607
18608 case WLAN_CIPHER_SUITE_WEP104:
18609 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
18610 break;
18611
18612 case WLAN_CIPHER_SUITE_TKIP:
18613 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
18614 break;
18615
18616 case WLAN_CIPHER_SUITE_CCMP:
18617 encryptionType = eCSR_ENCRYPT_TYPE_AES;
18618 break;
18619#ifdef FEATURE_WLAN_WAPI
18620 case WLAN_CIPHER_SUITE_SMS4:
18621 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
18622 break;
18623#endif
18624
18625#ifdef FEATURE_WLAN_ESE
18626 case WLAN_CIPHER_SUITE_KRK:
18627 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
18628 break;
18629#ifdef WLAN_FEATURE_ROAM_OFFLOAD
18630 case WLAN_CIPHER_SUITE_BTK:
18631 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
18632 break;
18633#endif
18634#endif
Mukul Sharma05504ac2017-06-08 12:35:53 +053018635 case WLAN_CIPHER_SUITE_GCMP:
18636 encryptionType = eCSR_ENCRYPT_TYPE_AES_GCMP;
18637 break;
18638 case WLAN_CIPHER_SUITE_GCMP_256:
18639 encryptionType = eCSR_ENCRYPT_TYPE_AES_GCMP_256;
18640 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018641 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018642 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018643 return -EOPNOTSUPP;
18644 }
18645 }
18646
Jeff Johnson20227a92018-03-13 09:41:05 -070018647 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018648 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018649 hdd_debug("setting unicast cipher type to %d", encryptionType);
Jeff Johnsond377dce2017-10-04 10:32:42 -070018650 sta_ctx->conn_info.ucEncryptionType = encryptionType;
Jeff Johnson20227a92018-03-13 09:41:05 -070018651 roam_profile->EncryptionType.numEntries = 1;
18652 roam_profile->EncryptionType.encryptionType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018653 encryptionType;
18654 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018655 hdd_debug("setting mcast cipher type to %d", encryptionType);
Jeff Johnsond377dce2017-10-04 10:32:42 -070018656 sta_ctx->conn_info.mcEncryptionType = encryptionType;
Jeff Johnson20227a92018-03-13 09:41:05 -070018657 roam_profile->mcEncryptionType.numEntries = 1;
18658 roam_profile->mcEncryptionType.encryptionType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018659 encryptionType;
18660 }
18661
18662 return 0;
18663}
18664
18665/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018666 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
Jeff Johnson20227a92018-03-13 09:41:05 -070018667 * @adapter: Pointer to adapter
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018668 * @gen_ie: Pointer to IE data
18669 * @len: length of IE data
18670 *
18671 * Return: 0 for success, non-zero for failure
18672 */
Jeff Johnson20227a92018-03-13 09:41:05 -070018673static int wlan_hdd_add_assoc_ie(struct hdd_adapter *adapter,
18674 const uint8_t *gen_ie, uint16_t len)
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018675{
Jeff Johnson20227a92018-03-13 09:41:05 -070018676 struct csr_roam_profile *roam_profile;
18677 tSirAddie *assoc_add_ie;
18678 uint16_t cur_add_ie_len;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018679
Jeff Johnson20227a92018-03-13 09:41:05 -070018680 assoc_add_ie = hdd_assoc_additional_ie(adapter);
18681 cur_add_ie_len = assoc_add_ie->length;
18682 if (SIR_MAC_MAX_ADD_IE_LENGTH < (cur_add_ie_len + len)) {
18683 hdd_err("current len %u, new ie of len %u will overflow",
18684 cur_add_ie_len, len);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018685 return -ENOMEM;
18686 }
Jeff Johnson20227a92018-03-13 09:41:05 -070018687 memcpy(assoc_add_ie->addIEdata + cur_add_ie_len, gen_ie, len);
18688 assoc_add_ie->length += len;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018689
Jeff Johnson20227a92018-03-13 09:41:05 -070018690 roam_profile = hdd_roam_profile(adapter);
18691 roam_profile->pAddIEAssoc = assoc_add_ie->addIEdata;
18692 roam_profile->nAddIEAssocLength = assoc_add_ie->length;
18693
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018694 return 0;
18695}
18696
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053018697#ifdef WLAN_FEATURE_FILS_SK
18698/**
18699 * wlan_hdd_save_hlp_ie - API to save HLP IE
18700 * @roam_profile: Pointer to roam profile
18701 * @gen_ie: IE buffer to store
18702 * @len: length of the IE buffer @gen_ie
18703 * @flush: Flush the older saved HLP if any
18704 *
18705 * Return: None
18706 */
Jeff Johnson61b5e982018-03-15 11:33:31 -070018707static void wlan_hdd_save_hlp_ie(struct csr_roam_profile *roam_profile,
Jeff Johnson20227a92018-03-13 09:41:05 -070018708 const uint8_t *gen_ie, uint16_t len,
18709 bool flush)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053018710{
18711 uint8_t *hlp_ie = roam_profile->hlp_ie;
18712
18713 if (flush) {
18714 roam_profile->hlp_ie_len = 0;
18715 if (hlp_ie) {
18716 qdf_mem_free(hlp_ie);
18717 roam_profile->hlp_ie = NULL;
18718 }
18719 }
18720
18721 if ((roam_profile->hlp_ie_len +
18722 len) > FILS_MAX_HLP_DATA_LEN) {
18723 hdd_err("HLP len exceeds: hlp_ie_len %d len %d",
18724 roam_profile->hlp_ie_len, len);
18725 return;
18726 }
18727
18728 if (!roam_profile->hlp_ie) {
18729 roam_profile->hlp_ie =
18730 qdf_mem_malloc(FILS_MAX_HLP_DATA_LEN);
18731 hlp_ie = roam_profile->hlp_ie;
18732 if (!hlp_ie) {
18733 hdd_err("HLP IE mem alloc fails");
18734 return;
18735 }
18736 }
18737
18738 qdf_mem_copy(hlp_ie + roam_profile->hlp_ie_len, gen_ie, len);
18739 roam_profile->hlp_ie_len += len;
18740}
18741#else
Jeff Johnson61b5e982018-03-15 11:33:31 -070018742static inline void wlan_hdd_save_hlp_ie(struct csr_roam_profile *roam_profile,
Jeff Johnson20227a92018-03-13 09:41:05 -070018743 const uint8_t *gen_ie, uint16_t len,
18744 bool flush)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053018745{}
18746#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018747/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018748 * wlan_hdd_cfg80211_set_ie() - set IEs
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018749 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018750 * @ie: Pointer ot ie
18751 * @ie: IE length
18752 *
18753 * Return: 0 for success, non-zero for failure
18754 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018755static int wlan_hdd_cfg80211_set_ie(struct hdd_adapter *adapter,
Jeff Johnson2a722002017-09-30 20:02:35 -070018756 const uint8_t *ie,
18757 size_t ie_len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018758{
Jeff Johnson20227a92018-03-13 09:41:05 -070018759 struct csr_roam_profile *roam_profile;
18760 tSirAddie *assoc_add_ie;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018761 const uint8_t *genie = ie;
18762 uint16_t remLen = ie_len;
18763#ifdef FEATURE_WLAN_WAPI
18764 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
tinlin8a44b642018-04-25 13:56:06 +080018765 uint8_t *tmp;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018766 uint16_t akmsuiteCount;
tinlin8a44b642018-04-25 13:56:06 +080018767 uint32_t *akmlist;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018768#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018769 int status;
Jeff Johnson20227a92018-03-13 09:41:05 -070018770 uint8_t *security_ie;
18771
18772 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018773
18774 /* clear previous assocAddIE */
Jeff Johnson20227a92018-03-13 09:41:05 -070018775 assoc_add_ie = hdd_assoc_additional_ie(adapter);
18776 assoc_add_ie->length = 0;
18777 roam_profile->bWPSAssociation = false;
18778 roam_profile->bOSENAssociation = false;
18779 security_ie = hdd_security_ie(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018780
18781 while (remLen >= 2) {
18782 uint16_t eLen = 0;
18783 uint8_t elementId;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070018784
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018785 elementId = *genie++;
18786 eLen = *genie++;
18787 remLen -= 2;
18788
Nachiket Kukade4bea8b42017-06-13 11:53:19 +053018789 /* Sanity check on eLen */
18790 if (eLen > remLen) {
18791 hdd_err("%s: Invalid IE length[%d] for IE[0x%X]",
18792 __func__, eLen, elementId);
18793 QDF_ASSERT(0);
18794 return -EINVAL;
18795 }
18796
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018797 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018798
18799 switch (elementId) {
18800 case DOT11F_EID_WPA:
18801 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 -070018802 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018803 return -EINVAL;
18804 } else if (0 ==
18805 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
Jeff Johnson20227a92018-03-13 09:41:05 -070018806 uint16_t curAddIELen = assoc_add_ie->length;
18807
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018808 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018809
18810 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070018811 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018812 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018813 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018814 return -ENOMEM;
18815 }
18816 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
Jeff Johnson20227a92018-03-13 09:41:05 -070018817 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018818 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070018819 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018820
Jeff Johnson20227a92018-03-13 09:41:05 -070018821 roam_profile->bWPSAssociation = true;
18822 roam_profile->pAddIEAssoc =
18823 assoc_add_ie->addIEdata;
18824 roam_profile->nAddIEAssocLength =
18825 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018826 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Nachiket Kukade2f6509f2017-06-13 17:45:46 +053018827 if (eLen > (MAX_WPA_RSN_IE_LEN - 2)) {
18828 hdd_err("%s: Invalid WPA IE length[%d]",
18829 __func__, eLen);
18830 QDF_ASSERT(0);
18831 return -EINVAL;
18832 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018833 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070018834 memset(security_ie, 0, MAX_WPA_RSN_IE_LEN);
18835 memcpy(security_ie, genie - 2, (eLen + 2));
18836 roam_profile->pWPAReqIE = security_ie;
18837 roam_profile->nWPAReqIELength = eLen + 2; /* ie_len; */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018838 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
18839 P2P_OUI_TYPE_SIZE))) {
18840 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070018841 assoc_add_ie->length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018842 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018843
18844 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070018845 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018846 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018847 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018848 return -ENOMEM;
18849 }
18850 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
Jeff Johnson20227a92018-03-13 09:41:05 -070018851 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018852 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070018853 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018854
Jeff Johnson20227a92018-03-13 09:41:05 -070018855 roam_profile->pAddIEAssoc =
18856 assoc_add_ie->addIEdata;
18857 roam_profile->nAddIEAssocLength =
18858 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018859 }
18860#ifdef WLAN_FEATURE_WFD
18861 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
18862 WFD_OUI_TYPE_SIZE)) &&
18863 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080018864 (QDF_P2P_CLIENT_MODE ==
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018865 adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018866 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070018867 assoc_add_ie->length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018868 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018869
18870 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070018871 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018872 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018873 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018874 return -ENOMEM;
18875 }
18876 /* WFD IE is saved to Additional IE ; it should
18877 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080018878 * WFD IE
18879 */
Jeff Johnson20227a92018-03-13 09:41:05 -070018880 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018881 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070018882 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018883
Jeff Johnson20227a92018-03-13 09:41:05 -070018884 roam_profile->pAddIEAssoc =
18885 assoc_add_ie->addIEdata;
18886 roam_profile->nAddIEAssocLength =
18887 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018888 }
18889#endif
18890 /* Appending HS 2.0 Indication Element in Assiciation Request */
18891 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
18892 HS20_OUI_TYPE_SIZE))) {
18893 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070018894 assoc_add_ie->length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018895 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018896
18897 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070018898 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018899 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018900 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018901 return -ENOMEM;
18902 }
Jeff Johnson20227a92018-03-13 09:41:05 -070018903 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018904 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070018905 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018906
Jeff Johnson20227a92018-03-13 09:41:05 -070018907 roam_profile->pAddIEAssoc =
18908 assoc_add_ie->addIEdata;
18909 roam_profile->nAddIEAssocLength =
18910 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018911 }
18912 /* Appending OSEN Information Element in Assiciation Request */
18913 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
18914 OSEN_OUI_TYPE_SIZE))) {
18915 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070018916 assoc_add_ie->length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018917 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018918
18919 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070018920 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018921 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018922 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018923 return -ENOMEM;
18924 }
Jeff Johnson20227a92018-03-13 09:41:05 -070018925 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018926 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070018927 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018928
Jeff Johnson20227a92018-03-13 09:41:05 -070018929 roam_profile->bOSENAssociation = true;
18930 roam_profile->pAddIEAssoc =
18931 assoc_add_ie->addIEdata;
18932 roam_profile->nAddIEAssocLength =
18933 assoc_add_ie->length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018934 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
18935 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018936 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070018937 status = wlan_hdd_add_assoc_ie(adapter,
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018938 genie - 2, eLen + 2);
18939 if (status)
18940 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018941 } else {
18942 uint16_t add_ie_len =
Jeff Johnson20227a92018-03-13 09:41:05 -070018943 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018944
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018945 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018946
18947 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070018948 (assoc_add_ie->length + eLen)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018949 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018950 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018951 return -ENOMEM;
18952 }
18953
Jeff Johnson20227a92018-03-13 09:41:05 -070018954 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018955 add_ie_len, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070018956 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018957
Jeff Johnson20227a92018-03-13 09:41:05 -070018958 roam_profile->pAddIEAssoc =
18959 assoc_add_ie->addIEdata;
18960 roam_profile->nAddIEAssocLength =
18961 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018962 }
18963 break;
18964 case DOT11F_EID_RSN:
tinlin8a44b642018-04-25 13:56:06 +080018965 if (eLen > DOT11F_IE_RSN_MAX_LEN) {
Vignesh Viswanathan96e0e702017-12-05 19:42:46 +053018966 hdd_err("%s: Invalid WPA RSN IE length[%d]",
tinlin8a44b642018-04-25 13:56:06 +080018967 __func__, eLen);
Vignesh Viswanathan96e0e702017-12-05 19:42:46 +053018968 return -EINVAL;
18969 }
Jeff Johnson20227a92018-03-13 09:41:05 -070018970 memset(security_ie, 0, MAX_WPA_RSN_IE_LEN);
18971 memcpy(security_ie, genie - 2, (eLen + 2));
18972 roam_profile->pRSNReqIE = security_ie;
18973 roam_profile->nRSNReqIELength = eLen + 2; /* ie_len; */
tinlin8a44b642018-04-25 13:56:06 +080018974 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018975 break;
18976 /*
18977 * Appending Extended Capabilities with Interworking bit set
18978 * in Assoc Req.
18979 *
18980 * In assoc req this EXT Cap will only be taken into account if
18981 * interworkingService bit is set to 1. Currently
18982 * driver is only interested in interworkingService capability
18983 * from supplicant. If in future any other EXT Cap info is
18984 * required from supplicat, it needs to be handled while
18985 * sending Assoc Req in LIM.
18986 */
18987 case DOT11F_EID_EXTCAP:
18988 {
18989 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070018990 assoc_add_ie->length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018991 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018992
18993 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070018994 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018995 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018996 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018997 return -ENOMEM;
18998 }
Jeff Johnson20227a92018-03-13 09:41:05 -070018999 memcpy(assoc_add_ie->addIEdata + curAddIELen, genie - 2, eLen + 2);
19000 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019001
Jeff Johnson20227a92018-03-13 09:41:05 -070019002 roam_profile->pAddIEAssoc = assoc_add_ie->addIEdata;
19003 roam_profile->nAddIEAssocLength = assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019004 break;
19005 }
19006#ifdef FEATURE_WLAN_WAPI
19007 case WLAN_EID_WAPI:
19008 /* Setting WAPI Mode to ON=1 */
tinlin8a44b642018-04-25 13:56:06 +080019009 adapter->wapi_info.wapi_mode = 1;
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070019010 hdd_debug("WAPI MODE IS %u", adapter->wapi_info.wapi_mode);
tinlin8a44b642018-04-25 13:56:06 +080019011 tmp = (uint8_t *)ie;
19012 tmp = tmp + 4; /* Skip element Id and Len, Version */
19013 /* Get the number of AKM suite */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019014 akmsuiteCount = WPA_GET_LE16(tmp);
tinlin8a44b642018-04-25 13:56:06 +080019015 /* Skip the number of AKM suite */
19016 tmp = tmp + 2;
19017 /* AKM suite list, each OUI contains 4 bytes */
19018 akmlist = (uint32_t *)(tmp);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019019 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
tinlin8a44b642018-04-25 13:56:06 +080019020 memcpy(akmsuite, akmlist, akmsuiteCount);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019021 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019022 hdd_err("Invalid akmSuite count: %u",
19023 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053019024 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019025 return -EINVAL;
19026 }
19027
19028 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019029 hdd_debug("WAPI AUTH MODE SET TO PSK");
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070019030 adapter->wapi_info.wapi_auth_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019031 WAPI_AUTH_MODE_PSK;
19032 }
19033 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019034 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070019035 adapter->wapi_info.wapi_auth_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019036 WAPI_AUTH_MODE_CERT;
19037 }
19038 break;
19039#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053019040 case DOT11F_EID_SUPPOPERATINGCLASSES:
19041 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019042 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019043 status = wlan_hdd_add_assoc_ie(adapter,
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053019044 genie - 2, eLen + 2);
19045 if (status)
19046 return status;
19047 break;
19048 }
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053019049 case SIR_MAC_REQUEST_EID_MAX:
19050 {
19051 if (genie[0] == SIR_FILS_HLP_EXT_EID) {
19052 hdd_debug("Set HLP EXT IE(len %d)",
19053 eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019054 wlan_hdd_save_hlp_ie(roam_profile,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019055 genie - 2, eLen + 2,
19056 true);
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053019057 status = wlan_hdd_add_assoc_ie(
Jeff Johnson20227a92018-03-13 09:41:05 -070019058 adapter, genie - 2,
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053019059 eLen + 2);
19060 if (status)
19061 return status;
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053019062 } else if (genie[0] ==
19063 SIR_DH_PARAMETER_ELEMENT_EXT_EID) {
19064 hdd_debug("Set DH EXT IE(len %d)",
19065 eLen + 2);
19066 status = wlan_hdd_add_assoc_ie(
Jeff Johnson20227a92018-03-13 09:41:05 -070019067 adapter, genie - 2,
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053019068 eLen + 2);
19069 if (status)
19070 return status;
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053019071 } else {
19072 hdd_err("UNKNOWN EID: %X", genie[0]);
19073 }
19074 break;
19075 }
19076 case DOT11F_EID_FRAGMENT_IE:
19077 {
19078 hdd_debug("Set Fragment IE(len %d)", eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070019079 wlan_hdd_save_hlp_ie(roam_profile,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053019080 genie - 2, eLen + 2,
19081 false);
Jeff Johnson20227a92018-03-13 09:41:05 -070019082 status = wlan_hdd_add_assoc_ie(adapter,
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053019083 genie - 2, eLen + 2);
19084 if (status)
19085 return status;
19086 break;
19087 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019088 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019089 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080019090 /* when Unknown IE is received we break
19091 * and continue to the next IE in the buffer
19092 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019093 break;
19094 }
19095 genie += eLen;
19096 remLen -= eLen;
19097 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019098 return 0;
19099}
19100
19101/**
19102 * hdd_is_wpaie_present() - check for WPA ie
19103 * @ie: Pointer to ie
19104 * @ie_len: Ie length
19105 *
19106 * Parse the received IE to find the WPA IE
19107 *
19108 * Return: true if wpa ie is found else false
19109 */
19110static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
19111{
19112 uint8_t eLen = 0;
19113 uint16_t remLen = ie_len;
19114 uint8_t elementId = 0;
19115
19116 while (remLen >= 2) {
19117 elementId = *ie++;
19118 eLen = *ie++;
19119 remLen -= 2;
19120 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019121 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019122 return false;
19123 }
19124 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
19125 /* OUI - 0x00 0X50 0XF2
19126 * WPA Information Element - 0x01
19127 * WPA version - 0x01
19128 */
19129 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
19130 return true;
19131 }
19132 ie += eLen;
19133 remLen -= eLen;
19134 }
19135 return false;
19136}
19137
19138/**
19139 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019140 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019141 * @req: Pointer to security parameters
19142 *
19143 * Return: 0 for success, non-zero for failure
19144 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019145static int wlan_hdd_cfg80211_set_privacy(struct hdd_adapter *adapter,
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070019146 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019147{
19148 int status = 0;
Jeff Johnsonce4a8342017-10-14 13:12:22 -070019149 struct hdd_station_ctx *sta_ctx;
Jeff Johnson20227a92018-03-13 09:41:05 -070019150 struct csr_roam_profile *roam_profile;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070019151
Dustin Brown491d54b2018-03-14 12:39:11 -070019152 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019153
Jeff Johnsonce4a8342017-10-14 13:12:22 -070019154 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
19155 sta_ctx->wpa_versions = req->crypto.wpa_versions;
19156 hdd_debug("set wpa version to %d", sta_ctx->wpa_versions);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019157
Jeff Johnson20227a92018-03-13 09:41:05 -070019158 roam_profile = hdd_roam_profile(adapter);
19159
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019160 /*set authentication type */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019161 status = wlan_hdd_cfg80211_set_auth_type(adapter, req->auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019162
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070019163 if (wlan_hdd_is_conn_type_fils(req)) {
19164 status = wlan_hdd_cfg80211_set_fils_config(adapter, req);
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053019165
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070019166 if (0 > status) {
19167 hdd_err("Failed to set fils config");
19168 return status;
19169 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019170 }
19171
19172 /*set key mgmt type */
19173 if (req->crypto.n_akm_suites) {
19174 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019175 wlan_hdd_set_akm_suite(adapter, req->crypto.akm_suites[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019176 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019177 hdd_err("Failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019178 return status;
19179 }
19180 }
19181
19182 /*set pairwise cipher type */
19183 if (req->crypto.n_ciphers_pairwise) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019184 status = wlan_hdd_cfg80211_set_cipher(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019185 req->crypto.
19186 ciphers_pairwise[0],
19187 true);
19188 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019189 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019190 return status;
19191 }
19192 } else {
19193 /*Reset previous cipher suite to none */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019194 status = wlan_hdd_cfg80211_set_cipher(adapter, 0, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019195 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019196 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019197 return status;
19198 }
19199 }
19200
19201 /*set group cipher type */
19202 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019203 wlan_hdd_cfg80211_set_cipher(adapter, req->crypto.cipher_group,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019204 false);
19205
19206 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019207 hdd_err("Failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019208 return status;
19209 }
19210#ifdef WLAN_FEATURE_11W
Jeff Johnson20227a92018-03-13 09:41:05 -070019211 roam_profile->MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019212#endif
19213
19214 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
19215 if (req->ie_len) {
19216 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019217 wlan_hdd_cfg80211_set_ie(adapter, req->ie, req->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019218 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019219 hdd_err("Failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019220 return status;
19221 }
19222 }
19223
19224 /*incase of WEP set default key information */
19225 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080019226 u8 key_len = req->key_len;
19227 u8 key_idx = req->key_idx;
Jeff Johnson37ecea42018-03-18 17:54:40 -070019228 u32 cipher = req->crypto.ciphers_pairwise[0];
Jeff Johnson68755312017-02-10 11:46:55 -080019229
Jeff Johnson37ecea42018-03-18 17:54:40 -070019230 if ((WLAN_CIPHER_SUITE_WEP40 == cipher) ||
19231 (WLAN_CIPHER_SUITE_WEP104 == cipher)) {
19232 enum hdd_auth_key_mgmt key_mgmt =
19233 sta_ctx->auth_key_mgmt;
19234
19235 if (key_mgmt & HDD_AUTH_KEY_MGMT_802_1X) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019236 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019237 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080019238 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019239
Jeff Johnson68755312017-02-10 11:46:55 -080019240 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
19241 && (CSR_MAX_NUM_KEY > key_idx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019242 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson68755312017-02-10 11:46:55 -080019243 key_idx, key_len);
Jeff Johnson20227a92018-03-13 09:41:05 -070019244 qdf_mem_copy(&roam_profile->Keys.
Jeff Johnson68755312017-02-10 11:46:55 -080019245 KeyMaterial[key_idx][0],
19246 req->key, key_len);
Jeff Johnson20227a92018-03-13 09:41:05 -070019247 roam_profile->Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019248 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson20227a92018-03-13 09:41:05 -070019249 roam_profile->Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019250 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019251 }
19252 }
19253 }
19254
19255 return status;
19256}
19257
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019258int wlan_hdd_try_disconnect(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019259{
19260 unsigned long rc;
Jeff Johnsond377dce2017-10-04 10:32:42 -070019261 struct hdd_station_ctx *sta_ctx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019262 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080019263 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019264
Jeff Johnsond377dce2017-10-04 10:32:42 -070019265 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019266 hal = WLAN_HDD_GET_HAL_CTX(adapter);
19267 if (adapter->device_mode == QDF_STA_MODE) {
Jeff Johnson1b780e42017-10-31 14:11:45 -070019268 sme_indicate_disconnect_inprogress(hal, adapter->session_id);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019269 hdd_debug("Stop firmware roaming");
Jeff Johnson1b780e42017-10-31 14:11:45 -070019270 sme_stop_roaming(hal, adapter->session_id, eCsrForcedDisassoc);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080019271
Abhishek Singh533c9da2017-05-04 10:23:34 +053019272 /*
19273 * If firmware has already started roaming process, driver
19274 * needs to wait for processing of this disconnect request.
19275 *
19276 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019277 INIT_COMPLETION(adapter->roaming_comp_var);
19278 if (hdd_is_roaming_in_progress(adapter)) {
Abhishek Singh533c9da2017-05-04 10:23:34 +053019279 rc = wait_for_completion_timeout(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019280 &adapter->roaming_comp_var,
Abhishek Singh533c9da2017-05-04 10:23:34 +053019281 msecs_to_jiffies(WLAN_WAIT_TIME_STOP_ROAM));
19282 if (!rc) {
19283 hdd_err("roaming comp var timed out session Id: %d",
Jeff Johnson1b780e42017-10-31 14:11:45 -070019284 adapter->session_id);
Abhishek Singh533c9da2017-05-04 10:23:34 +053019285 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019286 if (adapter->roam_ho_fail) {
19287 INIT_COMPLETION(adapter->disconnect_comp_var);
19288 hdd_conn_set_connection_state(adapter,
Abhishek Singh533c9da2017-05-04 10:23:34 +053019289 eConnectionState_Disconnecting);
19290 }
19291 }
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080019292 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019293
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019294 if ((QDF_IBSS_MODE == adapter->device_mode) ||
Jeff Johnsond377dce2017-10-04 10:32:42 -070019295 (eConnectionState_Associated == sta_ctx->conn_info.connState) ||
19296 (eConnectionState_Connecting == sta_ctx->conn_info.connState) ||
19297 (eConnectionState_IbssConnected == sta_ctx->conn_info.connState)) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019298 hdd_conn_set_connection_state(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019299 eConnectionState_Disconnecting);
19300 /* Issue disconnect to CSR */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019301 INIT_COMPLETION(adapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019302
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019303 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -070019304 adapter->session_id,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019305 eCSR_DISCONNECT_REASON_UNSPECIFIED);
19306 /*
19307 * Wait here instead of returning directly, this will block the
19308 * next connect command and allow processing of the scan for
19309 * ssid and the previous connect command in CSR. Else we might
19310 * hit some race conditions leading to SME and HDD out of sync.
19311 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053019312 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019313 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019314 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019315 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019316 (int)status);
Jeff Johnson8380f232017-10-25 12:39:44 -070019317 sta_ctx->sta_debug_state = status;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019318 result = -EINVAL;
19319 goto disconnected;
19320 }
19321
19322 rc = wait_for_completion_timeout(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019323 &adapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019324 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053019325 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson8380f232017-10-25 12:39:44 -070019326 hdd_err("Sme disconnect event timed out session Id: %d sta_debug_state: %d",
Jeff Johnson1b780e42017-10-31 14:11:45 -070019327 adapter->session_id, sta_ctx->sta_debug_state);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019328 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019329 }
19330 } else if (eConnectionState_Disconnecting ==
Jeff Johnsond377dce2017-10-04 10:32:42 -070019331 sta_ctx->conn_info.connState) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019332 rc = wait_for_completion_timeout(&adapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019333 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019334 if (!rc) {
Jeff Johnson8380f232017-10-25 12:39:44 -070019335 hdd_err("Disconnect event timed out session Id: %d sta_debug_state: %d",
Jeff Johnson1b780e42017-10-31 14:11:45 -070019336 adapter->session_id, sta_ctx->sta_debug_state);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019337 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019338 }
19339 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019340disconnected:
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019341 hdd_conn_set_connection_state(adapter, eConnectionState_NotConnected);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019342 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019343}
19344
19345/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019346 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
19347 * @adapter: Pointer to the HDD adapter
19348 * @req: Pointer to the structure cfg_connect_params receieved from user space
19349 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053019350 * This function will start reassociation if prev_bssid is set and bssid/
19351 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019352 *
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053019353 * Return: 0 if connect was for ReAssociation, non-zero error code otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019354 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053019355#if defined(CFG80211_CONNECT_PREV_BSSID) || \
19356 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053019357static int wlan_hdd_reassoc_bssid_hint(struct hdd_adapter *adapter,
19358 struct cfg80211_connect_params *req)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019359{
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053019360 int status = -EINVAL;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053019361 const uint8_t *bssid = NULL;
19362 uint16_t channel = 0;
Jeff Johnson731bc322017-10-14 19:53:44 -070019363 struct hdd_station_ctx *sta_ctx;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053019364
19365 if (req->bssid)
19366 bssid = req->bssid;
19367 else if (req->bssid_hint)
19368 bssid = req->bssid_hint;
19369
19370 if (req->channel)
19371 channel = req->channel->hw_value;
19372 else if (req->channel_hint)
19373 channel = req->channel_hint->hw_value;
19374
19375 if (bssid && channel && req->prev_bssid) {
Dustin Brownbacc48f2018-03-14 14:48:44 -070019376 hdd_debug("REASSOC Attempt on channel %d to " MAC_ADDRESS_STR,
19377 channel, MAC_ADDR_ARRAY(bssid));
Arif Hussain43354e62017-05-24 11:24:25 -070019378 /*
19379 * Save BSSID in a separate variable as
Jeff Johnson5b34fce2017-10-13 13:24:51 -070019380 * roam_profile's BSSID is getting zeroed out in the
Arif Hussain43354e62017-05-24 11:24:25 -070019381 * association process. In case of join failure
19382 * we should send valid BSSID to supplicant
19383 */
Jeff Johnson731bc322017-10-14 19:53:44 -070019384 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
19385 qdf_mem_copy(sta_ctx->requested_bssid.bytes, bssid,
Arif Hussain43354e62017-05-24 11:24:25 -070019386 QDF_MAC_ADDR_SIZE);
19387
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053019388 status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019389 CONNECT_CMD_USERSPACE);
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053019390 hdd_debug("hdd_reassoc: status: %d", status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019391 }
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053019392 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019393}
19394#else
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053019395static int wlan_hdd_reassoc_bssid_hint(struct hdd_adapter *adapter,
19396 struct cfg80211_connect_params *req)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019397{
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053019398 return -ENOTSUPP;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019399}
19400#endif
19401
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019402
19403/**
19404 * wlan_hdd_check_ht20_ht40_ind() - check if Supplicant has indicated to
19405 * connect in HT20 mode
19406 * @hdd_ctx: hdd context
19407 * @adapter: Pointer to the HDD adapter
19408 * @req: Pointer to the structure cfg_connect_params receieved from user space
19409 *
19410 * This function will check if supplicant has indicated to to connect in HT20
19411 * mode. this is currently applicable only for 2.4Ghz mode only.
19412 * if feature is enabled and supplicant indicate HT20 set
19413 * force_24ghz_in_ht20 to true to force 2.4Ghz in HT20 else set it to false.
19414 *
19415 * Return: void
19416 */
19417#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
Jeff Johnson20227a92018-03-13 09:41:05 -070019418static void
19419wlan_hdd_check_ht20_ht40_ind(struct hdd_context *hdd_ctx,
19420 struct hdd_adapter *adapter,
19421 struct cfg80211_connect_params *req)
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019422{
Jeff Johnson61b5e982018-03-15 11:33:31 -070019423 struct csr_roam_profile *roam_profile;
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019424
Jeff Johnson20227a92018-03-13 09:41:05 -070019425 roam_profile = hdd_roam_profile(adapter);
19426
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019427 roam_profile->force_24ghz_in_ht20 = false;
19428
19429 if (hdd_ctx->config->override_ht20_40_24g &&
Jeff Johnson20227a92018-03-13 09:41:05 -070019430 !(req->ht_capa.cap_info & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019431 roam_profile->force_24ghz_in_ht20 = true;
19432
19433 hdd_debug("req->ht_capa.cap_info %x override_ht20_40_24g %d",
19434 req->ht_capa.cap_info,
19435 hdd_ctx->config->override_ht20_40_24g);
19436}
19437#else
Jeff Johnson20227a92018-03-13 09:41:05 -070019438static inline void
19439wlan_hdd_check_ht20_ht40_ind(struct hdd_context *hdd_ctx,
19440 struct hdd_adapter *adapter,
19441 struct cfg80211_connect_params *req)
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019442{
Jeff Johnson61b5e982018-03-15 11:33:31 -070019443 struct csr_roam_profile *roam_profile;
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019444
Jeff Johnson20227a92018-03-13 09:41:05 -070019445 roam_profile = hdd_roam_profile(adapter);
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019446
19447 roam_profile->force_24ghz_in_ht20 = false;
19448}
19449#endif
19450
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019451/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019452 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
19453 * @wiphy: Pointer to wiphy
19454 * @dev: Pointer to network device
19455 * @req: Pointer to cfg80211 connect request
19456 *
19457 * This function is used to start the association process
19458 *
19459 * Return: 0 for success, non-zero for failure
19460 */
19461static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
19462 struct net_device *ndev,
19463 struct cfg80211_connect_params *req)
19464{
19465 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053019466 u16 channel;
Arif Hussainee677012017-01-26 17:50:13 -080019467 const u8 *bssid = NULL;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053019468#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
19469 const u8 *bssid_hint = req->bssid_hint;
19470#else
19471 const u8 *bssid_hint = NULL;
19472#endif
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019473 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070019474 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019475
Dustin Brown491d54b2018-03-14 12:39:11 -070019476 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019477
Anurag Chouhan6d760662016-02-20 16:05:43 +053019478 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019479 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019480 return -EINVAL;
19481 }
19482
Jeff Johnson1b780e42017-10-31 14:11:45 -070019483 if (wlan_hdd_validate_session_id(adapter->session_id)) {
19484 hdd_err("invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053019485 return -EINVAL;
19486 }
19487
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053019488 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019489 TRACE_CODE_HDD_CFG80211_CONNECT,
Jeff Johnson1b780e42017-10-31 14:11:45 -070019490 adapter->session_id, adapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019491 hdd_debug("Device_mode %s(%d)",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019492 hdd_device_mode_to_string(adapter->device_mode),
19493 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019494
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019495 if (adapter->device_mode != QDF_STA_MODE &&
19496 adapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019497 hdd_err("Device_mode %s(%d) is not supported",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019498 hdd_device_mode_to_string(adapter->device_mode),
19499 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019500 return -EINVAL;
19501 }
19502
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019503 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070019504 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019505 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019506 return -EINVAL;
19507 }
19508
Jeff Johnsonb8944722017-09-03 09:03:19 -070019509 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053019510 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019511 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019512
Arif Hussainee677012017-01-26 17:50:13 -080019513 if (req->bssid)
19514 bssid = req->bssid;
19515 else if (bssid_hint)
19516 bssid = bssid_hint;
19517
Jeff Johnsonb8944722017-09-03 09:03:19 -070019518 if (bssid && hdd_get_adapter_by_macaddr(hdd_ctx, (uint8_t *)bssid)) {
Arif Hussain7631afa2017-02-08 14:35:00 -080019519 hdd_err("adapter exist with same mac address " MAC_ADDRESS_STR,
19520 MAC_ADDR_ARRAY(bssid));
19521 return -EINVAL;
Arif Hussainee677012017-01-26 17:50:13 -080019522 }
19523
Vignesh Viswanathan75af0a62018-05-08 17:08:54 +053019524 /*
19525 * Check if this is reassoc to same bssid, if reassoc is success, return
19526 */
19527 status = wlan_hdd_reassoc_bssid_hint(adapter, req);
19528 if (!status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019529 return status;
19530
Agrawal Ashishf156e942016-08-04 14:54:47 +053019531 /* Try disconnecting if already in connected state */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019532 status = wlan_hdd_try_disconnect(adapter);
Agrawal Ashishf156e942016-08-04 14:54:47 +053019533 if (0 > status) {
19534 hdd_err("Failed to disconnect the existing connection");
19535 return -EALREADY;
19536 }
19537
19538 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019539 if (req->channel) {
Min Liuab6ed4f2018-01-09 13:13:57 +080019540 bool ok = false;
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053019541
19542 if (req->channel->hw_value && policy_mgr_is_chan_ok_for_dnbs(
Jeff Johnsonb8944722017-09-03 09:03:19 -070019543 hdd_ctx->hdd_psoc,
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053019544 req->channel->hw_value,
19545 &ok)) {
19546 hdd_warn("Unable to get channel:%d eligibility for DNBS",
19547 req->channel->hw_value);
19548 return -EINVAL;
19549 }
19550 /**
19551 * Send connection timedout, so that Android framework does not
19552 * blacklist us.
19553 */
19554 if (!ok) {
19555 struct ieee80211_channel *chan =
Dustin Brown2eb1e452017-08-15 12:40:34 -070019556 ieee80211_get_channel(wiphy,
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053019557 wlan_chan_to_freq(req->channel->hw_value));
19558 struct cfg80211_bss *bss;
19559
19560 hdd_warn("Channel:%d not OK for DNBS",
19561 req->channel->hw_value);
19562 if (chan) {
19563 bss = hdd_cfg80211_get_bss(wiphy,
19564 chan,
19565 req->bssid, req->ssid,
19566 req->ssid_len);
19567 if (bss) {
19568 cfg80211_assoc_timeout(ndev, bss);
19569 return -ETIMEDOUT;
19570 }
19571 }
19572 return -EINVAL;
19573 }
19574
Jeff Johnsonb8944722017-09-03 09:03:19 -070019575 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc,
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080019576 policy_mgr_convert_device_mode_to_qdf_type(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019577 adapter->device_mode),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019578 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019579 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019580 return -ECONNREFUSED;
19581 }
19582 } else {
Jeff Johnsonb8944722017-09-03 09:03:19 -070019583 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc,
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080019584 policy_mgr_convert_device_mode_to_qdf_type(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019585 adapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019586 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019587 return -ECONNREFUSED;
19588 }
19589 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019590
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019591 /*initialise security parameters */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019592 status = wlan_hdd_cfg80211_set_privacy(adapter, req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019593
19594 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019595 hdd_err("Failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019596 return status;
19597 }
19598
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053019599 if (req->channel)
19600 channel = req->channel->hw_value;
19601 else
19602 channel = 0;
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019603
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019604 wlan_hdd_check_ht20_ht40_ind(hdd_ctx, adapter, req);
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019605
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019606 status = wlan_hdd_cfg80211_connect_start(adapter, req->ssid,
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053019607 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070019608 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019609 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019610 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019611 return status;
19612 }
Dustin Browne74003f2018-03-14 12:51:58 -070019613 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019614 return status;
19615}
19616
19617/**
19618 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
19619 * @wiphy: Pointer to wiphy
19620 * @dev: Pointer to network device
19621 * @req: Pointer to cfg80211 connect request
19622 *
19623 * Return: 0 for success, non-zero for failure
19624 */
19625static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
19626 struct net_device *ndev,
19627 struct cfg80211_connect_params *req)
19628{
19629 int ret;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070019630
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019631 cds_ssr_protect(__func__);
19632 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
19633 cds_ssr_unprotect(__func__);
19634
19635 return ret;
19636}
19637
Himanshu Agarwal6c3607a2018-01-12 12:04:19 +053019638int wlan_hdd_disconnect(struct hdd_adapter *adapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019639{
19640 int status, result = 0;
19641 unsigned long rc;
Jeff Johnsond377dce2017-10-04 10:32:42 -070019642 struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019643 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053019644 eConnectionState prev_conn_state;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019645 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
Abhishek Singhe9706cc2017-10-12 17:25:06 +053019646 uint32_t wait_time = WLAN_WAIT_TIME_DISCONNECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019647
Dustin Brown491d54b2018-03-14 12:39:11 -070019648 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053019649
Jeff Johnsonb8944722017-09-03 09:03:19 -070019650 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019651
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053019652 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019653 return status;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019654 if (adapter->device_mode == QDF_STA_MODE) {
Jeff Johnson1b780e42017-10-31 14:11:45 -070019655 sme_indicate_disconnect_inprogress(hal, adapter->session_id);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019656 hdd_debug("Stop firmware roaming");
Jeff Johnson1b780e42017-10-31 14:11:45 -070019657 status = sme_stop_roaming(hal, adapter->session_id,
Abhishek Singh533c9da2017-05-04 10:23:34 +053019658 eCsrForcedDisassoc);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080019659 /*
Abhishek Singh533c9da2017-05-04 10:23:34 +053019660 * If firmware has already started roaming process, driver
19661 * needs to wait for processing of this disconnect request.
19662 *
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080019663 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019664 INIT_COMPLETION(adapter->roaming_comp_var);
19665 if (hdd_is_roaming_in_progress(adapter)) {
Abhishek Singh533c9da2017-05-04 10:23:34 +053019666 rc = wait_for_completion_timeout(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019667 &adapter->roaming_comp_var,
Abhishek Singh533c9da2017-05-04 10:23:34 +053019668 msecs_to_jiffies(WLAN_WAIT_TIME_STOP_ROAM));
19669 if (!rc) {
19670 hdd_err("roaming comp var timed out session Id: %d",
Jeff Johnson1b780e42017-10-31 14:11:45 -070019671 adapter->session_id);
Abhishek Singh533c9da2017-05-04 10:23:34 +053019672 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019673 if (adapter->roam_ho_fail) {
19674 INIT_COMPLETION(adapter->disconnect_comp_var);
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -070019675 hdd_debug("Disabling queues");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019676 wlan_hdd_netif_queue_control(adapter,
Abhishek Singh533c9da2017-05-04 10:23:34 +053019677 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
19678 WLAN_CONTROL_PATH);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019679 hdd_conn_set_connection_state(adapter,
Abhishek Singh533c9da2017-05-04 10:23:34 +053019680 eConnectionState_Disconnecting);
19681 goto wait_for_disconnect;
19682 }
19683 }
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080019684 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019685
Jeff Johnsond377dce2017-10-04 10:32:42 -070019686 prev_conn_state = sta_ctx->conn_info.connState;
Srinivas Girigowda6598eea2017-07-06 19:26:19 -070019687 /*stop tx queues */
19688 hdd_info("Disabling queues");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019689 wlan_hdd_netif_queue_control(adapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053019690 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019691 hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019692 hdd_conn_set_connection_state(adapter, eConnectionState_Disconnecting);
Varun Reddy Yeturu9e0032c2017-07-12 18:39:59 -070019693
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019694 INIT_COMPLETION(adapter->disconnect_comp_var);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019695
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080019696 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019697
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019698 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -070019699 adapter->session_id, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053019700 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
19701 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019702 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053019703 result = 0;
Abhishek Singhe9706cc2017-10-12 17:25:06 +053019704 /*
19705 * Wait here instead of returning directly. This will block the
19706 * next connect command and allow processing of the disconnect
19707 * in SME else we might hit some race conditions leading to SME
19708 * and HDD out of sync. As disconnect is already in progress,
19709 * wait here for 1 sec instead of 5 sec.
19710 */
19711 wait_time = WLAN_WAIT_DISCONNECT_ALREADY_IN_PROGRESS;
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053019712 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
19713 /*
19714 * Wait here instead of returning directly, this will block the
19715 * next connect command and allow processing of the scan for
19716 * ssid and the previous connect command in CSR. Else we might
19717 * hit some race conditions leading to SME and HDD out of sync.
19718 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019719 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019720 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019721 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Jeff Johnson8380f232017-10-25 12:39:44 -070019722 sta_ctx->sta_debug_state = status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019723 result = -EINVAL;
19724 goto disconnected;
19725 }
Abhishek Singh533c9da2017-05-04 10:23:34 +053019726wait_for_disconnect:
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019727 rc = wait_for_completion_timeout(&adapter->disconnect_comp_var,
Abhishek Singhe9706cc2017-10-12 17:25:06 +053019728 msecs_to_jiffies(wait_time));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019729
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053019730 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019731 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019732 result = -ETIMEDOUT;
19733 }
19734disconnected:
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019735 hdd_conn_set_connection_state(adapter, eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019736#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
19737 /* Sending disconnect event to userspace for kernel version < 3.11
19738 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
19739 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019740 hdd_debug("Send disconnected event to userspace");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019741 wlan_hdd_cfg80211_indicate_disconnect(adapter->dev, true,
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053019742 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019743#endif
19744
19745 return result;
19746}
19747
19748/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080019749 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
19750 * @reason: ieee80211 reason code.
19751 *
19752 * This utility function helps log string conversion of reason code.
19753 *
19754 * Return: string conversion of reason code, if match found;
19755 * "Unknown" otherwise.
19756 */
19757static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
19758{
19759 switch (reason) {
19760 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
19761 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
19762 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
19763 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
19764 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
19765 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
19766 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
19767 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
19768 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
19769 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
19770 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
19771 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
19772 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
19773 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
19774 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
19775 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
19776 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
19777 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
19778 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
19779 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
19780 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
19781 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
19782 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
19783 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
19784 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
19785 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
19786 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
19787 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
19788 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
19789 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
19790 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
19791 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
19792 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
19793 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
19794 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
19795 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
19796 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
19797 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
19798 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
19799 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
19800 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
19801 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
19802 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
19803 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
19804 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
19805 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
19806 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
19807 default:
19808 return "Unknown";
19809 }
19810}
19811
19812/**
Srinivas Girigowda44cff5c2018-04-16 15:49:30 -070019813 * hdd_print_netdev_txq_status() - print netdev tx queue status
19814 * @dev: Pointer to network device
19815 *
19816 * This function is used to print netdev tx queue status
19817 *
19818 * Return: none
19819 */
19820static void hdd_print_netdev_txq_status(struct net_device *dev)
19821{
19822 unsigned int i;
19823
19824 if (!dev)
19825 return;
19826
19827 for (i = 0; i < dev->num_tx_queues; i++) {
19828 struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
19829
19830 hdd_info("netdev tx queue[%u] state: 0x%lx", i, txq->state);
19831 }
19832}
19833
19834/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019835 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
19836 * @wiphy: Pointer to wiphy
19837 * @dev: Pointer to network device
19838 * @reason: Disconnect reason code
19839 *
19840 * This function is used to issue a disconnect request to SME
19841 *
19842 * Return: 0 for success, non-zero for failure
19843 */
19844static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
19845 struct net_device *dev, u16 reason)
19846{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019847 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019848 int status;
Jeff Johnsond377dce2017-10-04 10:32:42 -070019849 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019850 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
19851 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019852
Dustin Brown491d54b2018-03-14 12:39:11 -070019853 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019854
Anurag Chouhan6d760662016-02-20 16:05:43 +053019855 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019856 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019857 return -EINVAL;
19858 }
19859
Jeff Johnson1b780e42017-10-31 14:11:45 -070019860 if (wlan_hdd_validate_session_id(adapter->session_id)) {
19861 hdd_err("Invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053019862 return -EINVAL;
19863 }
19864
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053019865 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019866 TRACE_CODE_HDD_CFG80211_DISCONNECT,
Jeff Johnson1b780e42017-10-31 14:11:45 -070019867 adapter->session_id, reason));
Srinivas Girigowda44cff5c2018-04-16 15:49:30 -070019868 hdd_print_netdev_txq_status(dev);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019869 hdd_debug("Device_mode %s(%d) reason code(%d)",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019870 hdd_device_mode_to_string(adapter->device_mode),
19871 adapter->device_mode, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019872
Jeff Johnsonb8944722017-09-03 09:03:19 -070019873 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019874
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053019875 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019876 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019877
Alok Kumarb64650c2018-03-23 17:05:11 +053019878 qdf_mutex_acquire(&adapter->disconnection_status_lock);
19879 if (adapter->disconnection_in_progress) {
19880 qdf_mutex_release(&adapter->disconnection_status_lock);
19881 hdd_debug("Disconnect is already in progress");
19882 return 0;
19883 }
19884 adapter->disconnection_in_progress = true;
19885 qdf_mutex_release(&adapter->disconnection_status_lock);
19886
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019887 /* Issue disconnect request to SME, if station is in connected state */
Jeff Johnsond377dce2017-10-04 10:32:42 -070019888 if ((sta_ctx->conn_info.connState == eConnectionState_Associated) ||
19889 (sta_ctx->conn_info.connState == eConnectionState_Connecting)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019890 eCsrRoamDisconnectReason reasonCode =
19891 eCSR_DISCONNECT_REASON_UNSPECIFIED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019892
19893 switch (reason) {
19894 case WLAN_REASON_MIC_FAILURE:
19895 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
19896 break;
19897
19898 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
19899 case WLAN_REASON_DISASSOC_AP_BUSY:
19900 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
19901 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
19902 break;
19903
19904 case WLAN_REASON_PREV_AUTH_NOT_VALID:
19905 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
19906 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
19907 break;
19908
19909 case WLAN_REASON_DEAUTH_LEAVING:
19910 reasonCode =
Jeff Johnsonb8944722017-09-03 09:03:19 -070019911 hdd_ctx->config->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019912 gEnableDeauthToDisassocMap ?
19913 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
19914 eCSR_DISCONNECT_REASON_DEAUTH;
Mohit Khannaceb97782017-04-05 16:27:08 -070019915 qdf_dp_trace_dump_all(
19916 WLAN_DEAUTH_DPTRACE_DUMP_COUNT,
19917 QDF_TRACE_DEFAULT_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019918 break;
19919 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
19920 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
19921 break;
19922 default:
19923 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
19924 break;
19925 }
Sandeep Puligilla5f86d992017-10-29 14:58:53 -070019926 if (ucfg_scan_get_vdev_status(adapter->hdd_vdev) !=
19927 SCAN_NOT_IN_PROGRESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019928 hdd_debug("Disconnect is in progress, Aborting Scan");
Jeff Johnsonb8944722017-09-03 09:03:19 -070019929 wlan_abort_scan(hdd_ctx->hdd_pdev, INVAL_PDEV_ID,
Jeff Johnson1b780e42017-10-31 14:11:45 -070019930 adapter->session_id, INVALID_SCAN_ID, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019931 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019932 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019933 /* First clean up the tdls peers if any */
Jeff Johnson1b780e42017-10-31 14:11:45 -070019934 hdd_notify_sta_disconnect(adapter->session_id,
Kabilan Kannanb6153b12017-07-13 17:54:02 -070019935 false, true, adapter->hdd_vdev);
19936
Srinivas Girigowdaf620d482017-04-06 19:03:20 -070019937 hdd_info("Disconnect request from user space with reason: %d (%s) internal reason code: %d",
19938 reason, hdd_ieee80211_reason_code_to_str(reason), reasonCode);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019939 status = wlan_hdd_disconnect(adapter, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019940 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019941 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Alok Kumarb64650c2018-03-23 17:05:11 +053019942 hdd_set_disconnect_status(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019943 return -EINVAL;
19944 }
19945 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019946 hdd_err("Unexpected cfg disconnect called while in state: %d",
Jeff Johnsond377dce2017-10-04 10:32:42 -070019947 sta_ctx->conn_info.connState);
Alok Kumarb64650c2018-03-23 17:05:11 +053019948 hdd_set_disconnect_status(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019949 }
19950
19951 return status;
19952}
19953
19954/**
19955 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
19956 * @wiphy: Pointer to wiphy
19957 * @dev: Pointer to network device
19958 * @reason: Disconnect reason code
19959 *
19960 * Return: 0 for success, non-zero for failure
19961 */
19962static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
19963 struct net_device *dev, u16 reason)
19964{
19965 int ret;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070019966
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019967 cds_ssr_protect(__func__);
19968 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
19969 cds_ssr_unprotect(__func__);
19970
19971 return ret;
19972}
19973
19974/**
19975 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019976 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019977 * @param: Pointer to IBSS parameters
19978 *
19979 * This function is used to initialize the security settings in IBSS mode
19980 *
19981 * Return: 0 for success, non-zero for failure
19982 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019983static int wlan_hdd_cfg80211_set_privacy_ibss(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019984 struct cfg80211_ibss_params
19985 *params)
19986{
Naveen Rawat72475db2017-12-13 18:07:35 -080019987 uint32_t ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019988 int status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019989 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
Jeff Johnsond377dce2017-10-04 10:32:42 -070019990 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019991 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070019992 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019993
Dustin Brown491d54b2018-03-14 12:39:11 -070019994 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019995
Jeff Johnsonce4a8342017-10-14 13:12:22 -070019996 sta_ctx->wpa_versions = 0;
Jeff Johnsond377dce2017-10-04 10:32:42 -070019997 qdf_mem_zero(&sta_ctx->ibss_enc_key, sizeof(tCsrRoamSetKey));
19998 sta_ctx->ibss_enc_key_installed = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019999
20000 if (params->ie_len && (NULL != params->ie)) {
Naveen Rawat08db88f2017-09-08 15:07:48 -070020001 if (wlan_get_ie_ptr_from_eid(WLAN_EID_RSN, params->ie,
20002 params->ie_len)) {
Jeff Johnsonce4a8342017-10-14 13:12:22 -070020003 sta_ctx->wpa_versions = NL80211_WPA_VERSION_2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020004 encryptionType = eCSR_ENCRYPT_TYPE_AES;
20005 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
20006 tDot11fIEWPA dot11WPAIE;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020007 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(adapter);
Naveen Rawat08db88f2017-09-08 15:07:48 -070020008 const u8 *ie;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020009
20010 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
Naveen Rawat08db88f2017-09-08 15:07:48 -070020011 ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_WPA,
20012 params->ie, params->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020013 if (NULL != ie) {
Jeff Johnsonce4a8342017-10-14 13:12:22 -070020014 sta_ctx->wpa_versions = NL80211_WPA_VERSION_1;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080020015 /* Unpack the WPA IE
20016 * Skip past the EID byte and length byte
20017 * and four byte WiFi OUI
20018 */
Hanumanth Reddy Pothulaf6e3db32018-01-24 17:54:15 +053020019 if (ie[1] < DOT11F_IE_WPA_MIN_LEN ||
20020 ie[1] > DOT11F_IE_WPA_MAX_LEN) {
20021 hdd_err("invalid ie len:%d", ie[1]);
20022 return -EINVAL;
20023 }
Naveen Rawat72475db2017-12-13 18:07:35 -080020024 ret = dot11f_unpack_ie_wpa(
20025 (tpAniSirGlobal) halHandle,
20026 (uint8_t *)&ie[2 + 4],
20027 ie[1] - 4, &dot11WPAIE, false);
20028 if (DOT11F_FAILED(ret)) {
20029 hdd_err("unpack failed ret: 0x%x", ret);
20030 return -EINVAL;
20031 }
Selvaraj, Sridhar75afbeb2017-04-03 17:08:59 +053020032 /*
20033 * Extract the multicast cipher, the
Jeff Johnsonf3826e12017-01-12 09:49:40 -080020034 * encType for unicast cipher for
20035 * wpa-none is none
20036 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020037 encryptionType =
20038 hdd_translate_wpa_to_csr_encryption_type
20039 (dot11WPAIE.multicast_cipher);
20040 }
20041 }
20042
20043 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020044 wlan_hdd_cfg80211_set_ie(adapter, params->ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020045 params->ie_len);
20046
20047 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020048 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020049 return status;
20050 }
20051 }
20052
Jeff Johnson20227a92018-03-13 09:41:05 -070020053 roam_profile = hdd_roam_profile(adapter);
20054 roam_profile->AuthType.authType[0] =
Jeff Johnsond377dce2017-10-04 10:32:42 -070020055 sta_ctx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020056
20057 if (params->privacy) {
20058 /* Security enabled IBSS, At this time there is no information
Jeff Johnson60ed45a2018-05-06 15:28:49 -070020059 * available about the security parameters, so initialise the
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020060 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
20061 * The correct security parameters will be updated later in
20062 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
20063 * set inorder enable privacy bit in beacons
20064 */
20065
20066 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
20067 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020068 hdd_debug("encryptionType=%d", encryptionType);
Jeff Johnsond377dce2017-10-04 10:32:42 -070020069 sta_ctx->conn_info.ucEncryptionType = encryptionType;
Jeff Johnson20227a92018-03-13 09:41:05 -070020070 roam_profile->EncryptionType.numEntries = 1;
20071 roam_profile->EncryptionType.encryptionType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020072 encryptionType;
20073 return status;
20074}
20075
20076/**
20077 * __wlan_hdd_cfg80211_join_ibss() - join ibss
20078 * @wiphy: Pointer to wiphy
20079 * @dev: Pointer to network device
20080 * @param: Pointer to IBSS join parameters
20081 *
20082 * This function is used to create/join an IBSS network
20083 *
20084 * Return: 0 for success, non-zero for failure
20085 */
20086static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
20087 struct net_device *dev,
20088 struct cfg80211_ibss_params *params)
20089{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020090 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson61b5e982018-03-15 11:33:31 -070020091 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020092 int status;
Jeff Johnsond377dce2017-10-04 10:32:42 -070020093 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020094 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
20095 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053020096 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020097 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020098
Dustin Brown491d54b2018-03-14 12:39:11 -070020099 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020100
Anurag Chouhan6d760662016-02-20 16:05:43 +053020101 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020102 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020103 return -EINVAL;
20104 }
20105
Jeff Johnson1b780e42017-10-31 14:11:45 -070020106 if (wlan_hdd_validate_session_id(adapter->session_id)) {
20107 hdd_err("Invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053020108 return -EINVAL;
20109 }
20110
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053020111 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020112 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
Jeff Johnson1b780e42017-10-31 14:11:45 -070020113 adapter->session_id, adapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020114 hdd_debug("Device_mode %s(%d)",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020115 hdd_device_mode_to_string(adapter->device_mode),
20116 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020117
Jeff Johnsonb8944722017-09-03 09:03:19 -070020118 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020119
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053020120 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020121 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020122
20123 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053020124 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020125 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
20126 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020127 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020128 int indx;
20129
20130 /* Get channel number */
20131 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020132 params->
20133 chandef.
20134 chan->
20135 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020136
20137 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
20138 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020139 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020140 return -EOPNOTSUPP;
20141 }
20142
20143 for (indx = 0; indx < numChans; indx++) {
Srinivas Girigowda576b2352017-08-25 14:44:26 -070020144 if (channelNum == validChan[indx])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020145 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020146 }
20147 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020148 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020149 return -EINVAL;
20150 }
20151 }
20152
Jeff Johnsonb8944722017-09-03 09:03:19 -070020153 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc,
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080020154 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020155 hdd_err("This concurrency combination is not allowed");
20156 return -ECONNREFUSED;
20157 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020158
Jeff Johnsonb8944722017-09-03 09:03:19 -070020159 status = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070020160 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020161 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070020162
Jeff Johnsonb8944722017-09-03 09:03:19 -070020163 status = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
Jeff Johnson1b780e42017-10-31 14:11:45 -070020164 adapter->session_id, channelNum,
Tushnim Bhattacharyya3b99f4b2018-03-26 14:19:24 -070020165 POLICY_MGR_UPDATE_REASON_JOIN_IBSS);
Krunal Soni3091bcc2016-06-23 12:28:21 -070020166 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020167 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070020168 return -EINVAL;
20169 }
20170
20171 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080020172 status = policy_mgr_wait_for_connection_update(
Jeff Johnsonb8944722017-09-03 09:03:19 -070020173 hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070020174 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020175 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020176 return -EINVAL;
20177 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020178 }
20179
20180 /*Try disconnecting if already in connected state */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020181 status = wlan_hdd_try_disconnect(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020182 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020183 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020184 return -EALREADY;
20185 }
20186
Jeff Johnson20227a92018-03-13 09:41:05 -070020187 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020188
Jeff Johnson5b34fce2017-10-13 13:24:51 -070020189 if (eCSR_BSS_TYPE_START_IBSS != roam_profile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020190 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020191 return -EINVAL;
20192 }
20193
20194 /* enable selected protection checks in IBSS mode */
Jeff Johnson5b34fce2017-10-13 13:24:51 -070020195 roam_profile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020196
Jeff Johnsonb8944722017-09-03 09:03:19 -070020197 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(hdd_ctx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020198 WNI_CFG_IBSS_ATIM_WIN_SIZE,
Jeff Johnsonb8944722017-09-03 09:03:19 -070020199 hdd_ctx->config->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020200 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020201 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020202 }
20203
20204 /* BSSID is provided by upper layers hence no need to AUTO generate */
20205 if (NULL != params->bssid) {
Jeff Johnsonb8944722017-09-03 09:03:19 -070020206 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020207 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020208 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020209 return -EIO;
20210 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053020211 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Jeff Johnsonb8944722017-09-03 09:03:19 -070020212 } else if (hdd_ctx->config->isCoalesingInIBSSAllowed == 0) {
20213 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020214 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020215 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020216 return -EIO;
20217 }
Jeff Johnsonb8944722017-09-03 09:03:19 -070020218 qdf_copy_macaddr(&bssid, &hdd_ctx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020219 }
20220 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
20221 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
Jeff Johnson5b34fce2017-10-13 13:24:51 -070020222 roam_profile->beaconInterval = params->beacon_interval;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020223 else {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070020224 roam_profile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020225 hdd_debug("input beacon interval %d TU is invalid, use default %d TU",
Jeff Johnson5b34fce2017-10-13 13:24:51 -070020226 params->beacon_interval, roam_profile->beaconInterval);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020227 }
20228
20229 /* Set Channel */
20230 if (channelNum) {
20231 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020232 hdd_debug("set channel %d", channelNum);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070020233 roam_profile->ChannelInfo.numOfChannels = 1;
Jeff Johnsond377dce2017-10-04 10:32:42 -070020234 sta_ctx->conn_info.operationChannel = channelNum;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070020235 roam_profile->ChannelInfo.ChannelList =
Jeff Johnsond377dce2017-10-04 10:32:42 -070020236 &sta_ctx->conn_info.operationChannel;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020237 }
20238
20239 /* Initialize security parameters */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020240 status = wlan_hdd_cfg80211_set_privacy_ibss(adapter, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020241 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020242 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020243 return status;
20244 }
20245
20246 /* Issue connect start */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020247 status = wlan_hdd_cfg80211_connect_start(adapter, params->ssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020248 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070020249 bssid.bytes, NULL,
Jeff Johnsond377dce2017-10-04 10:32:42 -070020250 sta_ctx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070020251 operationChannel,
20252 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020253
20254 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020255 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020256 return status;
20257 }
Dustin Browne74003f2018-03-14 12:51:58 -070020258 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020259 return 0;
20260}
20261
20262/**
20263 * wlan_hdd_cfg80211_join_ibss() - join ibss
20264 * @wiphy: Pointer to wiphy
20265 * @dev: Pointer to network device
20266 * @param: Pointer to IBSS join parameters
20267 *
20268 * This function is used to create/join an IBSS network
20269 *
20270 * Return: 0 for success, non-zero for failure
20271 */
20272static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
20273 struct net_device *dev,
20274 struct cfg80211_ibss_params *params)
20275{
20276 int ret = 0;
20277
20278 cds_ssr_protect(__func__);
20279 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
20280 cds_ssr_unprotect(__func__);
20281
20282 return ret;
20283}
20284
20285/**
20286 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
20287 * @wiphy: Pointer to wiphy
20288 * @dev: Pointer to network device
20289 *
20290 * This function is used to leave an IBSS network
20291 *
20292 * Return: 0 for success, non-zero for failure
20293 */
20294static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
20295 struct net_device *dev)
20296{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020297 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson61b5e982018-03-15 11:33:31 -070020298 struct csr_roam_profile *roam_profile;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020299 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020300 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020301 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053020302 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080020303 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020304
Dustin Brown491d54b2018-03-14 12:39:11 -070020305 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020306
Anurag Chouhan6d760662016-02-20 16:05:43 +053020307 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020308 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020309 return -EINVAL;
20310 }
20311
Jeff Johnson1b780e42017-10-31 14:11:45 -070020312 if (wlan_hdd_validate_session_id(adapter->session_id)) {
20313 hdd_err("Invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053020314 return -EINVAL;
20315 }
20316
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053020317 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020318 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
Jeff Johnson1b780e42017-10-31 14:11:45 -070020319 adapter->session_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020320 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
Jeff Johnsonb8944722017-09-03 09:03:19 -070020321 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053020322 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020323 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020324
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020325 hdd_debug("Device_mode %s(%d)",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020326 hdd_device_mode_to_string(adapter->device_mode),
20327 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020328
Jeff Johnson20227a92018-03-13 09:41:05 -070020329 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020330
20331 /* Issue disconnect only if interface type is set to IBSS */
Jeff Johnson5b34fce2017-10-13 13:24:51 -070020332 if (eCSR_BSS_TYPE_START_IBSS != roam_profile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020333 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020334 return -EINVAL;
20335 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080020336 /* Clearing add IE of beacon */
Jeff Johnson1e851a12017-10-28 14:36:12 -070020337 qdf_mem_copy(updateIE.bssid.bytes, adapter->mac_addr.bytes,
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080020338 sizeof(tSirMacAddr));
Jeff Johnson1b780e42017-10-31 14:11:45 -070020339 updateIE.smeSessionId = adapter->session_id;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080020340 updateIE.ieBufferlength = 0;
20341 updateIE.pAdditionIEBuffer = NULL;
20342 updateIE.append = true;
20343 updateIE.notify = true;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020344 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080020345 &updateIE,
20346 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020347 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080020348 }
20349
20350 /* Reset WNI_CFG_PROBE_RSP Flags */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020351 wlan_hdd_reset_prob_rspies(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020352
20353 /* Issue Disconnect request */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020354 INIT_COMPLETION(adapter->disconnect_comp_var);
20355 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -070020356 adapter->session_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020357 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020358 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020359 hdd_err("sme_roam_disconnect failed status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020360 hal_status);
20361 return -EAGAIN;
20362 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053020363
20364 /* wait for mc thread to cleanup and then return to upper stack
20365 * so by the time upper layer calls the change interface, we are
20366 * all set to proceed further
20367 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020368 rc = wait_for_completion_timeout(&adapter->disconnect_comp_var,
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053020369 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
20370 if (!rc) {
20371 hdd_err("Failed to disconnect, timed out");
20372 return -ETIMEDOUT;
20373 }
20374
Dustin Browne74003f2018-03-14 12:51:58 -070020375 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020376 return 0;
20377}
20378
20379/**
20380 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
20381 * @wiphy: Pointer to wiphy
20382 * @dev: Pointer to network device
20383 *
20384 * This function is used to leave an IBSS network
20385 *
20386 * Return: 0 for success, non-zero for failure
20387 */
20388static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
20389 struct net_device *dev)
20390{
20391 int ret = 0;
20392
20393 cds_ssr_protect(__func__);
20394 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
20395 cds_ssr_unprotect(__func__);
20396
20397 return ret;
20398}
20399
20400/**
20401 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
20402 * @wiphy: Pointer to wiphy
20403 * @changed: Parameters changed
20404 *
20405 * This function is used to set the phy parameters. RTS Threshold/FRAG
20406 * Threshold/Retry Count etc.
20407 *
20408 * Return: 0 for success, non-zero for failure
20409 */
20410static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
20411 u32 changed)
20412{
Jeff Johnsonb8944722017-09-03 09:03:19 -070020413 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
20414 tHalHandle hHal = hdd_ctx->hHal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020415 int status;
20416
Dustin Brown491d54b2018-03-14 12:39:11 -070020417 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020418
Anurag Chouhan6d760662016-02-20 16:05:43 +053020419 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020420 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020421 return -EINVAL;
20422 }
20423
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053020424 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020425 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
20426 NO_SESSION, wiphy->rts_threshold));
Jeff Johnsonb8944722017-09-03 09:03:19 -070020427 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020428
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053020429 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020430 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020431
20432 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
20433 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
20434 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
20435
20436 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
20437 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020438 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020439 rts_threshold);
20440 return -EINVAL;
20441 }
20442
20443 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
20444 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020445 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020446 rts_threshold);
20447 return -EIO;
20448 }
20449
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020450 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020451 }
20452
20453 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
20454 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
20455 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
20456 wiphy->frag_threshold;
20457
20458 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
20459 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020460 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020461 frag_threshold);
20462 return -EINVAL;
20463 }
20464
20465 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
20466 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020467 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020468 frag_threshold);
20469 return -EIO;
20470 }
20471
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020472 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020473 }
20474
Dustin Browne74003f2018-03-14 12:51:58 -070020475 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020476 return 0;
20477}
20478
20479/**
20480 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
20481 * @wiphy: Pointer to wiphy
20482 * @changed: Parameters changed
20483 *
20484 * Return: 0 for success, non-zero for failure
20485 */
20486static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
20487{
20488 int ret;
20489
20490 cds_ssr_protect(__func__);
20491 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
20492 cds_ssr_unprotect(__func__);
20493
20494 return ret;
20495}
20496
20497/**
20498 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
20499 * key
20500 * @wiphy: Pointer to wiphy
20501 * @dev: Pointer to network device
20502 * @key_index: Key index
20503 *
20504 * Return: 0
20505 */
20506static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
20507 struct net_device *netdev,
20508 u8 key_index)
20509{
Dustin Brown491d54b2018-03-14 12:39:11 -070020510 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020511 return 0;
20512}
20513
20514/**
20515 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
20516 * wlan_hdd_set_default_mgmt_key
20517 * @wiphy: pointer to wiphy
20518 * @netdev: pointer to net_device structure
20519 * @key_index: key index
20520 *
20521 * Return: 0 on success, error number on failure
20522 */
20523static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
20524 struct net_device *netdev,
20525 u8 key_index)
20526{
20527 int ret;
20528
20529 cds_ssr_protect(__func__);
20530 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
20531 cds_ssr_unprotect(__func__);
20532
20533 return ret;
20534}
20535
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020536/**
20537 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
20538 * @wiphy: Pointer to wiphy
20539 * @dev: Pointer to network device
20540 * @params: Pointer to tx queue parameters
20541 *
20542 * Return: 0
20543 */
20544static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
20545 struct net_device *dev,
20546 struct ieee80211_txq_params *params)
20547{
Dustin Brown491d54b2018-03-14 12:39:11 -070020548 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020549 return 0;
20550}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020551
20552/**
20553 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
20554 * @wiphy: pointer to wiphy
20555 * @netdev: pointer to net_device structure
20556 * @params: pointer to ieee80211_txq_params
20557 *
20558 * Return: 0 on success, error number on failure
20559 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020560static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
20561 struct net_device *dev,
20562 struct ieee80211_txq_params *params)
20563{
20564 int ret;
20565
20566 cds_ssr_protect(__func__);
20567 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
20568 cds_ssr_unprotect(__func__);
20569
20570 return ret;
20571}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020572
20573/**
20574 * __wlan_hdd_cfg80211_del_station() - delete station v2
20575 * @wiphy: Pointer to wiphy
20576 * @param: Pointer to delete station parameter
20577 *
20578 * Return: 0 for success, non-zero for failure
20579 */
20580static
20581int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
20582 struct net_device *dev,
Jeff Johnsone6bf7192017-11-07 15:16:09 -080020583 struct csr_del_sta_params *pDelStaParams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020584{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020585 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070020586 struct hdd_context *hdd_ctx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053020587 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Jeff Johnsonca2530c2017-09-30 18:25:40 -070020588 struct hdd_hostapd_state *hapd_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020589 int status;
20590 uint8_t staId;
20591 uint8_t *mac;
20592
Dustin Brown491d54b2018-03-14 12:39:11 -070020593 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020594
Anurag Chouhan6d760662016-02-20 16:05:43 +053020595 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020596 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020597 return -EINVAL;
20598 }
20599
Jeff Johnson1b780e42017-10-31 14:11:45 -070020600 if (wlan_hdd_validate_session_id(adapter->session_id)) {
20601 hdd_err("Invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053020602 return -EINVAL;
20603 }
20604
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053020605 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020606 TRACE_CODE_HDD_CFG80211_DEL_STA,
Jeff Johnson1b780e42017-10-31 14:11:45 -070020607 adapter->session_id, adapter->device_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020608
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020609 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070020610 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020611
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053020612 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020613 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020614
20615 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
20616
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020617 if ((QDF_SAP_MODE == adapter->device_mode) ||
20618 (QDF_P2P_GO_MODE == adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020619
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020620 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020621 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020622 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020623 return 0;
20624 }
20625
Anurag Chouhanc5548422016-02-24 18:33:27 +053020626 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020627 uint16_t i;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070020628
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020629 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -070020630 if ((adapter->sta_info[i].in_use) &&
20631 (!adapter->sta_info[i].
Jeff Johnsone4f5d932017-10-21 13:21:15 -070020632 is_deauth_in_progress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053020633 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020634 mac,
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -070020635 adapter->sta_info[i].
Jeff Johnsonf2356512017-10-21 16:04:12 -070020636 sta_mac.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053020637 QDF_MAC_ADDR_SIZE);
Yun Parka4bb37c2017-12-08 16:14:22 -080020638
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020639 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020640 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020641 MAC_ADDR_ARRAY(mac));
20642
Jeff Johnsonb8944722017-09-03 09:03:19 -070020643 if (hdd_ctx->dev_dfs_cac_status ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020644 DFS_CAC_IN_PROGRESS)
20645 goto fn_end;
20646
Wei Song2f76f642016-11-18 16:32:53 +080020647 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020648 hdd_softap_sta_disassoc(adapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053020649 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020650 qdf_status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020651 hdd_softap_sta_deauth(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020652 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020653 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -070020654 adapter->sta_info[i].
Jeff Johnsone4f5d932017-10-21 13:21:15 -070020655 is_deauth_in_progress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053020656 qdf_status =
Nachiket Kukade0396b732017-11-14 16:35:16 +053020657 qdf_wait_for_event_completion(
Naveen Rawatb56880c2016-12-13 17:56:03 -080020658 &hapd_state->
20659 qdf_sta_disassoc_event,
20660 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053020661 if (!QDF_IS_STATUS_SUCCESS(
20662 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020663 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020664 }
20665 }
20666 }
20667 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020668 qdf_status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020669 hdd_softap_get_sta_id(adapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053020670 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020671 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020672 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020673 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020674 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020675 MAC_ADDR_ARRAY(mac));
20676 return -ENOENT;
20677 }
20678
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -070020679 if (adapter->sta_info[staId].is_deauth_in_progress ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020680 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020681 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020682 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020683 MAC_ADDR_ARRAY(mac));
20684 return -ENOENT;
20685 }
20686
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -070020687 adapter->sta_info[staId].is_deauth_in_progress = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020688
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020689 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020690 MAC_ADDR_ARRAY(mac));
20691
20692 /* Case: SAP in ACS selected DFS ch and client connected
20693 * Now Radar detected. Then if random channel is another
20694 * DFS ch then new CAC is initiated and no TX allowed.
20695 * So do not send any mgmt frames as it will timeout
20696 * during CAC.
20697 */
20698
Jeff Johnsonb8944722017-09-03 09:03:19 -070020699 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020700 goto fn_end;
20701
Wei Song2f76f642016-11-18 16:32:53 +080020702 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053020703 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
Jeff Johnson1b780e42017-10-31 14:11:45 -070020704 (adapter), adapter->session_id,
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053020705 (uint8_t *)&pDelStaParams->peerMacAddr,
20706 pDelStaParams->reason_code, 0);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020707 qdf_status = hdd_softap_sta_deauth(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020708 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020709 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -070020710 adapter->sta_info[staId].is_deauth_in_progress =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020711 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020712 hdd_debug("STA removal failed for ::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020713 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020714 MAC_ADDR_ARRAY(mac));
20715 return -ENOENT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020716 }
Nachiket Kukade0396b732017-11-14 16:35:16 +053020717 qdf_status = qdf_wait_for_event_completion(
Srinivas Girigowda576b2352017-08-25 14:44:26 -070020718 &hapd_state->
20719 qdf_sta_disassoc_event,
20720 SME_CMD_TIMEOUT_VALUE);
20721 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
20722 hdd_warn("Deauth wait time expired");
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +053020723
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020724 }
20725 }
20726
20727fn_end:
Dustin Browne74003f2018-03-14 12:51:58 -070020728 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020729 return 0;
20730}
20731
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080020732#if defined(USE_CFG80211_DEL_STA_V2)
20733/**
20734 * wlan_hdd_del_station() - delete station wrapper
20735 * @adapter: pointer to the hdd adapter
20736 *
20737 * Return: None
20738 */
Jeff Johnsone5006672017-08-29 14:39:02 -070020739void wlan_hdd_del_station(struct hdd_adapter *adapter)
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080020740{
20741 struct station_del_parameters del_sta;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070020742
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080020743 del_sta.mac = NULL;
20744 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
20745 del_sta.reason_code = eCsrForcedDeauthSta;
20746
20747 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
20748 &del_sta);
20749}
20750#else
Jeff Johnsone5006672017-08-29 14:39:02 -070020751void wlan_hdd_del_station(struct hdd_adapter *adapter)
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080020752{
20753 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
20754}
20755#endif
20756
20757#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020758/**
20759 * wlan_hdd_cfg80211_del_station() - delete station v2
20760 * @wiphy: Pointer to wiphy
20761 * @param: Pointer to delete station parameter
20762 *
20763 * Return: 0 for success, non-zero for failure
20764 */
20765int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
20766 struct net_device *dev,
20767 struct station_del_parameters *param)
20768#else
20769/**
20770 * wlan_hdd_cfg80211_del_station() - delete station
20771 * @wiphy: Pointer to wiphy
20772 * @mac: Pointer to station mac address
20773 *
20774 * Return: 0 for success, non-zero for failure
20775 */
20776#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
20777int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
20778 struct net_device *dev,
20779 const uint8_t *mac)
20780#else
20781int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
20782 struct net_device *dev,
20783 uint8_t *mac)
20784#endif
20785#endif
20786{
20787 int ret;
Jeff Johnsone6bf7192017-11-07 15:16:09 -080020788 struct csr_del_sta_params delStaParams;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020789
20790 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080020791#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020792 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080020793 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020794 return -EINVAL;
20795 }
20796 wlansap_populate_del_sta_params(param->mac, param->reason_code,
20797 param->subtype, &delStaParams);
20798#else
20799 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
20800 (SIR_MAC_MGMT_DEAUTH >> 4),
20801 &delStaParams);
20802#endif
20803 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
20804 cds_ssr_unprotect(__func__);
20805
20806 return ret;
20807}
20808
20809/**
20810 * __wlan_hdd_cfg80211_add_station() - add station
20811 * @wiphy: Pointer to wiphy
20812 * @mac: Pointer to station mac address
20813 * @pmksa: Pointer to add station parameter
20814 *
20815 * Return: 0 for success, non-zero for failure
20816 */
20817static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
20818 struct net_device *dev,
20819 const uint8_t *mac,
20820 struct station_parameters *params)
20821{
20822 int status = -EPERM;
20823#ifdef FEATURE_WLAN_TDLS
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020824 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070020825 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020826 u32 mask, set;
20827
Dustin Brown491d54b2018-03-14 12:39:11 -070020828 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020829
Anurag Chouhan6d760662016-02-20 16:05:43 +053020830 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020831 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020832 return -EINVAL;
20833 }
20834
Jeff Johnson1b780e42017-10-31 14:11:45 -070020835 if (wlan_hdd_validate_session_id(adapter->session_id)) {
20836 hdd_err("Invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053020837 return -EINVAL;
20838 }
20839
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053020840 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020841 TRACE_CODE_HDD_CFG80211_ADD_STA,
Jeff Johnson1b780e42017-10-31 14:11:45 -070020842 adapter->session_id, params->listen_interval));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020843
Jeff Johnsonb8944722017-09-03 09:03:19 -070020844 if (0 != wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020845 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020846
20847 mask = params->sta_flags_mask;
20848
20849 set = params->sta_flags_set;
20850
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020851 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020852 MAC_ADDR_ARRAY(mac));
20853
20854 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud1a28462017-09-06 22:55:48 +080020855 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER))
Jeff Johnsonb8944722017-09-03 09:03:19 -070020856 status = wlan_cfg80211_tdls_add_peer(hdd_ctx->hdd_pdev,
Frank Liud4b2fa02017-03-29 11:46:48 +080020857 dev, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020858 }
20859#endif
Dustin Browne74003f2018-03-14 12:51:58 -070020860 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020861 return status;
20862}
20863
20864/**
20865 * wlan_hdd_cfg80211_add_station() - add station
20866 * @wiphy: Pointer to wiphy
20867 * @mac: Pointer to station mac address
20868 * @pmksa: Pointer to add station parameter
20869 *
20870 * Return: 0 for success, non-zero for failure
20871 */
20872#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
20873static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
20874 struct net_device *dev,
20875 const uint8_t *mac,
20876 struct station_parameters *params)
20877#else
20878static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
20879 struct net_device *dev, uint8_t *mac,
20880 struct station_parameters *params)
20881#endif
20882{
20883 int ret;
20884
20885 cds_ssr_protect(__func__);
20886 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
20887 cds_ssr_unprotect(__func__);
20888
20889 return ret;
20890}
20891
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053020892#if defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
20893 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020894/*
20895 * wlan_hdd_is_pmksa_valid: API to validate pmksa
20896 * @pmksa: pointer to cfg80211_pmksa structure
20897 *
20898 * Return: True if valid else false
20899 */
20900static inline bool wlan_hdd_is_pmksa_valid(struct cfg80211_pmksa *pmksa)
20901{
20902 if (!pmksa->bssid) {
Vignesh Viswanathanfa90d622017-12-22 13:13:26 +053020903 hdd_warn("bssid (%pK) is NULL",
20904 pmksa->bssid);
20905 if (!pmksa->ssid || !pmksa->cache_id) {
20906 hdd_err("either ssid (%pK) or cache_id (%pK) are NULL",
20907 pmksa->ssid, pmksa->cache_id);
20908 return false;
20909 }
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020910 }
20911 return true;
20912}
20913
20914/*
20915 * hdd_fill_pmksa_info: API to update tPmkidCacheInfo from cfg80211_pmksa
gaurank kathpalia99d06c12018-05-16 16:28:35 +053020916 * @adapter: Pointer to hdd adapter
20917 * @pmk_cache: pmk that needs to be udated
20918 * @pmksa: pmk from supplicant
20919 * @is_delete: Bool to decide set or delete PMK
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020920 * Return: None
20921 */
gaurank kathpalia99d06c12018-05-16 16:28:35 +053020922static void hdd_fill_pmksa_info(struct hdd_adapter *adapter,
20923 tPmkidCacheInfo *pmk_cache,
20924 struct cfg80211_pmksa *pmksa, bool is_delete)
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020925{
20926 if (pmksa->bssid) {
20927 hdd_debug("%s PMKSA for " MAC_ADDRESS_STR,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053020928 is_delete ? "Delete" : "Set",
20929 MAC_ADDR_ARRAY(pmksa->bssid));
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020930 qdf_mem_copy(pmk_cache->BSSID.bytes,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053020931 pmksa->bssid, QDF_MAC_ADDR_SIZE);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020932 } else {
Jeff Johnson9c749db2018-05-07 12:50:46 -070020933 qdf_mem_copy(pmk_cache->ssid, pmksa->ssid, pmksa->ssid_len);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053020934 qdf_mem_copy(pmk_cache->cache_id, pmksa->cache_id,
20935 CACHE_ID_LEN);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020936 pmk_cache->ssid_len = pmksa->ssid_len;
20937 hdd_debug("%s PMKSA for ssid %*.*s cache_id %x %x",
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053020938 is_delete ? "Delete" : "Set",
20939 pmk_cache->ssid_len, pmk_cache->ssid_len,
20940 pmk_cache->ssid, pmk_cache->cache_id[0],
20941 pmk_cache->cache_id[1]);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020942 }
20943
20944 if (is_delete)
20945 return;
20946
20947 qdf_mem_copy(pmk_cache->PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
20948 if (pmksa->pmk_len && (pmksa->pmk_len <= CSR_RSN_MAX_PMK_LEN)) {
20949 qdf_mem_copy(pmk_cache->pmk, pmksa->pmk, pmksa->pmk_len);
20950 pmk_cache->pmk_len = pmksa->pmk_len;
20951 } else
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053020952 hdd_debug("pmk len is %zu", pmksa->pmk_len);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020953}
20954#else
20955/*
20956 * wlan_hdd_is_pmksa_valid: API to validate pmksa
20957 * @pmksa: pointer to cfg80211_pmksa structure
20958 *
20959 * Return: True if valid else false
20960 */
20961static inline bool wlan_hdd_is_pmksa_valid(struct cfg80211_pmksa *pmksa)
20962{
20963 if (!pmksa->bssid) {
Jeff Johnson36e74c42017-09-18 08:15:42 -070020964 hdd_err("both bssid is NULL %pK", pmksa->bssid);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020965 return false;
20966 }
20967 return true;
20968}
20969
20970/*
20971 * hdd_fill_pmksa_info: API to update tPmkidCacheInfo from cfg80211_pmksa
gaurank kathpalia99d06c12018-05-16 16:28:35 +053020972 * @adapter: Pointer to hdd adapter
20973 * @pmk_cache: pmk which needs to be updated
20974 * @pmksa: pmk from supplicant
20975 * @is_delete: Bool to decide whether to set or delete PMK
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020976 *
20977 * Return: None
20978 */
gaurank kathpalia99d06c12018-05-16 16:28:35 +053020979static void hdd_fill_pmksa_info(struct hdd_adapter *adapter,
20980 tPmkidCacheInfo *pmk_cache,
20981 struct cfg80211_pmksa *pmksa, bool is_delete)
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020982{
gaurank kathpalia99d06c12018-05-16 16:28:35 +053020983 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020984 hdd_debug("%s PMKSA for " MAC_ADDRESS_STR, is_delete ? "Delete" : "Set",
20985 MAC_ADDR_ARRAY(pmksa->bssid));
20986 qdf_mem_copy(pmk_cache->BSSID.bytes,
20987 pmksa->bssid, QDF_MAC_ADDR_SIZE);
20988
20989 if (is_delete)
20990 return;
gaurank kathpalia99d06c12018-05-16 16:28:35 +053020991 sme_get_pmk_info(hal, adapter->session_id, pmk_cache);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020992 qdf_mem_copy(pmk_cache->PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
20993}
20994#endif
20995
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020996/**
20997 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
20998 * @wiphy: Pointer to wiphy
20999 * @dev: Pointer to network device
21000 * @pmksa: Pointer to set pmksa parameter
21001 *
21002 * Return: 0 for success, non-zero for failure
21003 */
21004static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
21005 struct net_device *dev,
21006 struct cfg80211_pmksa *pmksa)
21007{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021008 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
21009 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021010 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053021011 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021012 int status;
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021013 tPmkidCacheInfo pmk_cache;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021014
Dustin Brown491d54b2018-03-14 12:39:11 -070021015 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021016
Anurag Chouhan6d760662016-02-20 16:05:43 +053021017 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021018 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021019 return -EINVAL;
21020 }
21021
Jeff Johnson1b780e42017-10-31 14:11:45 -070021022 if (wlan_hdd_validate_session_id(adapter->session_id)) {
21023 hdd_err("Invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021024 return -EINVAL;
21025 }
21026
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021027 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021028 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021029 return -EINVAL;
21030 }
21031
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021032 if (!pmksa->pmkid) {
Jeff Johnson36e74c42017-09-18 08:15:42 -070021033 hdd_err("pmksa->pmkid(%pK) is NULL",
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021034 pmksa->pmkid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021035 return -EINVAL;
21036 }
21037
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021038 if (!wlan_hdd_is_pmksa_valid(pmksa))
21039 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021040
Jeff Johnsonb8944722017-09-03 09:03:19 -070021041 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021042
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021043 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021044 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021045
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021046 halHandle = WLAN_HDD_GET_HAL_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021047
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021048 qdf_mem_zero(&pmk_cache, sizeof(pmk_cache));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021049
gaurank kathpalia99d06c12018-05-16 16:28:35 +053021050 hdd_fill_pmksa_info(adapter, &pmk_cache, pmksa, false);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021051
21052 /*
21053 * Add to the PMKSA Cache in CSR
21054 * PMKSA cache will be having following
21055 * 1. pmkid id
21056 * 2. pmk
21057 * 3. bssid or cache identifier
21058 */
Jeff Johnson1b780e42017-10-31 14:11:45 -070021059 result = sme_roam_set_pmkid_cache(halHandle, adapter->session_id,
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021060 &pmk_cache, 1, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021061
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053021062 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021063 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
Jeff Johnson1b780e42017-10-31 14:11:45 -070021064 adapter->session_id, result));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021065
Jeff Johnson1b780e42017-10-31 14:11:45 -070021066 sme_set_del_pmkid_cache(halHandle, adapter->session_id,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021067 &pmk_cache, true);
21068
Dustin Browne74003f2018-03-14 12:51:58 -070021069 hdd_exit();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053021070 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021071}
21072
21073/**
21074 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
21075 * @wiphy: Pointer to wiphy
21076 * @dev: Pointer to network device
21077 * @pmksa: Pointer to set pmksa parameter
21078 *
21079 * Return: 0 for success, non-zero for failure
21080 */
21081static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
21082 struct net_device *dev,
21083 struct cfg80211_pmksa *pmksa)
21084{
21085 int ret;
21086
21087 cds_ssr_protect(__func__);
21088 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
21089 cds_ssr_unprotect(__func__);
21090
21091 return ret;
21092}
21093
21094/**
21095 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
21096 * @wiphy: Pointer to wiphy
21097 * @dev: Pointer to network device
21098 * @pmksa: Pointer to pmksa parameter
21099 *
21100 * Return: 0 for success, non-zero for failure
21101 */
21102static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
21103 struct net_device *dev,
21104 struct cfg80211_pmksa *pmksa)
21105{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021106 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
21107 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021108 tHalHandle halHandle;
21109 int status = 0;
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021110 tPmkidCacheInfo pmk_cache;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021111
Dustin Brown491d54b2018-03-14 12:39:11 -070021112 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021113
Anurag Chouhan6d760662016-02-20 16:05:43 +053021114 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021115 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021116 return -EINVAL;
21117 }
21118
Jeff Johnson1b780e42017-10-31 14:11:45 -070021119 if (wlan_hdd_validate_session_id(adapter->session_id)) {
21120 hdd_err("invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021121 return -EINVAL;
21122 }
21123
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021124 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021125 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021126 return -EINVAL;
21127 }
21128
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021129 if (!wlan_hdd_is_pmksa_valid(pmksa))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021130 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021131
Jeff Johnsonb8944722017-09-03 09:03:19 -070021132 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021133
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021134 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021135 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021136
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021137 halHandle = WLAN_HDD_GET_HAL_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021138
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053021139 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053021140 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
Jeff Johnson1b780e42017-10-31 14:11:45 -070021141 adapter->session_id, 0));
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021142
21143 qdf_mem_zero(&pmk_cache, sizeof(pmk_cache));
21144
gaurank kathpalia99d06c12018-05-16 16:28:35 +053021145 hdd_fill_pmksa_info(adapter, &pmk_cache, pmksa, true);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021146
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021147 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053021148 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021149 sme_roam_del_pmkid_from_cache(halHandle,
Jeff Johnson1b780e42017-10-31 14:11:45 -070021150 adapter->session_id, &pmk_cache,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021151 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021152 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021153 MAC_ADDR_ARRAY(pmksa->bssid));
21154 status = -EINVAL;
21155 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021156
Jeff Johnson1b780e42017-10-31 14:11:45 -070021157 sme_set_del_pmkid_cache(halHandle, adapter->session_id, &pmk_cache,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021158 false);
Dustin Browne74003f2018-03-14 12:51:58 -070021159 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021160 return status;
21161}
21162
21163/**
21164 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
21165 * @wiphy: Pointer to wiphy
21166 * @dev: Pointer to network device
21167 * @pmksa: Pointer to pmksa parameter
21168 *
21169 * Return: 0 for success, non-zero for failure
21170 */
21171static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
21172 struct net_device *dev,
21173 struct cfg80211_pmksa *pmksa)
21174{
21175 int ret;
21176
21177 cds_ssr_protect(__func__);
21178 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
21179 cds_ssr_unprotect(__func__);
21180
21181 return ret;
21182
21183}
21184
21185/**
21186 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
21187 * @wiphy: Pointer to wiphy
21188 * @dev: Pointer to network device
21189 *
21190 * Return: 0 for success, non-zero for failure
21191 */
21192static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
21193 struct net_device *dev)
21194{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021195 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
21196 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021197 tHalHandle halHandle;
21198 int status = 0;
21199
Dustin Brown491d54b2018-03-14 12:39:11 -070021200 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021201
Anurag Chouhan6d760662016-02-20 16:05:43 +053021202 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021203 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021204 return -EINVAL;
21205 }
21206
Jeff Johnson1b780e42017-10-31 14:11:45 -070021207 if (wlan_hdd_validate_session_id(adapter->session_id)) {
21208 hdd_err("invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021209 return -EINVAL;
21210 }
21211
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021212 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021213
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021214 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070021215 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021216
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021217 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021218 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021219
21220 /* Retrieve halHandle */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021221 halHandle = WLAN_HDD_GET_HAL_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021222
21223 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053021224 if (QDF_STATUS_SUCCESS !=
Jeff Johnson1b780e42017-10-31 14:11:45 -070021225 sme_roam_del_pmkid_from_cache(halHandle, adapter->session_id, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021226 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021227 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021228 status = -EINVAL;
21229 }
Vignesh Viswanathane8a26b22017-10-11 20:38:47 +053021230
Jeff Johnson1b780e42017-10-31 14:11:45 -070021231 sme_set_del_pmkid_cache(halHandle, adapter->session_id, NULL, false);
Dustin Browne74003f2018-03-14 12:51:58 -070021232 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021233 return status;
21234}
21235
21236/**
21237 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
21238 * @wiphy: Pointer to wiphy
21239 * @dev: Pointer to network device
21240 *
21241 * Return: 0 for success, non-zero for failure
21242 */
21243static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
21244 struct net_device *dev)
21245{
21246 int ret;
21247
21248 cds_ssr_protect(__func__);
21249 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
21250 cds_ssr_unprotect(__func__);
21251
21252 return ret;
21253}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021254
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080021255#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021256/**
21257 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
21258 * @wiphy: Pointer to wiphy
21259 * @dev: Pointer to network device
21260 * @ftie: Pointer to fast transition ie parameter
21261 *
21262 * Return: 0 for success, non-zero for failure
21263 */
21264static int
21265__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
21266 struct net_device *dev,
21267 struct cfg80211_update_ft_ies_params *ftie)
21268{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070021269 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021270 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsond377dce2017-10-04 10:32:42 -070021271 struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021272 int status;
21273
Dustin Brown491d54b2018-03-14 12:39:11 -070021274 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021275
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021276 status = wlan_hdd_validate_context(hdd_ctx);
21277 if (status)
21278 return status;
21279
Anurag Chouhan6d760662016-02-20 16:05:43 +053021280 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021281 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021282 return -EINVAL;
21283 }
21284
Jeff Johnson1b780e42017-10-31 14:11:45 -070021285 if (wlan_hdd_validate_session_id(adapter->session_id)) {
21286 hdd_err("invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021287 return -EINVAL;
21288 }
21289
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053021290 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021291 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
Jeff Johnson1b780e42017-10-31 14:11:45 -070021292 adapter->session_id, sta_ctx->conn_info.connState));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021293 /* Added for debug on reception of Re-assoc Req. */
Jeff Johnsond377dce2017-10-04 10:32:42 -070021294 if (eConnectionState_Associated != sta_ctx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021295 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021296 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021297 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021298 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021299 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021300 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021301
21302 /* Pass the received FT IEs to SME */
Jeff Johnson1b780e42017-10-31 14:11:45 -070021303 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(adapter), adapter->session_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021304 (const u8 *)ftie->ie, ftie->ie_len);
Dustin Browne74003f2018-03-14 12:51:58 -070021305 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021306 return 0;
21307}
21308
21309/**
21310 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
21311 * @wiphy: Pointer to wiphy
21312 * @dev: Pointer to network device
21313 * @ftie: Pointer to fast transition ie parameter
21314 *
21315 * Return: 0 for success, non-zero for failure
21316 */
21317static int
21318wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
21319 struct net_device *dev,
21320 struct cfg80211_update_ft_ies_params *ftie)
21321{
21322 int ret;
21323
21324 cds_ssr_protect(__func__);
21325 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
21326 cds_ssr_unprotect(__func__);
21327
21328 return ret;
21329}
21330#endif
21331
Ashish Kumar Dhanotiyacf11bae2017-04-04 03:29:47 +053021332void wlan_hdd_cfg80211_update_replay_counter_cb(
Mukul Sharma3d36c392017-01-18 18:39:12 +053021333 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
21334
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021335{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021336 struct hdd_adapter *adapter = (struct hdd_adapter *)cb_ctx;
Mukul Sharma3d36c392017-01-18 18:39:12 +053021337 uint8_t temp_replay_counter[8];
21338 int i;
21339 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021340
Dustin Brown491d54b2018-03-14 12:39:11 -070021341 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021342
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021343 if (!adapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021344 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053021345 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021346 }
21347
Mukul Sharma3d36c392017-01-18 18:39:12 +053021348 if (!gtk_rsp_param) {
21349 hdd_err("gtk_rsp_param is Null");
21350 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021351 }
21352
Mukul Sharma3d36c392017-01-18 18:39:12 +053021353 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021354 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053021355 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021356 }
21357
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021358 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053021359 gtk_rsp_param->replay_counter);
21360 /* convert little to big endian since supplicant works on big endian */
21361 p = (uint8_t *)&gtk_rsp_param->replay_counter;
21362 for (i = 0; i < 8; i++)
21363 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021364
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021365 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021366 /* Update replay counter to NL */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021367 cfg80211_gtk_rekey_notify(adapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053021368 gtk_rsp_param->bssid.bytes,
21369 temp_replay_counter, GFP_KERNEL);
21370out:
Dustin Browne74003f2018-03-14 12:51:58 -070021371 hdd_exit();
Mukul Sharma3d36c392017-01-18 18:39:12 +053021372
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021373}
21374
Wu Gaoa9d336b2018-05-30 14:48:04 +080021375#ifdef WLAN_FEATURE_GTK_OFFLOAD
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021376/**
21377 * wlan_hdd_copy_gtk_kek - Copy the KEK from GTK rekey data to GTK request
21378 * @gtk_req: Pointer to GTK request
21379 * @data: Pointer to rekey data
21380 *
21381 * Return: none
21382 */
21383#ifdef CFG80211_REKEY_DATA_KEK_LEN
21384static
21385void wlan_hdd_copy_gtk_kek(struct pmo_gtk_req *gtk_req,
21386 struct cfg80211_gtk_rekey_data *data)
21387{
21388 qdf_mem_copy(gtk_req->kek, data->kek, data->kek_len);
21389 gtk_req->kek_len = data->kek_len;
21390}
21391#else
21392static
21393void wlan_hdd_copy_gtk_kek(struct pmo_gtk_req *gtk_req,
21394 struct cfg80211_gtk_rekey_data *data)
21395{
21396 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
21397 gtk_req->kek_len = NL80211_KEK_LEN;
21398}
21399#endif
21400
21401/**
21402 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
21403 * @wiphy: Pointer to wiphy
21404 * @dev: Pointer to network device
21405 * @data: Pointer to rekey data
21406 *
21407 * This function is used to offload GTK rekeying job to the firmware.
21408 *
21409 * Return: 0 for success, non-zero for failure
21410 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070021411static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021412int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053021413 struct net_device *dev,
21414 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021415{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021416 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053021417 int result, i;
21418 struct pmo_gtk_req *gtk_req = NULL;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021419 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Mukul Sharma3d36c392017-01-18 18:39:12 +053021420 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053021421 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021422
Dustin Brown491d54b2018-03-14 12:39:11 -070021423 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021424
Anurag Chouhan6d760662016-02-20 16:05:43 +053021425 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021426 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053021427 result = -EINVAL;
21428 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021429 }
21430
Jeff Johnson1b780e42017-10-31 14:11:45 -070021431 if (wlan_hdd_validate_session_id(adapter->session_id)) {
21432 hdd_err("invalid session id: %d", adapter->session_id);
Mukul Sharma3d36c392017-01-18 18:39:12 +053021433 result = -EINVAL;
21434 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021435 }
21436
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053021437 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021438 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
Jeff Johnson1b780e42017-10-31 14:11:45 -070021439 adapter->session_id, adapter->device_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021440
Mukul Sharma3d36c392017-01-18 18:39:12 +053021441 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021442 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053021443 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021444
Mukul Sharma3d36c392017-01-18 18:39:12 +053021445 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
21446 if (!gtk_req) {
21447 hdd_err("cannot allocate gtk_req");
21448 result = -ENOMEM;
21449 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021450 }
21451
Mukul Sharma3d36c392017-01-18 18:39:12 +053021452 /* convert big to little endian since driver work on little endian */
21453 buf = (uint8_t *)&gtk_req->replay_counter;
21454 for (i = 0; i < 8; i++)
21455 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021456
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021457 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053021458 gtk_req->replay_counter);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021459
21460 wlan_hdd_copy_gtk_kek(gtk_req, data);
Mukul Sharma3d36c392017-01-18 18:39:12 +053021461 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021462 status = pmo_ucfg_cache_gtk_offload_req(adapter->hdd_vdev, gtk_req);
Mukul Sharma3d36c392017-01-18 18:39:12 +053021463 if (status != QDF_STATUS_SUCCESS) {
21464 hdd_err("Failed to cache GTK Offload");
21465 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021466 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053021467out:
21468 if (gtk_req)
21469 qdf_mem_free(gtk_req);
Dustin Browne74003f2018-03-14 12:51:58 -070021470 hdd_exit();
Mukul Sharma3d36c392017-01-18 18:39:12 +053021471
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021472 return result;
21473}
21474
21475/**
21476 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
21477 * @wiphy: Pointer to wiphy
21478 * @dev: Pointer to network device
21479 * @data: Pointer to rekey data
21480 *
21481 * This function is used to offload GTK rekeying job to the firmware.
21482 *
21483 * Return: 0 for success, non-zero for failure
21484 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070021485static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021486int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
21487 struct net_device *dev,
21488 struct cfg80211_gtk_rekey_data *data)
21489{
21490 int ret;
21491
21492 cds_ssr_protect(__func__);
21493 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
21494 cds_ssr_unprotect(__func__);
21495
21496 return ret;
21497}
Wu Gaoa9d336b2018-05-30 14:48:04 +080021498#endif /* WLAN_FEATURE_GTK_OFFLOAD */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021499
21500/**
21501 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
21502 * @wiphy: Pointer to wiphy
21503 * @dev: Pointer to network device
21504 * @param: Pointer to access control parameter
21505 *
21506 * Return: 0 for success, non-zero for failure
21507 */
21508static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
21509 struct net_device *dev,
21510 const struct cfg80211_acl_data *params)
21511{
21512 int i;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021513 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson5c19ade2017-10-04 09:52:12 -070021514 struct hdd_hostapd_state *hostapd_state;
Jeff Johnsone4c11db2018-05-05 23:22:32 -070021515 tsap_config_t *pConfig;
Jeff Johnsonb8944722017-09-03 09:03:19 -070021516 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021517 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053021518 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021519
Dustin Brown491d54b2018-03-14 12:39:11 -070021520 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021521
Anurag Chouhan6d760662016-02-20 16:05:43 +053021522 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021523 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021524 return -EINVAL;
21525 }
21526
21527 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021528 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021529 return -EINVAL;
21530 }
21531
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021532 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070021533 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021534
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021535 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021536 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021537
Jeff Johnson5c19ade2017-10-04 09:52:12 -070021538 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021539
Jeff Johnson5c19ade2017-10-04 09:52:12 -070021540 if (NULL == hostapd_state) {
21541 hdd_err("hostapd_state is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021542 return -EINVAL;
21543 }
21544
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021545 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021546 params->n_acl_entries);
21547
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053021548 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053021549 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
Jeff Johnson1b780e42017-10-31 14:11:45 -070021550 adapter->session_id, adapter->device_mode));
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021551 if (QDF_SAP_MODE == adapter->device_mode) {
Jeff Johnsonb9424862017-10-30 08:49:35 -070021552 pConfig = &adapter->session.ap.sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021553
21554 /* default value */
21555 pConfig->num_accept_mac = 0;
21556 pConfig->num_deny_mac = 0;
21557
21558 /**
21559 * access control policy
21560 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
21561 * listed in hostapd.deny file.
21562 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
21563 * listed in hostapd.accept file.
21564 */
21565 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
21566 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
21567 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
21568 params->acl_policy) {
21569 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
21570 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021571 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021572 params->acl_policy);
21573 return -ENOTSUPP;
21574 }
21575
21576 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
21577 pConfig->num_accept_mac = params->n_acl_entries;
21578 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021579 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021580 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021581 MAC_ADDR_ARRAY(
21582 params->mac_addrs[i].addr));
21583
Anurag Chouhan600c3a02016-03-01 10:33:54 +053021584 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021585 params->mac_addrs[i].addr,
21586 sizeof(qcmacaddr));
21587 }
21588 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
21589 pConfig->num_deny_mac = params->n_acl_entries;
21590 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021591 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021592 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021593 MAC_ADDR_ARRAY(
21594 params->mac_addrs[i].addr));
21595
Anurag Chouhan600c3a02016-03-01 10:33:54 +053021596 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021597 params->mac_addrs[i].addr,
21598 sizeof(qcmacaddr));
21599 }
21600 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070021601 qdf_status = wlansap_set_mac_acl(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021602 WLAN_HDD_GET_SAP_CTX_PTR(adapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053021603 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021604 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021605 return -EINVAL;
21606 }
21607 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021608 hdd_debug("Invalid device_mode %s(%d)",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021609 hdd_device_mode_to_string(adapter->device_mode),
21610 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021611 return -EINVAL;
21612 }
Dustin Browne74003f2018-03-14 12:51:58 -070021613 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021614 return 0;
21615}
21616
21617/**
21618 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
21619 * __wlan_hdd_cfg80211_set_mac_acl
21620 * @wiphy: pointer to wiphy structure
21621 * @dev: pointer to net_device
21622 * @params: pointer to cfg80211_acl_data
21623 *
21624 * Return; 0 on success, error number otherwise
21625 */
21626static int
21627wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
21628 struct net_device *dev,
21629 const struct cfg80211_acl_data *params)
21630{
21631 int ret;
21632
21633 cds_ssr_protect(__func__);
21634 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
21635 cds_ssr_unprotect(__func__);
21636
21637 return ret;
21638}
21639
21640#ifdef WLAN_NL80211_TESTMODE
21641#ifdef FEATURE_WLAN_LPHB
21642/**
21643 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
Jeff Johnsonb8944722017-09-03 09:03:19 -070021644 * @hdd_ctx: Pointer to hdd context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021645 * @lphbInd: Pointer to low power heart beat indication parameter
21646 *
21647 * Return: none
21648 */
Jeff Johnsonb8944722017-09-03 09:03:19 -070021649static void wlan_hdd_cfg80211_lphb_ind_handler(void *hdd_ctx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053021650 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021651{
21652 struct sk_buff *skb;
21653
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021654 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021655
Jeff Johnsonb8944722017-09-03 09:03:19 -070021656 if (0 != wlan_hdd_validate_context((struct hdd_context *) hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021657 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021658
Mukul Sharmafcd57f52017-03-20 18:18:59 +053021659 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021660 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021661 return;
21662 }
21663
Jeff Johnsonb8944722017-09-03 09:03:19 -070021664 skb = cfg80211_testmode_alloc_event_skb(((struct hdd_context *) hdd_ctx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053021665 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021666 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021667 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021668 return;
21669 }
21670
21671 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021672 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021673 goto nla_put_failure;
21674 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053021675 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021676 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021677 goto nla_put_failure;
21678 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053021679 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
21680 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021681 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021682 goto nla_put_failure;
21683 }
21684 cfg80211_testmode_event(skb, GFP_ATOMIC);
21685 return;
21686
21687nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021688 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021689 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021690}
21691#endif /* FEATURE_WLAN_LPHB */
21692
21693/**
21694 * __wlan_hdd_cfg80211_testmode() - test mode
21695 * @wiphy: Pointer to wiphy
21696 * @data: Data pointer
21697 * @len: Data length
21698 *
21699 * Return: 0 for success, non-zero for failure
21700 */
21701static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
21702 void *data, int len)
21703{
21704 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
21705 int err;
Jeff Johnsonb8944722017-09-03 09:03:19 -070021706 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021707
Dustin Brown491d54b2018-03-14 12:39:11 -070021708 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021709
Jeff Johnsonb8944722017-09-03 09:03:19 -070021710 err = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021711 if (err)
21712 return err;
21713
Dustin Brown4ea21db2018-01-05 14:13:17 -080021714 err = wlan_cfg80211_nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
21715 len, wlan_hdd_tm_policy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021716 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021717 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021718 return err;
21719 }
21720
21721 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021722 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021723 return -EINVAL;
21724 }
21725
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053021726 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053021727 TRACE_CODE_HDD_CFG80211_TESTMODE,
21728 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021729 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
21730#ifdef FEATURE_WLAN_LPHB
21731 /* Low Power Heartbeat configuration request */
21732 case WLAN_HDD_TM_CMD_WLAN_HB:
21733 {
21734 int buf_len;
21735 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053021736 struct pmo_lphb_req *hb_params = NULL;
21737 struct pmo_lphb_req *hb_params_temp = NULL;
21738 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021739
21740 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021741 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021742 return -EINVAL;
21743 }
21744
21745 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
21746 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
21747
Mukul Sharmafcd57f52017-03-20 18:18:59 +053021748 hb_params_temp = (struct pmo_lphb_req *) buf;
21749 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
21750 && (hb_params_temp->params.lphb_tcp_params.
21751 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021752 return -EINVAL;
21753
Manjeet Singh00b2a562017-01-03 12:08:10 +053021754 if (buf_len > sizeof(*hb_params)) {
21755 hdd_err("buf_len=%d exceeded hb_params size limit",
21756 buf_len);
21757 return -ERANGE;
21758 }
21759
Mukul Sharmafcd57f52017-03-20 18:18:59 +053021760 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
21761 sizeof(*hb_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021762 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021763 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021764 return -ENOMEM;
21765 }
21766
Ashish Kumar Dhanotiya0fa8ee02017-07-13 14:04:31 +053021767 qdf_mem_zero(hb_params, sizeof(*hb_params));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053021768 qdf_mem_copy(hb_params, buf, buf_len);
Jeff Johnsonb8944722017-09-03 09:03:19 -070021769 status = pmo_ucfg_lphb_config_req(hdd_ctx->hdd_psoc,
21770 hb_params, (void *)hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021771 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053021772 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021773 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053021774
21775 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021776 return 0;
21777 }
21778#endif /* FEATURE_WLAN_LPHB */
21779
21780#if defined(QCA_WIFI_FTM)
21781 case WLAN_HDD_TM_CMD_WLAN_FTM:
21782 {
Ryan Hsuc8b27a42018-01-02 13:57:56 -080021783 err = wlan_cfg80211_ftm_testmode_cmd(hdd_ctx->hdd_pdev,
21784 data, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021785 break;
21786 }
21787#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021788 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021789 hdd_err("command: %d not supported",
Ryan Hsuc8b27a42018-01-02 13:57:56 -080021790 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021791 return -EOPNOTSUPP;
21792 }
Ryan Hsuc8b27a42018-01-02 13:57:56 -080021793
Dustin Browne74003f2018-03-14 12:51:58 -070021794 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021795 return err;
21796}
21797
21798/**
21799 * wlan_hdd_cfg80211_testmode() - test mode
21800 * @wiphy: Pointer to wiphy
21801 * @dev: Pointer to network device
21802 * @data: Data pointer
21803 * @len: Data length
21804 *
21805 * Return: 0 for success, non-zero for failure
21806 */
21807static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
21808#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
21809 struct wireless_dev *wdev,
21810#endif
21811 void *data, int len)
21812{
21813 int ret;
21814
21815 cds_ssr_protect(__func__);
21816 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
21817 cds_ssr_unprotect(__func__);
21818
21819 return ret;
21820}
21821
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021822#endif /* CONFIG_NL80211_TESTMODE */
21823
21824#ifdef QCA_HT_2040_COEX
21825/**
21826 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
21827 * @wiphy: Pointer to wiphy
21828 * @dev: Pointer to network device
21829 * @chandef: Pointer to channel definition parameter
21830 *
21831 * Return: 0 for success, non-zero for failure
21832 */
21833static int
21834__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
21835 struct net_device *dev,
21836 struct cfg80211_chan_def *chandef)
21837{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021838 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070021839 struct hdd_context *hdd_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053021840 QDF_STATUS status;
Sridhar Selvaraj48c47092017-07-31 18:18:14 +053021841 int retval = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021842
Anurag Chouhan6d760662016-02-20 16:05:43 +053021843 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021844 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021845 return -EINVAL;
21846 }
21847
Jeff Johnson1b780e42017-10-31 14:11:45 -070021848 if (wlan_hdd_validate_session_id(adapter->session_id)) {
21849 hdd_err("invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021850 return -EINVAL;
21851 }
Abhishek Singh9d5f4582017-10-11 17:59:48 +053021852 if (!(adapter->device_mode == QDF_SAP_MODE ||
21853 adapter->device_mode == QDF_P2P_GO_MODE))
21854 return -EOPNOTSUPP;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021855
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021856 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070021857 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053021858 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021859 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021860
Abhishek Singh9d5f4582017-10-11 17:59:48 +053021861 hdd_debug("Channel width changed to %d ",
21862 cfg80211_get_chandef_type(chandef));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021863
21864 /* Change SAP ht2040 mode */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021865 status = hdd_set_sap_ht2040_mode(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021866 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053021867 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021868 hdd_err("Cannot set SAP HT20/40 mode!");
Sridhar Selvaraj48c47092017-07-31 18:18:14 +053021869 retval = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021870 }
21871
Sridhar Selvaraj48c47092017-07-31 18:18:14 +053021872 return retval;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021873}
21874
21875/**
21876 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
21877 * @wiphy: Pointer to wiphy
21878 * @dev: Pointer to network device
21879 * @chandef: Pointer to channel definition parameter
21880 *
21881 * Return: 0 for success, non-zero for failure
21882 */
21883static int
21884wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
21885 struct net_device *dev,
21886 struct cfg80211_chan_def *chandef)
21887{
21888 int ret;
21889
21890 cds_ssr_protect(__func__);
21891 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
21892 cds_ssr_unprotect(__func__);
21893
21894 return ret;
21895}
21896#endif
21897
Abhishek Singh1bdb1572015-10-16 16:24:19 +053021898#ifdef CHANNEL_SWITCH_SUPPORTED
21899/**
21900 * __wlan_hdd_cfg80211_channel_switch()- function to switch
21901 * channel in SAP/GO
21902 * @wiphy: wiphy pointer
21903 * @dev: dev pointer.
21904 * @csa_params: Change channel params
21905 *
21906 * This function is called to switch channel in SAP/GO
21907 *
21908 * Return: 0 if success else return non zero
21909 */
21910static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
21911 struct net_device *dev,
21912 struct cfg80211_csa_settings *csa_params)
21913{
Jeff Johnsone5006672017-08-29 14:39:02 -070021914 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070021915 struct hdd_context *hdd_ctx;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053021916 uint8_t channel;
21917 uint16_t freq;
21918 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080021919 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053021920
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021921 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053021922 csa_params->chandef.chan->center_freq);
21923
Jeff Johnson1b780e42017-10-31 14:11:45 -070021924 if (wlan_hdd_validate_session_id(adapter->session_id)) {
21925 hdd_err("invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021926 return -EINVAL;
21927 }
21928
Abhishek Singh1bdb1572015-10-16 16:24:19 +053021929 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
21930 ret = wlan_hdd_validate_context(hdd_ctx);
21931
21932 if (0 != ret)
21933 return ret;
21934
Krunal Sonib4326f22016-03-10 13:05:51 -080021935 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
21936 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053021937 return -ENOTSUPP;
21938
21939 freq = csa_params->chandef.chan->center_freq;
21940 channel = cds_freq_to_chan(freq);
21941
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053021942 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
21943
Min Liu2fef5792018-01-19 17:59:42 +080021944 ret = hdd_softap_set_channel_change(dev, channel, ch_width, false);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053021945 return ret;
21946}
21947
21948/**
21949 * wlan_hdd_cfg80211_channel_switch()- function to switch
21950 * channel in SAP/GO
21951 * @wiphy: wiphy pointer
21952 * @dev: dev pointer.
21953 * @csa_params: Change channel params
21954 *
21955 * This function is called to switch channel in SAP/GO
21956 *
21957 * Return: 0 if success else return non zero
21958 */
21959static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
21960 struct net_device *dev,
21961 struct cfg80211_csa_settings *csa_params)
21962{
21963 int ret;
21964
21965 cds_ssr_protect(__func__);
21966 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
21967 cds_ssr_unprotect(__func__);
21968 return ret;
21969}
21970#endif
21971
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021972/**
21973 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
21974 * translation from NL to policy manager type
21975 * @type: Generic connection mode type defined in NL
21976 *
21977 *
21978 * This function provides the type translation
21979 *
21980 * Return: cds_con_mode enum
21981 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080021982enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021983 enum nl80211_iftype type)
21984{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080021985 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070021986
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021987 switch (type) {
21988 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080021989 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021990 break;
21991 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080021992 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021993 break;
21994 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080021995 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021996 break;
21997 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080021998 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021999 break;
22000 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080022001 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022002 break;
22003 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022004 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022005 }
22006 return mode;
22007}
22008
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022009int wlan_hdd_change_hw_mode_for_given_chnl(struct hdd_adapter *adapter,
22010 uint8_t channel,
22011 enum policy_mgr_conn_update_reason reason)
22012{
22013 QDF_STATUS status;
22014 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
22015
Dustin Brown491d54b2018-03-14 12:39:11 -070022016 hdd_enter();
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022017 if (0 != wlan_hdd_validate_context(hdd_ctx))
22018 return -EINVAL;
22019
22020 status = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
22021 if (!QDF_IS_STATUS_SUCCESS(status))
22022 hdd_err("clearing event failed");
22023
22024 status = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
22025 adapter->session_id, channel, reason);
22026 switch (status) {
22027 case QDF_STATUS_E_FAILURE:
22028 /*
Jeff Johnson11d7c9d2018-05-06 15:44:09 -070022029 * QDF_STATUS_E_FAILURE indicates that some error has occurred
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022030 * while changing the hw mode
22031 */
22032 hdd_err("ERROR: connections update failed!!");
22033 return -EINVAL;
22034
22035 case QDF_STATUS_SUCCESS:
22036 /*
22037 * QDF_STATUS_SUCCESS indicates that HW mode change has been
22038 * triggered and wait for it to finish.
22039 */
22040 status = policy_mgr_wait_for_connection_update(
22041 hdd_ctx->hdd_psoc);
22042 if (!QDF_IS_STATUS_SUCCESS(status)) {
22043 hdd_err("ERROR: qdf wait for event failed!!");
22044 return -EINVAL;
22045 }
22046 if (QDF_MONITOR_MODE == adapter->device_mode)
22047 hdd_info("Monitor mode:channel:%d (SMM->DBS)", channel);
22048 break;
22049
22050 default:
22051 /*
22052 * QDF_STATUS_E_NOSUPPORT indicates that no HW mode change is
22053 * required, so caller can proceed further.
22054 */
22055 break;
22056
22057 }
Dustin Browne74003f2018-03-14 12:51:58 -070022058 hdd_exit();
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022059
22060 return 0;
22061}
22062
Nirav Shah73713f72018-05-17 14:50:41 +053022063#ifdef FEATURE_MONITOR_MODE_SUPPORT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022064/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022065 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
22066 * @wiphy: Handle to struct wiphy to get handle to module context.
22067 * @chandef: Contains information about the capture channel to be set.
22068 *
22069 * This interface is called if and only if monitor mode interface alone is
22070 * active.
22071 *
22072 * Return: 0 success or error code on failure.
22073 */
22074static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
22075 struct cfg80211_chan_def *chandef)
22076{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070022077 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnsone5006672017-08-29 14:39:02 -070022078 struct hdd_adapter *adapter;
Jeff Johnson40dae4e2017-08-29 14:00:25 -070022079 struct hdd_station_ctx *sta_ctx;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022080 struct hdd_mon_set_ch_info *ch_info;
22081 QDF_STATUS status;
22082 tHalHandle hal_hdl;
22083 struct qdf_mac_addr bssid;
Jeff Johnson61b5e982018-03-15 11:33:31 -070022084 struct csr_roam_profile roam_profile;
Amar Singhal5cccafe2017-02-15 12:42:58 -080022085 struct ch_params ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070022086 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022087 int ret;
22088 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
22089
Dustin Brown491d54b2018-03-14 12:39:11 -070022090 hdd_enter();
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022091
22092 ret = wlan_hdd_validate_context(hdd_ctx);
22093 if (ret)
22094 return ret;
22095
22096 hal_hdl = hdd_ctx->hHal;
22097
22098 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
22099 if (!adapter)
22100 return -EIO;
22101
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022102 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022103 adapter->dev->name, chan_num, chandef->chan->center_freq);
22104
22105 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
22106 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022107 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
22108 roam_profile.ChannelInfo.numOfChannels = 1;
22109 roam_profile.phyMode = ch_info->phy_mode;
Naveen Rawat3184dd82017-07-05 14:58:18 -070022110 roam_profile.ch_params.ch_width = hdd_map_nl_chan_width(chandef->width);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070022111 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022112
Jeff Johnson1e851a12017-10-28 14:36:12 -070022113 qdf_mem_copy(bssid.bytes, adapter->mac_addr.bytes,
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022114 QDF_MAC_ADDR_SIZE);
22115
Naveen Rawat3184dd82017-07-05 14:58:18 -070022116 ch_params.ch_width = hdd_map_nl_chan_width(chandef->width);
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070022117 /*
22118 * CDS api expects secondary channel for calculating
22119 * the channel params
22120 */
22121 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070022122 (WLAN_REG_IS_24GHZ_CH(chan_num))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070022123 if (chan_num >= 1 && chan_num <= 5)
22124 sec_ch = chan_num + 4;
22125 else if (chan_num >= 6 && chan_num <= 13)
22126 sec_ch = chan_num - 4;
22127 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070022128 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan_num,
22129 sec_ch, &ch_params);
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022130 if (wlan_hdd_change_hw_mode_for_given_chnl(adapter, chan_num,
22131 POLICY_MGR_UPDATE_REASON_SET_OPER_CHAN)) {
22132 hdd_err("Failed to change hw mode");
22133 return -EINVAL;
22134 }
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022135 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
22136 &roam_profile);
22137 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022138 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022139 status);
22140 ret = qdf_status_to_os_return(status);
22141 return ret;
22142 }
Dustin Browne74003f2018-03-14 12:51:58 -070022143 hdd_exit();
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022144
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022145 return 0;
22146}
22147
22148/**
22149 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
22150 * @wiphy: Handle to struct wiphy to get handle to module context.
22151 * @chandef: Contains information about the capture channel to be set.
22152 *
22153 * This interface is called if and only if monitor mode interface alone is
22154 * active.
22155 *
22156 * Return: 0 success or error code on failure.
22157 */
22158static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
22159 struct cfg80211_chan_def *chandef)
22160{
22161 int ret;
22162
22163 cds_ssr_protect(__func__);
22164 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
22165 cds_ssr_unprotect(__func__);
22166 return ret;
22167}
Nirav Shah73713f72018-05-17 14:50:41 +053022168#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022169
22170/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053022171 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
22172 * @adapter: pointer to adapter
22173 *
22174 * Wrapper function to clear link layer stats.
22175 * return - void
22176 */
Jeff Johnsone5006672017-08-29 14:39:02 -070022177void wlan_hdd_clear_link_layer_stats(struct hdd_adapter *adapter)
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053022178{
22179 tSirLLStatsClearReq link_layer_stats_clear_req;
22180 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
22181
Mukul Sharma491021c2016-09-29 21:39:19 +053022182 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
22183 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053022184 link_layer_stats_clear_req.stopReq = 0;
22185 link_layer_stats_clear_req.reqId = 1;
Jeff Johnson1b780e42017-10-31 14:11:45 -070022186 link_layer_stats_clear_req.staId = adapter->session_id;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053022187 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053022188}
22189
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053022190#define CNT_DIFF(cur, prev) \
22191 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
22192#define MAX_COUNT 0xffffffff
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070022193static void hdd_update_chan_info(struct hdd_context *hdd_ctx,
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053022194 struct scan_chan_info *chan,
22195 struct scan_chan_info *info, uint32_t cmd_flag)
22196{
22197 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
22198 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
22199 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
22200
22201 mutex_lock(&hdd_ctx->chan_info_lock);
22202
22203 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
22204 qdf_mem_zero(chan, sizeof(*chan));
22205
22206 chan->freq = info->freq;
22207 chan->noise_floor = info->noise_floor;
22208 chan->clock_freq = info->clock_freq;
22209 chan->cmd_flag = info->cmd_flag;
22210 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
22211
22212 chan->rx_clear_count =
22213 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
22214
22215 chan->tx_frame_count =
22216 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
22217
22218 mutex_unlock(&hdd_ctx->chan_info_lock);
22219
22220}
22221#undef CNT_DIFF
22222#undef MAX_COUNT
22223
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022224#if defined(WLAN_FEATURE_FILS_SK) &&\
Sridhar Selvaraje5260442017-08-19 10:12:03 +053022225 defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) &&\
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022226 (defined(CFG80211_UPDATE_CONNECT_PARAMS) ||\
22227 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)))
22228
22229#ifndef UPDATE_FILS_ERP_INFO
22230#define UPDATE_FILS_ERP_INFO BIT(1)
22231#endif
22232
22233#ifndef UPDATE_FILS_AUTH_TYPE
22234#define UPDATE_FILS_AUTH_TYPE BIT(2)
22235#endif
22236
22237/**
22238 * __wlan_hdd_cfg80211_update_connect_params - update connect params
22239 * @wiphy: Handle to struct wiphy to get handle to module context.
22240 * @dev: Pointer to network device
22241 * @req: Pointer to connect params
22242 * @changed: Bitmap used to indicate the changed params
22243 *
22244 * Update the connect parameters while connected to a BSS. The updated
22245 * parameters can be used by driver/firmware for subsequent BSS selection
22246 * (roaming) decisions and to form the Authentication/(Re)Association
22247 * Request frames. This call does not request an immediate disassociation
22248 * or reassociation with the current BSS, i.e., this impacts only
22249 * subsequent (re)associations. The bits in changed are defined in enum
22250 * cfg80211_connect_params_changed
22251 *
22252 * Return: zero for success, non-zero for failure
22253 */
22254static int __wlan_hdd_cfg80211_update_connect_params(
22255 struct wiphy *wiphy, struct net_device *dev,
22256 struct cfg80211_connect_params *req, uint32_t changed)
22257{
Jeff Johnson61b5e982018-03-15 11:33:31 -070022258 struct csr_roam_profile *roam_profile;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022259 uint8_t *buf;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070022260 int ret;
22261 enum eAniAuthType auth_type;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022262 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
22263 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
22264 QDF_STATUS status;
22265 struct cds_fils_connection_info *fils_info;
22266
Dustin Brownfdf17c12018-03-14 12:55:34 -070022267 hdd_enter_dev(dev);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022268
Jeff Johnson1b780e42017-10-31 14:11:45 -070022269 if (wlan_hdd_validate_session_id(adapter->session_id)) {
22270 hdd_err("invalid session id: %d", adapter->session_id);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022271 return -EINVAL;
22272 }
22273
22274 ret = wlan_hdd_validate_context(hdd_ctx);
22275 if (ret)
22276 return -EINVAL;
22277
Jeff Johnson20227a92018-03-13 09:41:05 -070022278 roam_profile = hdd_roam_profile(adapter);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022279 fils_info = roam_profile->fils_con_info;
22280
22281 if (!fils_info) {
22282 hdd_err("No valid FILS conn info");
22283 return -EINVAL;
22284 }
22285
22286 if (req->ie_len)
22287 wlan_hdd_cfg80211_set_ie(adapter, req->ie, req->ie_len);
22288
22289 if (changed)
22290 fils_info->is_fils_connection = true;
22291
22292 if (changed & UPDATE_FILS_ERP_INFO) {
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080022293 if (!wlan_hdd_fils_data_in_limits(req))
Jeff Johnsonb8adae42018-02-27 16:12:00 -080022294 return -EINVAL;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022295 fils_info->key_nai_length = req->fils_erp_username_len +
22296 sizeof(char) +
22297 req->fils_erp_realm_len;
Dundi Raviteja170d2872018-03-23 15:49:54 +053022298 if (fils_info->key_nai_length >
22299 FILS_MAX_KEYNAME_NAI_LENGTH) {
22300 hdd_err("Key NAI Length %d",
22301 fils_info->key_nai_length);
22302 return -EINVAL;
22303 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022304 if (req->fils_erp_username_len && req->fils_erp_username) {
22305 buf = fils_info->keyname_nai;
22306 qdf_mem_copy(buf, req->fils_erp_username,
22307 req->fils_erp_username_len);
22308 buf += req->fils_erp_username_len;
22309 *buf++ = '@';
22310 qdf_mem_copy(buf, req->fils_erp_realm,
22311 req->fils_erp_realm_len);
22312 }
22313
22314 fils_info->sequence_number = req->fils_erp_next_seq_num;
22315 fils_info->r_rk_length = req->fils_erp_rrk_len;
22316
22317 if (req->fils_erp_rrk_len && req->fils_erp_rrk)
22318 qdf_mem_copy(fils_info->r_rk, req->fils_erp_rrk,
22319 fils_info->r_rk_length);
22320
22321 fils_info->realm_len = req->fils_erp_realm_len;
22322 if (req->fils_erp_realm_len && req->fils_erp_realm)
22323 qdf_mem_copy(fils_info->realm, req->fils_erp_realm,
22324 fils_info->realm_len);
22325 }
22326
22327 if (changed & UPDATE_FILS_AUTH_TYPE) {
22328 auth_type = wlan_hdd_get_fils_auth_type(req->auth_type);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070022329 if (auth_type == eSIR_DONOT_USE_AUTH_TYPE) {
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022330 hdd_err("invalid auth type for fils %d",
22331 req->auth_type);
22332 return -EINVAL;
22333 }
22334
22335 roam_profile->fils_con_info->auth_type = auth_type;
22336 }
22337
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080022338 hdd_debug("fils conn update: changed %x is_fils %d keyname nai len %d",
22339 changed, roam_profile->fils_con_info->is_fils_connection,
22340 roam_profile->fils_con_info->key_nai_length);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022341
Abhishek Singh1f217ec2017-12-22 11:48:27 +053022342 if (!hdd_ctx->is_fils_roaming_supported) {
22343 hdd_debug("FILS roaming support %d",
Vignesh Viswanathan731186f2017-09-18 13:47:37 +053022344 hdd_ctx->is_fils_roaming_supported);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022345 return 0;
22346 }
22347
Jeff Johnson1b780e42017-10-31 14:11:45 -070022348 status = sme_update_fils_config(hdd_ctx->hHal, adapter->session_id,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022349 roam_profile);
22350 if (QDF_IS_STATUS_ERROR(status))
22351 hdd_err("Update FILS connect params to Fw failed %d", status);
22352
22353 return 0;
22354}
22355
22356/**
22357 * wlan_hdd_cfg80211_update_connect_params - SSR wrapper for
22358 * __wlan_hdd_cfg80211_update_connect_params
22359 * @wiphy: Pointer to wiphy structure
22360 * @dev: Pointer to net_device
22361 * @req: Pointer to connect params
22362 * @changed: flags used to indicate the changed params
22363 *
22364 * Return: zero for success, non-zero for failure
22365 */
22366static int wlan_hdd_cfg80211_update_connect_params(struct wiphy *wiphy,
22367 struct net_device *dev,
22368 struct cfg80211_connect_params *req,
22369 uint32_t changed)
22370{
22371 int ret;
22372
22373 cds_ssr_protect(__func__);
22374 ret = __wlan_hdd_cfg80211_update_connect_params(wiphy, dev,
22375 req, changed);
22376 cds_ssr_unprotect(__func__);
22377
22378 return ret;
22379}
22380#endif
22381
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053022382#if defined(WLAN_FEATURE_SAE) && \
22383 defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
22384/**
22385 * __wlan_hdd_cfg80211_external_auth() - Handle external auth
22386 * @wiphy: Pointer to wireless phy
22387 * @dev: net device
22388 * @params: Pointer to external auth params
22389 *
22390 * Return: 0 on success, negative errno on failure
22391 */
22392static int
22393__wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
22394 struct net_device *dev,
22395 struct cfg80211_external_auth_params *params)
22396{
22397 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
22398 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
22399 int ret;
22400
22401 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
22402 hdd_err("Command not allowed in FTM mode");
22403 return -EPERM;
22404 }
22405
22406 if (wlan_hdd_validate_session_id(adapter->session_id)) {
22407 hdd_err("invalid session id: %d", adapter->session_id);
22408 return -EINVAL;
22409 }
22410
22411 ret = wlan_hdd_validate_context(hdd_ctx);
22412 if (ret)
22413 return ret;
22414
22415
22416 hdd_debug("external_auth status: %d", params->status);
22417 sme_handle_sae_msg(hdd_ctx->hHal, adapter->session_id, params->status);
22418
22419 return ret;
22420}
22421
22422/**
22423 * wlan_hdd_cfg80211_external_auth() - Handle external auth
22424 * @wiphy: Pointer to wireless phy
22425 * @dev: net device
22426 * @params: Pointer to external auth params
22427 *
22428 * Return: 0 on success, negative errno on failure
22429 */
22430static int
22431wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
22432 struct net_device *dev,
22433 struct cfg80211_external_auth_params *params)
22434{
22435 int ret;
22436
22437 cds_ssr_protect(__func__);
22438 ret = __wlan_hdd_cfg80211_external_auth(wiphy, dev, params);
22439 cds_ssr_unprotect(__func__);
22440
22441 return ret;
22442}
22443#endif
22444
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053022445/**
22446 * wlan_hdd_chan_info_cb() - channel info callback
22447 * @chan_info: struct scan_chan_info
22448 *
22449 * Store channel info into HDD context
22450 *
22451 * Return: None.
22452 */
22453static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
22454{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070022455 struct hdd_context *hdd_ctx;
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053022456 struct scan_chan_info *chan;
22457 uint8_t idx;
22458
Dustin Brown491d54b2018-03-14 12:39:11 -070022459 hdd_enter();
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053022460
22461 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
22462 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
22463 hdd_err("hdd_ctx is invalid");
22464 return;
22465 }
22466
22467 if (!hdd_ctx->chan_info) {
22468 hdd_err("chan_info is NULL");
22469 return;
22470 }
22471
22472 chan = hdd_ctx->chan_info;
22473 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
22474 if (chan[idx].freq == info->freq) {
22475 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
22476 info->cmd_flag);
22477 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
22478 chan[idx].cmd_flag, chan[idx].freq,
22479 chan[idx].noise_floor,
22480 chan[idx].cycle_count, chan[idx].rx_clear_count,
22481 chan[idx].clock_freq, chan[idx].cmd_flag,
22482 chan[idx].tx_frame_count, idx);
22483 if (chan[idx].freq == 0)
22484 break;
22485
22486 }
22487 }
22488
Dustin Browne74003f2018-03-14 12:51:58 -070022489 hdd_exit();
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053022490}
22491
22492/**
22493 * wlan_hdd_init_chan_info() - init chan info in hdd context
22494 * @hdd_ctx: HDD context pointer
22495 *
22496 * Return: none
22497 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070022498void wlan_hdd_init_chan_info(struct hdd_context *hdd_ctx)
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053022499{
22500 uint8_t num_2g, num_5g, index = 0;
22501
Kapil Gupta63e75282017-05-18 20:55:10 +053022502 hdd_ctx->chan_info = NULL;
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053022503 if (!hdd_ctx->config->fEnableSNRMonitoring) {
22504 hdd_info("SNR monitoring is disabled");
22505 return;
22506 }
22507
22508 hdd_ctx->chan_info =
22509 qdf_mem_malloc(sizeof(struct scan_chan_info)
22510 * QDF_MAX_NUM_CHAN);
22511 if (hdd_ctx->chan_info == NULL) {
22512 hdd_err("Failed to malloc for chan info");
22513 return;
22514 }
22515 mutex_init(&hdd_ctx->chan_info_lock);
22516
22517 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
22518 for (; index < num_2g; index++) {
22519 hdd_ctx->chan_info[index].freq =
22520 hdd_channels_2_4_ghz[index].center_freq;
22521 }
22522
22523 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
22524 for (; (index - num_2g) < num_5g; index++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070022525 if (WLAN_REG_IS_11P_CH(
22526 hdd_channels_5_ghz[index - num_2g].hw_value))
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053022527 continue;
22528 hdd_ctx->chan_info[index].freq =
22529 hdd_channels_5_ghz[index - num_2g].center_freq;
22530 }
22531 sme_set_chan_info_callback(hdd_ctx->hHal,
22532 &wlan_hdd_chan_info_cb);
22533}
22534
22535/**
22536 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
22537 * @hdd_ctx: hdd context pointer
22538 *
22539 * Return: none
22540 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070022541void wlan_hdd_deinit_chan_info(struct hdd_context *hdd_ctx)
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053022542{
22543 struct scan_chan_info *chan;
22544
22545 chan = hdd_ctx->chan_info;
22546 hdd_ctx->chan_info = NULL;
22547 if (chan)
22548 qdf_mem_free(chan);
22549}
22550
Dustin Brown32cb4792017-06-15 15:33:42 -070022551#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) || defined(WITH_BACKPORTS)
22552static enum rate_info_bw hdd_map_hdd_bw_to_os(enum hdd_rate_info_bw hdd_bw)
22553{
22554 switch (hdd_bw) {
22555 case HDD_RATE_BW_5:
22556 return RATE_INFO_BW_5;
22557 case HDD_RATE_BW_10:
22558 return RATE_INFO_BW_10;
22559 case HDD_RATE_BW_20:
22560 return RATE_INFO_BW_20;
22561 case HDD_RATE_BW_40:
22562 return RATE_INFO_BW_40;
22563 case HDD_RATE_BW_80:
22564 return RATE_INFO_BW_80;
22565 case HDD_RATE_BW_160:
22566 return RATE_INFO_BW_160;
22567 }
22568
22569 hdd_err("Unhandled HDD_RATE_BW: %d", hdd_bw);
22570
22571 return RATE_INFO_BW_20;
22572}
22573
22574void hdd_set_rate_bw(struct rate_info *info, enum hdd_rate_info_bw hdd_bw)
22575{
22576 info->bw = hdd_map_hdd_bw_to_os(hdd_bw);
22577}
22578#else
22579static enum rate_info_flags hdd_map_hdd_bw_to_os(enum hdd_rate_info_bw hdd_bw)
22580{
22581 switch (hdd_bw) {
22582 case HDD_RATE_BW_5:
22583 case HDD_RATE_BW_10:
22584 case HDD_RATE_BW_20:
22585 return (enum rate_info_flags)0;
22586 case HDD_RATE_BW_40:
22587 return RATE_INFO_FLAGS_40_MHZ_WIDTH;
22588 case HDD_RATE_BW_80:
22589 return RATE_INFO_FLAGS_80_MHZ_WIDTH;
22590 case HDD_RATE_BW_160:
22591 return RATE_INFO_FLAGS_160_MHZ_WIDTH;
22592 }
22593
22594 hdd_err("Unhandled HDD_RATE_BW: %d", hdd_bw);
22595
22596 return (enum rate_info_flags)0;
22597}
22598
22599void hdd_set_rate_bw(struct rate_info *info, enum hdd_rate_info_bw hdd_bw)
22600{
22601 const enum rate_info_flags all_bws =
22602 RATE_INFO_FLAGS_40_MHZ_WIDTH |
22603 RATE_INFO_FLAGS_80_MHZ_WIDTH |
22604 RATE_INFO_FLAGS_80P80_MHZ_WIDTH |
22605 RATE_INFO_FLAGS_160_MHZ_WIDTH;
22606
22607 info->flags &= ~all_bws;
22608 info->flags |= hdd_map_hdd_bw_to_os(hdd_bw);
22609}
22610#endif
22611
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053022612/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022613 * struct cfg80211_ops - cfg80211_ops
22614 *
22615 * @add_virtual_intf: Add virtual interface
22616 * @del_virtual_intf: Delete virtual interface
22617 * @change_virtual_intf: Change virtual interface
22618 * @change_station: Change station
22619 * @add_beacon: Add beacon in sap mode
22620 * @del_beacon: Delete beacon in sap mode
22621 * @set_beacon: Set beacon in sap mode
22622 * @start_ap: Start ap
22623 * @change_beacon: Change beacon
22624 * @stop_ap: Stop ap
22625 * @change_bss: Change bss
22626 * @add_key: Add key
22627 * @get_key: Get key
22628 * @del_key: Delete key
22629 * @set_default_key: Set default key
22630 * @set_channel: Set channel
22631 * @scan: Scan
22632 * @connect: Connect
22633 * @disconnect: Disconnect
22634 * @join_ibss = Join ibss
22635 * @leave_ibss = Leave ibss
22636 * @set_wiphy_params = Set wiphy params
22637 * @set_tx_power = Set tx power
22638 * @get_tx_power = get tx power
22639 * @remain_on_channel = Remain on channel
22640 * @cancel_remain_on_channel = Cancel remain on channel
22641 * @mgmt_tx = Tx management frame
22642 * @mgmt_tx_cancel_wait = Cancel management tx wait
22643 * @set_default_mgmt_key = Set default management key
22644 * @set_txq_params = Set tx queue parameters
22645 * @get_station = Get station
22646 * @set_power_mgmt = Set power management
22647 * @del_station = Delete station
22648 * @add_station = Add station
22649 * @set_pmksa = Set pmksa
22650 * @del_pmksa = Delete pmksa
22651 * @flush_pmksa = Flush pmksa
22652 * @update_ft_ies = Update FT IEs
22653 * @tdls_mgmt = Tdls management
22654 * @tdls_oper = Tdls operation
22655 * @set_rekey_data = Set rekey data
22656 * @sched_scan_start = Scheduled scan start
22657 * @sched_scan_stop = Scheduled scan stop
22658 * @resume = Resume wlan
22659 * @suspend = Suspend wlan
22660 * @set_mac_acl = Set mac acl
22661 * @testmode_cmd = Test mode command
22662 * @set_ap_chanwidth = Set AP channel bandwidth
22663 * @dump_survey = Dump survey
22664 * @key_mgmt_set_pmk = Set pmk key management
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022665 * @update_connect_params = Update connect params
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022666 */
22667static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
22668 .add_virtual_intf = wlan_hdd_add_virtual_intf,
22669 .del_virtual_intf = wlan_hdd_del_virtual_intf,
22670 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
22671 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022672 .start_ap = wlan_hdd_cfg80211_start_ap,
22673 .change_beacon = wlan_hdd_cfg80211_change_beacon,
22674 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022675 .change_bss = wlan_hdd_cfg80211_change_bss,
22676 .add_key = wlan_hdd_cfg80211_add_key,
22677 .get_key = wlan_hdd_cfg80211_get_key,
22678 .del_key = wlan_hdd_cfg80211_del_key,
22679 .set_default_key = wlan_hdd_cfg80211_set_default_key,
22680 .scan = wlan_hdd_cfg80211_scan,
22681 .connect = wlan_hdd_cfg80211_connect,
22682 .disconnect = wlan_hdd_cfg80211_disconnect,
22683 .join_ibss = wlan_hdd_cfg80211_join_ibss,
22684 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
22685 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
22686 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
22687 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
22688 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
22689 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
22690 .mgmt_tx = wlan_hdd_mgmt_tx,
22691 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
22692 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
22693 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053022694 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022695 .get_station = wlan_hdd_cfg80211_get_station,
22696 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
22697 .del_station = wlan_hdd_cfg80211_del_station,
22698 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022699 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
22700 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
22701 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080022702#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022703 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
22704#endif
22705#ifdef FEATURE_WLAN_TDLS
22706 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
22707 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
22708#endif
22709#ifdef WLAN_FEATURE_GTK_OFFLOAD
22710 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
22711#endif /* WLAN_FEATURE_GTK_OFFLOAD */
22712#ifdef FEATURE_WLAN_SCAN_PNO
22713 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
22714 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
22715#endif /*FEATURE_WLAN_SCAN_PNO */
22716 .resume = wlan_hdd_cfg80211_resume_wlan,
22717 .suspend = wlan_hdd_cfg80211_suspend_wlan,
22718 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
22719#ifdef WLAN_NL80211_TESTMODE
22720 .testmode_cmd = wlan_hdd_cfg80211_testmode,
22721#endif
22722#ifdef QCA_HT_2040_COEX
22723 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
22724#endif
22725 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053022726#ifdef CHANNEL_SWITCH_SUPPORTED
22727 .channel_switch = wlan_hdd_cfg80211_channel_switch,
22728#endif
Nirav Shah73713f72018-05-17 14:50:41 +053022729#ifdef FEATURE_MONITOR_MODE_SUPPORT
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022730 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Nirav Shah73713f72018-05-17 14:50:41 +053022731#endif
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053022732#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
Srinivas Girigowda576b2352017-08-25 14:44:26 -070022733 defined(CFG80211_ABORT_SCAN)
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053022734 .abort_scan = wlan_hdd_cfg80211_abort_scan,
22735#endif
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022736#if defined(WLAN_FEATURE_FILS_SK) &&\
Sridhar Selvaraje5260442017-08-19 10:12:03 +053022737 defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) &&\
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022738 (defined(CFG80211_UPDATE_CONNECT_PARAMS) ||\
22739 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)))
22740 .update_connect_params = wlan_hdd_cfg80211_update_connect_params,
22741#endif
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053022742#if defined(WLAN_FEATURE_SAE) && \
22743 defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
22744 .external_auth = wlan_hdd_cfg80211_external_auth,
22745#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022746};