blob: dcf3e0e4dd8e032cdc143c4726bebb9027d670be [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 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wlan_hdd_cfg80211.c
30 *
31 * WLAN Host Device Driver cfg80211 APIs implementation
32 *
33 */
34
35#include <linux/version.h>
36#include <linux/module.h>
37#include <linux/kernel.h>
38#include <linux/init.h>
39#include <linux/etherdevice.h>
40#include <linux/wireless.h>
41#include <wlan_hdd_includes.h>
42#include <net/arp.h>
43#include <net/cfg80211.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080044#include <wlan_hdd_wowl.h>
45#include <ani_global.h>
46#include "sir_params.h"
47#include "dot11f.h"
48#include "wlan_hdd_assoc.h"
49#include "wlan_hdd_wext.h"
50#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070051#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080052#include "wlan_hdd_p2p.h"
53#include "wlan_hdd_cfg80211.h"
54#include "wlan_hdd_hostapd.h"
55#include "wlan_hdd_softap_tx_rx.h"
56#include "wlan_hdd_main.h"
57#include "wlan_hdd_power.h"
58#include "wlan_hdd_trace.h"
Dustin Brownd4241942018-02-26 12:51:37 -080059#include "qdf_str.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053060#include "qdf_trace.h"
Dustin Brownd4241942018-02-26 12:51:37 -080061#include "qdf_types.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080062#include "cds_utils.h"
63#include "cds_sched.h"
64#include "wlan_hdd_scan.h"
65#include <qc_sap_ioctl.h>
66#include "wlan_hdd_tdls.h"
67#include "wlan_hdd_wmm.h"
68#include "wma_types.h"
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053069#include "wma.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080070#include "wlan_hdd_misc.h"
71#include "wlan_hdd_nan.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080072#include "wlan_logging_sock_svc.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053073#include "sap_api.h"
Agrawal Ashish21ba2572016-09-03 16:40:10 +053074#include "csr_api.h"
Agrawal Ashish467dde42016-09-08 18:44:22 +053075#include "pld_common.h"
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070076#include "wmi_unified_param.h"
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070077
Paul Zhang3a210c52016-12-08 10:18:12 +080078#ifdef WLAN_UMAC_CONVERGENCE
79#include "wlan_cfg80211.h"
80#endif
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -080081#include <cdp_txrx_handle.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -080082#include <wlan_cfg80211_scan.h>
Ryan Hsuc8b27a42018-01-02 13:57:56 -080083#include <wlan_cfg80211_ftm.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080084
85#ifdef FEATURE_WLAN_EXTSCAN
86#include "wlan_hdd_ext_scan.h"
87#endif
88
89#ifdef WLAN_FEATURE_LINK_LAYER_STATS
90#include "wlan_hdd_stats.h"
91#endif
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080092#include "cds_api.h"
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080093#include "wlan_policy_mgr_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080094#include "qwlan_version.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080095
96#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070097#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080098
Ravi Joshideb5a8d2015-11-09 19:11:43 -080099#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +0530100#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700101#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700102#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530103#include "wlan_hdd_disa.h"
Jeff Johnsoncd113fc2017-01-26 14:42:44 -0800104#include "wlan_hdd_request_manager.h"
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -0800105#include "wlan_hdd_he.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800106
Leo Changfdb45c32016-10-28 11:09:23 -0700107#include <cdp_txrx_cmn.h>
108#include <cdp_txrx_misc.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -0800109#include <qca_vendor.h>
Mukul Sharma3d36c392017-01-18 18:39:12 +0530110#include "wlan_pmo_ucfg_api.h"
Naveen Rawat5f040ba2017-03-06 12:20:25 -0800111#include "os_if_wifi_pos.h"
Ajit Pal Singh90a45a42017-04-18 18:53:46 +0530112#include "wlan_utility.h"
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -0700113#include "wlan_reg_ucfg_api.h"
Naveen Rawatd2657be2017-10-10 14:31:23 -0700114#include "wifi_pos_api.h"
Sandeep Puligilla063a4342018-01-10 02:50:14 -0800115#include "wlan_hdd_spectralscan.h"
Sravan Kumar Kairam858073b2018-03-13 09:03:32 +0530116#include "wlan_ipa_ucfg_api.h"
117
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800118#define g_mode_rates_size (12)
119#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800120
121/*
122 * Android CTS verifier needs atleast this much wait time (in msec)
123 */
124#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
125
126/*
127 * Refer @tCfgProtection structure for definition of the bit map.
128 * below value is obtained by setting the following bit-fields.
129 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
130 */
131#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
132
133#define HDD2GHZCHAN(freq, chan, flag) { \
Srinivas Girigowda11c28e02017-06-27 20:06:21 -0700134 .band = HDD_NL80211_BAND_2GHZ, \
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 HDD5GHZCHAN(freq, chan, flag) { \
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -0700143 .band = HDD_NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800144 .center_freq = (freq), \
145 .hw_value = (chan), \
146 .flags = (flag), \
147 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800148 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800149}
150
151#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
152 { \
153 .bitrate = rate, \
154 .hw_value = rate_id, \
155 .flags = flag, \
156 }
157
Dustin Brown5f7d38e2017-08-16 11:30:08 -0700158#ifndef WLAN_AKM_SUITE_FT_8021X
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800159#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
Dustin Brown5f7d38e2017-08-16 11:30:08 -0700160#endif
161
Dustin Brown234d45f2017-08-16 11:45:05 -0700162#ifndef WLAN_AKM_SUITE_FT_PSK
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800163#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Dustin Brown234d45f2017-08-16 11:45:05 -0700164#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800165
166#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800167
Agrawal Ashish65634612016-08-18 13:24:32 +0530168#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
169 mode <= DFS_MODE_DEPRIORITIZE))
Agrawal Ashish65634612016-08-18 13:24:32 +0530170
Peng Xu4d67c8f2015-10-16 16:02:26 -0700171#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530172#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700173
Mohit Khannaceb97782017-04-05 16:27:08 -0700174/*
175 * Number of DPTRACE records to dump when a cfg80211 disconnect with reason
176 * WLAN_REASON_DEAUTH_LEAVING DEAUTH is received from user-space.
177 */
178#define WLAN_DEAUTH_DPTRACE_DUMP_COUNT 100
Mukul Sharma05504ac2017-06-08 12:35:53 +0530179#ifndef WLAN_CIPHER_SUITE_GCMP
180#define WLAN_CIPHER_SUITE_GCMP 0x000FAC08
181#endif
182#ifndef WLAN_CIPHER_SUITE_GCMP_256
183#define WLAN_CIPHER_SUITE_GCMP_256 0x000FAC09
184#endif
Mohit Khannaceb97782017-04-05 16:27:08 -0700185
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +0530186static const u32 hdd_gcmp_cipher_suits[] = {
187 WLAN_CIPHER_SUITE_GCMP,
188 WLAN_CIPHER_SUITE_GCMP_256,
189};
190
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800191static const u32 hdd_cipher_suites[] = {
192 WLAN_CIPHER_SUITE_WEP40,
193 WLAN_CIPHER_SUITE_WEP104,
194 WLAN_CIPHER_SUITE_TKIP,
195#ifdef FEATURE_WLAN_ESE
196#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
197#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
198 WLAN_CIPHER_SUITE_BTK,
199 WLAN_CIPHER_SUITE_KRK,
200 WLAN_CIPHER_SUITE_CCMP,
201#else
202 WLAN_CIPHER_SUITE_CCMP,
203#endif
204#ifdef FEATURE_WLAN_WAPI
205 WLAN_CIPHER_SUITE_SMS4,
206#endif
207#ifdef WLAN_FEATURE_11W
208 WLAN_CIPHER_SUITE_AES_CMAC,
Padma, Santhosh Kumar4117d7a2017-12-20 17:39:33 +0530209#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
210 WLAN_CIPHER_SUITE_BIP_GMAC_128,
211 WLAN_CIPHER_SUITE_BIP_GMAC_256,
212#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800213#endif
214};
215
Abhishek Singhf512bf32016-05-04 16:47:46 +0530216static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800217 HDD2GHZCHAN(2412, 1, 0),
218 HDD2GHZCHAN(2417, 2, 0),
219 HDD2GHZCHAN(2422, 3, 0),
220 HDD2GHZCHAN(2427, 4, 0),
221 HDD2GHZCHAN(2432, 5, 0),
222 HDD2GHZCHAN(2437, 6, 0),
223 HDD2GHZCHAN(2442, 7, 0),
224 HDD2GHZCHAN(2447, 8, 0),
225 HDD2GHZCHAN(2452, 9, 0),
226 HDD2GHZCHAN(2457, 10, 0),
227 HDD2GHZCHAN(2462, 11, 0),
228 HDD2GHZCHAN(2467, 12, 0),
229 HDD2GHZCHAN(2472, 13, 0),
230 HDD2GHZCHAN(2484, 14, 0),
231};
232
Abhishek Singhf512bf32016-05-04 16:47:46 +0530233static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800234 HDD5GHZCHAN(5180, 36, 0),
235 HDD5GHZCHAN(5200, 40, 0),
236 HDD5GHZCHAN(5220, 44, 0),
237 HDD5GHZCHAN(5240, 48, 0),
238 HDD5GHZCHAN(5260, 52, 0),
239 HDD5GHZCHAN(5280, 56, 0),
240 HDD5GHZCHAN(5300, 60, 0),
241 HDD5GHZCHAN(5320, 64, 0),
242 HDD5GHZCHAN(5500, 100, 0),
243 HDD5GHZCHAN(5520, 104, 0),
244 HDD5GHZCHAN(5540, 108, 0),
245 HDD5GHZCHAN(5560, 112, 0),
246 HDD5GHZCHAN(5580, 116, 0),
247 HDD5GHZCHAN(5600, 120, 0),
248 HDD5GHZCHAN(5620, 124, 0),
249 HDD5GHZCHAN(5640, 128, 0),
250 HDD5GHZCHAN(5660, 132, 0),
251 HDD5GHZCHAN(5680, 136, 0),
252 HDD5GHZCHAN(5700, 140, 0),
253 HDD5GHZCHAN(5720, 144, 0),
254 HDD5GHZCHAN(5745, 149, 0),
255 HDD5GHZCHAN(5765, 153, 0),
256 HDD5GHZCHAN(5785, 157, 0),
257 HDD5GHZCHAN(5805, 161, 0),
258 HDD5GHZCHAN(5825, 165, 0),
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +0530259};
260
261static const struct ieee80211_channel hdd_channels_dot11p[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800262 HDD5GHZCHAN(5852, 170, 0),
263 HDD5GHZCHAN(5855, 171, 0),
264 HDD5GHZCHAN(5860, 172, 0),
265 HDD5GHZCHAN(5865, 173, 0),
266 HDD5GHZCHAN(5870, 174, 0),
267 HDD5GHZCHAN(5875, 175, 0),
268 HDD5GHZCHAN(5880, 176, 0),
269 HDD5GHZCHAN(5885, 177, 0),
270 HDD5GHZCHAN(5890, 178, 0),
271 HDD5GHZCHAN(5895, 179, 0),
272 HDD5GHZCHAN(5900, 180, 0),
273 HDD5GHZCHAN(5905, 181, 0),
274 HDD5GHZCHAN(5910, 182, 0),
275 HDD5GHZCHAN(5915, 183, 0),
276 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800277};
278
279static struct ieee80211_rate g_mode_rates[] = {
280 HDD_G_MODE_RATETAB(10, 0x1, 0),
281 HDD_G_MODE_RATETAB(20, 0x2, 0),
282 HDD_G_MODE_RATETAB(55, 0x4, 0),
283 HDD_G_MODE_RATETAB(110, 0x8, 0),
284 HDD_G_MODE_RATETAB(60, 0x10, 0),
285 HDD_G_MODE_RATETAB(90, 0x20, 0),
286 HDD_G_MODE_RATETAB(120, 0x40, 0),
287 HDD_G_MODE_RATETAB(180, 0x80, 0),
288 HDD_G_MODE_RATETAB(240, 0x100, 0),
289 HDD_G_MODE_RATETAB(360, 0x200, 0),
290 HDD_G_MODE_RATETAB(480, 0x400, 0),
291 HDD_G_MODE_RATETAB(540, 0x800, 0),
292};
293
294static struct ieee80211_rate a_mode_rates[] = {
295 HDD_G_MODE_RATETAB(60, 0x10, 0),
296 HDD_G_MODE_RATETAB(90, 0x20, 0),
297 HDD_G_MODE_RATETAB(120, 0x40, 0),
298 HDD_G_MODE_RATETAB(180, 0x80, 0),
299 HDD_G_MODE_RATETAB(240, 0x100, 0),
300 HDD_G_MODE_RATETAB(360, 0x200, 0),
301 HDD_G_MODE_RATETAB(480, 0x400, 0),
302 HDD_G_MODE_RATETAB(540, 0x800, 0),
303};
304
305static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530306 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800307 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -0700308 .band = HDD_NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800309 .bitrates = g_mode_rates,
310 .n_bitrates = g_mode_rates_size,
311 .ht_cap.ht_supported = 1,
312 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
313 | IEEE80211_HT_CAP_GRN_FLD
314 | IEEE80211_HT_CAP_DSSSCCK40
315 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
316 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
317 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
318 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
319 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
320 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
321 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
322};
323
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800324static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530325 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800326 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Srinivas Girigowda11c28e02017-06-27 20:06:21 -0700327 .band = HDD_NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800328 .bitrates = a_mode_rates,
329 .n_bitrates = a_mode_rates_size,
330 .ht_cap.ht_supported = 1,
331 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
332 | IEEE80211_HT_CAP_GRN_FLD
333 | IEEE80211_HT_CAP_DSSSCCK40
334 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
335 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
336 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
337 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
338 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
339 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
340 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
341 .vht_cap.vht_supported = 1,
342};
343
344/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800345 * TX/RX direction for each kind of interface
346 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800347static const struct ieee80211_txrx_stypes
348 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
349 [NL80211_IFTYPE_STATION] = {
350 .tx = 0xffff,
351 .rx = BIT(SIR_MAC_MGMT_ACTION) |
Padma, Santhosh Kumar1ccc1332017-09-13 17:39:01 +0530352 BIT(SIR_MAC_MGMT_PROBE_REQ) |
353 BIT(SIR_MAC_MGMT_AUTH),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800354 },
355 [NL80211_IFTYPE_AP] = {
356 .tx = 0xffff,
357 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
358 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
359 BIT(SIR_MAC_MGMT_PROBE_REQ) |
360 BIT(SIR_MAC_MGMT_DISASSOC) |
361 BIT(SIR_MAC_MGMT_AUTH) |
362 BIT(SIR_MAC_MGMT_DEAUTH) |
363 BIT(SIR_MAC_MGMT_ACTION),
364 },
365 [NL80211_IFTYPE_ADHOC] = {
366 .tx = 0xffff,
367 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
368 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
369 BIT(SIR_MAC_MGMT_PROBE_REQ) |
370 BIT(SIR_MAC_MGMT_DISASSOC) |
371 BIT(SIR_MAC_MGMT_AUTH) |
372 BIT(SIR_MAC_MGMT_DEAUTH) |
373 BIT(SIR_MAC_MGMT_ACTION),
374 },
375 [NL80211_IFTYPE_P2P_CLIENT] = {
376 .tx = 0xffff,
377 .rx = BIT(SIR_MAC_MGMT_ACTION) |
378 BIT(SIR_MAC_MGMT_PROBE_REQ),
379 },
380 [NL80211_IFTYPE_P2P_GO] = {
381 /* This is also same as for SoftAP */
382 .tx = 0xffff,
383 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
384 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
385 BIT(SIR_MAC_MGMT_PROBE_REQ) |
386 BIT(SIR_MAC_MGMT_DISASSOC) |
387 BIT(SIR_MAC_MGMT_AUTH) |
388 BIT(SIR_MAC_MGMT_DEAUTH) |
389 BIT(SIR_MAC_MGMT_ACTION),
390 },
391};
392
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800393/* Interface limits and combinations registered by the driver */
394
395/* STA ( + STA ) combination */
396static const struct ieee80211_iface_limit
397 wlan_hdd_sta_iface_limit[] = {
398 {
399 .max = 3, /* p2p0 is a STA as well */
400 .types = BIT(NL80211_IFTYPE_STATION),
401 },
402};
403
404/* ADHOC (IBSS) limit */
405static const struct ieee80211_iface_limit
406 wlan_hdd_adhoc_iface_limit[] = {
407 {
408 .max = 1,
409 .types = BIT(NL80211_IFTYPE_STATION),
410 },
411 {
412 .max = 1,
413 .types = BIT(NL80211_IFTYPE_ADHOC),
414 },
415};
416
417/* AP ( + AP ) combination */
418static const struct ieee80211_iface_limit
419 wlan_hdd_ap_iface_limit[] = {
420 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530421 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800422 .types = BIT(NL80211_IFTYPE_AP),
423 },
424};
425
426/* P2P limit */
427static const struct ieee80211_iface_limit
428 wlan_hdd_p2p_iface_limit[] = {
429 {
430 .max = 1,
431 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
432 },
433 {
434 .max = 1,
435 .types = BIT(NL80211_IFTYPE_P2P_GO),
436 },
437};
438
439static const struct ieee80211_iface_limit
440 wlan_hdd_sta_ap_iface_limit[] = {
441 {
442 /* We need 1 extra STA interface for OBSS scan when SAP starts
443 * with HT40 in STA+SAP concurrency mode
444 */
445 .max = (1 + SAP_MAX_OBSS_STA_CNT),
446 .types = BIT(NL80211_IFTYPE_STATION),
447 },
448 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530449 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800450 .types = BIT(NL80211_IFTYPE_AP),
451 },
452};
453
454/* STA + P2P combination */
455static const struct ieee80211_iface_limit
456 wlan_hdd_sta_p2p_iface_limit[] = {
457 {
458 /* One reserved for dedicated P2PDEV usage */
459 .max = 2,
460 .types = BIT(NL80211_IFTYPE_STATION)
461 },
462 {
463 /* Support for two identical (GO + GO or CLI + CLI)
464 * or dissimilar (GO + CLI) P2P interfaces
465 */
466 .max = 2,
467 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
468 },
469};
470
471/* STA + AP + P2PGO combination */
472static const struct ieee80211_iface_limit
473wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
474 /* Support for AP+P2PGO interfaces */
475 {
476 .max = 2,
477 .types = BIT(NL80211_IFTYPE_STATION)
478 },
479 {
480 .max = 1,
481 .types = BIT(NL80211_IFTYPE_P2P_GO)
482 },
483 {
484 .max = 1,
485 .types = BIT(NL80211_IFTYPE_AP)
486 }
487};
488
489/* SAP + P2P combination */
490static const struct ieee80211_iface_limit
491wlan_hdd_sap_p2p_iface_limit[] = {
492 {
493 /* 1 dedicated for p2p0 which is a STA type */
494 .max = 1,
495 .types = BIT(NL80211_IFTYPE_STATION)
496 },
497 {
498 /* The p2p interface in SAP+P2P can be GO/CLI.
499 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
500 */
501 .max = 1,
502 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
503 },
504 {
505 /* SAP+GO to support only one SAP interface */
506 .max = 1,
507 .types = BIT(NL80211_IFTYPE_AP)
508 }
509};
510
511/* P2P + P2P combination */
512static const struct ieee80211_iface_limit
513wlan_hdd_p2p_p2p_iface_limit[] = {
514 {
515 /* 1 dedicated for p2p0 which is a STA type */
516 .max = 1,
517 .types = BIT(NL80211_IFTYPE_STATION)
518 },
519 {
520 /* The p2p interface in P2P+P2P can be GO/CLI.
521 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
522 */
523 .max = 2,
524 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
525 },
526};
527
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700528static const struct ieee80211_iface_limit
529 wlan_hdd_mon_iface_limit[] = {
530 {
531 .max = 3, /* Monitor interface */
532 .types = BIT(NL80211_IFTYPE_MONITOR),
533 },
534};
535
536static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800537 wlan_hdd_iface_combination[] = {
538 /* STA */
539 {
540 .limits = wlan_hdd_sta_iface_limit,
541 .num_different_channels = 2,
542 .max_interfaces = 3,
543 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
544 },
545 /* ADHOC */
546 {
547 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700548 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800549 .max_interfaces = 2,
550 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
551 },
552 /* AP */
553 {
554 .limits = wlan_hdd_ap_iface_limit,
555 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530556 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800557 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
hqu3c4ed3d2017-09-19 11:42:35 +0800558#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) || \
559 defined(CFG80211_BEACON_INTERVAL_BACKPORT)
560 .beacon_int_min_gcd = 1,
561#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800562 },
563 /* P2P */
564 {
565 .limits = wlan_hdd_p2p_iface_limit,
566 .num_different_channels = 2,
567 .max_interfaces = 2,
568 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
569 },
570 /* STA + AP */
571 {
572 .limits = wlan_hdd_sta_ap_iface_limit,
573 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530574 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800575 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
576 .beacon_int_infra_match = true,
hqu3c4ed3d2017-09-19 11:42:35 +0800577#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) || \
578 defined(CFG80211_BEACON_INTERVAL_BACKPORT)
579 .beacon_int_min_gcd = 1,
580#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800581 },
582 /* STA + P2P */
583 {
584 .limits = wlan_hdd_sta_p2p_iface_limit,
585 .num_different_channels = 2,
586 /* one interface reserved for P2PDEV dedicated usage */
587 .max_interfaces = 4,
588 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
589 .beacon_int_infra_match = true,
590 },
591 /* STA + P2P GO + SAP */
592 {
593 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
594 /* we can allow 3 channels for three different persona
595 * but due to firmware limitation, allow max 2 concrnt channels.
596 */
597 .num_different_channels = 2,
598 /* one interface reserved for P2PDEV dedicated usage */
599 .max_interfaces = 4,
600 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
601 .beacon_int_infra_match = true,
602 },
603 /* SAP + P2P */
604 {
605 .limits = wlan_hdd_sap_p2p_iface_limit,
606 .num_different_channels = 2,
607 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
608 .max_interfaces = 3,
609 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
610 .beacon_int_infra_match = true,
611 },
612 /* P2P + P2P */
613 {
614 .limits = wlan_hdd_p2p_p2p_iface_limit,
615 .num_different_channels = 2,
616 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
617 .max_interfaces = 3,
618 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
619 .beacon_int_infra_match = true,
620 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530621 /* Monitor */
622 {
623 .limits = wlan_hdd_mon_iface_limit,
624 .max_interfaces = 3,
625 .num_different_channels = 2,
626 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
627 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800628};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800629
630static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800631
632#ifdef WLAN_NL80211_TESTMODE
633enum wlan_hdd_tm_attr {
634 WLAN_HDD_TM_ATTR_INVALID = 0,
635 WLAN_HDD_TM_ATTR_CMD = 1,
636 WLAN_HDD_TM_ATTR_DATA = 2,
637 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
638 WLAN_HDD_TM_ATTR_TYPE = 4,
639 /* keep last */
640 WLAN_HDD_TM_ATTR_AFTER_LAST,
641 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
642};
643
644enum wlan_hdd_tm_cmd {
645 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
646 WLAN_HDD_TM_CMD_WLAN_HB = 1,
647};
648
649#define WLAN_HDD_TM_DATA_MAX_LEN 5000
650
651static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
652 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
653 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
654 .len = WLAN_HDD_TM_DATA_MAX_LEN},
655};
656#endif /* WLAN_NL80211_TESTMODE */
657
Lin Baia016e9a2017-08-29 19:10:42 +0800658enum wlan_hdd_vendor_ie_access_policy {
659 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
660 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
661};
662
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800663#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
664static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
665 .flags = WIPHY_WOWLAN_MAGIC_PKT,
666 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
667 .pattern_min_len = 1,
668 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
669};
670#endif
671
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800672/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530673 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
674 * @flags: Pointer to the flags to Add channel switch flag.
675 *
676 * This Function adds Channel Switch support flag, if channel switch is
677 * supported by kernel.
678 * Return: void.
679 */
680#ifdef CHANNEL_SWITCH_SUPPORTED
681static inline void hdd_add_channel_switch_support(uint32_t *flags)
682{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800683 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530684}
685#else
686static inline void hdd_add_channel_switch_support(uint32_t *flags)
687{
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530688}
689#endif
690
Manikandan Mohan22b83722015-12-15 15:03:23 -0800691#ifdef FEATURE_WLAN_TDLS
692
693/* TDLS capabilities params */
694#define PARAM_MAX_TDLS_SESSION \
695 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
696#define PARAM_TDLS_FEATURE_SUPPORT \
697 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
698
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530699/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800700 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
701 * @wiphy: WIPHY structure pointer
702 * @wdev: Wireless device structure pointer
703 * @data: Pointer to the data received
704 * @data_len: Length of the data received
705 *
706 * This function provides TDLS capabilities
707 *
708 * Return: 0 on success and errno on failure
709 */
710static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
711 struct wireless_dev *wdev,
712 const void *data,
713 int data_len)
714{
715 int status;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -0700716 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800717 struct sk_buff *skb;
718 uint32_t set = 0;
Frank Liu5c63dc82017-09-07 14:49:05 +0800719 uint32_t max_num_tdls_sta = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800720
Dustin Brownfdf17c12018-03-14 12:55:34 -0700721 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -0800722
Anurag Chouhan6d760662016-02-20 16:05:43 +0530723 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800724 hdd_err("Command not allowed in FTM mode");
725 return -EPERM;
726 }
727
728 status = wlan_hdd_validate_context(hdd_ctx);
729 if (status)
730 return status;
731
732 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
733 NLMSG_HDRLEN);
734 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700735 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800736 goto fail;
737 }
738
739 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800740 hdd_debug("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800741 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
742 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700743 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800744 goto fail;
745 }
746 } else {
747 set = set | WIFI_TDLS_SUPPORT;
748 set = set | (hdd_ctx->config->fTDLSExternalControl ?
749 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
750 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
751 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Frank Liu5c63dc82017-09-07 14:49:05 +0800752 if (hdd_ctx->config->fEnableTDLSSleepSta ||
753 hdd_ctx->config->fEnableTDLSBufferSta ||
754 hdd_ctx->config->fEnableTDLSOffChannel)
755 max_num_tdls_sta = HDD_MAX_NUM_TDLS_STA_P_UAPSD_OFFCHAN;
756 else
757 max_num_tdls_sta = HDD_MAX_NUM_TDLS_STA;
758
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800759 hdd_debug("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800760 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
Frank Liu5c63dc82017-09-07 14:49:05 +0800761 max_num_tdls_sta) ||
762 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700763 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800764 goto fail;
765 }
766 }
767 return cfg80211_vendor_cmd_reply(skb);
768fail:
769 if (skb)
770 kfree_skb(skb);
771 return -EINVAL;
772}
773
774/**
775 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
776 * @wiphy: WIPHY structure pointer
777 * @wdev: Wireless device structure pointer
778 * @data: Pointer to the data received
779 * @data_len: Length of the data received
780 *
781 * This function provides TDLS capabilities
782 *
783 * Return: 0 on success and errno on failure
784 */
785static int
786wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
787 struct wireless_dev *wdev,
788 const void *data,
789 int data_len)
790{
791 int ret;
792
793 cds_ssr_protect(__func__);
794 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
795 data, data_len);
796 cds_ssr_unprotect(__func__);
797
798 return ret;
799}
800#endif
801
802#ifdef QCA_HT_2040_COEX
803static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
804#endif
805
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700806int wlan_hdd_merge_avoid_freqs(struct ch_avoid_ind_type *destFreqList,
807 struct ch_avoid_ind_type *srcFreqList)
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530808{
809 int i;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700810 struct ch_avoid_freq_type *avoid_range =
811 &destFreqList->avoid_freq_range[destFreqList->ch_avoid_range_cnt];
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530812
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700813 destFreqList->ch_avoid_range_cnt += srcFreqList->ch_avoid_range_cnt;
Jeff Johnson31304cc2017-09-30 19:08:09 -0700814 if (destFreqList->ch_avoid_range_cnt > CH_AVOID_MAX_RANGE) {
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530815 hdd_err("avoid freq overflow");
816 return -EINVAL;
817 }
818
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700819 for (i = 0; i < srcFreqList->ch_avoid_range_cnt; i++) {
820 avoid_range->start_freq =
821 srcFreqList->avoid_freq_range[i].start_freq;
822 avoid_range->end_freq =
823 srcFreqList->avoid_freq_range[i].end_freq;
824 avoid_range++;
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +0530825 }
826 return 0;
827}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800828/*
829 * FUNCTION: wlan_hdd_send_avoid_freq_event
830 * This is called when wlan driver needs to send vendor specific
831 * avoid frequency range event to userspace
832 */
Jeff Johnsonb8944722017-09-03 09:03:19 -0700833int wlan_hdd_send_avoid_freq_event(struct hdd_context *hdd_ctx,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700834 struct ch_avoid_ind_type *avoid_freq_list)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800835{
836 struct sk_buff *vendor_event;
837
Dustin Brown491d54b2018-03-14 12:39:11 -0700838 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800839
Jeff Johnsonb8944722017-09-03 09:03:19 -0700840 if (!hdd_ctx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700841 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800842 return -EINVAL;
843 }
844
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700845 if (!avoid_freq_list) {
846 hdd_err("avoid_freq_list is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800847 return -EINVAL;
848 }
849
Jeff Johnsonb8944722017-09-03 09:03:19 -0700850 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700851 NULL, sizeof(struct ch_avoid_ind_type),
852 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
853 GFP_KERNEL);
854
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800855 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700856 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800857 return -EINVAL;
858 }
859
Kiran Kumar Lokere48795792017-07-07 15:34:29 -0700860 memcpy(skb_put(vendor_event, sizeof(struct ch_avoid_ind_type)),
861 (void *)avoid_freq_list, sizeof(struct ch_avoid_ind_type));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800862
863 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
864
Dustin Browne74003f2018-03-14 12:51:58 -0700865 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800866 return 0;
867}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800868
Anurag Chouhan4085ff72017-10-05 18:09:56 +0530869/*
870 * define short names for the global vendor params
871 * used by QCA_NL80211_VENDOR_SUBCMD_HANG
872 */
873#define HANG_REASON_INDEX QCA_NL80211_VENDOR_SUBCMD_HANG_REASON_INDEX
874
875/**
876 * hdd_convert_hang_reason() - Convert cds recovery reason to vendor specific
877 * hang reason
878 * @reason: cds recovery reason
879 *
880 * Return: Vendor specific reason code
881 */
882static enum qca_wlan_vendor_hang_reason
883hdd_convert_hang_reason(enum qdf_hang_reason reason)
884{
Mahesh Kumar Kalikot Veetil9111a572017-10-10 16:11:11 -0700885 u32 ret_val;
Anurag Chouhan4085ff72017-10-05 18:09:56 +0530886
887 switch (reason) {
888 case QDF_RX_HASH_NO_ENTRY_FOUND:
889 ret_val = QCA_WLAN_HANG_RX_HASH_NO_ENTRY_FOUND;
890 break;
891 case QDF_PEER_DELETION_TIMEDOUT:
892 ret_val = QCA_WLAN_HANG_PEER_DELETION_TIMEDOUT;
893 break;
894 case QDF_PEER_UNMAP_TIMEDOUT:
895 ret_val = QCA_WLAN_HANG_PEER_UNMAP_TIMEDOUT;
896 break;
897 case QDF_SCAN_REQ_EXPIRED:
898 ret_val = QCA_WLAN_HANG_SCAN_REQ_EXPIRED;
899 break;
900 case QDF_SCAN_ATTEMPT_FAILURES:
901 ret_val = QCA_WLAN_HANG_SCAN_ATTEMPT_FAILURES;
902 break;
903 case QDF_GET_MSG_BUFF_FAILURE:
904 ret_val = QCA_WLAN_HANG_GET_MSG_BUFF_FAILURE;
905 break;
906 case QDF_ACTIVE_LIST_TIMEOUT:
907 ret_val = QCA_WLAN_HANG_ACTIVE_LIST_TIMEOUT;
908 break;
909 case QDF_SUSPEND_TIMEOUT:
910 ret_val = QCA_WLAN_HANG_SUSPEND_TIMEOUT;
911 break;
912 case QDF_RESUME_TIMEOUT:
913 ret_val = QCA_WLAN_HANG_RESUME_TIMEOUT;
914 break;
915 case QDF_REASON_UNSPECIFIED:
916 default:
917 ret_val = QCA_WLAN_HANG_REASON_UNSPECIFIED;
918 }
919 return ret_val;
920}
921
922/**
923 * wlan_hdd_send_hang_reason_event() - Send hang reason to the userspace
924 * @hdd_ctx: Pointer to hdd context
925 * @reason: cds recovery reason
926 *
927 * Return: 0 on success or failure reason
928 */
929int wlan_hdd_send_hang_reason_event(struct hdd_context *hdd_ctx,
930 enum qdf_hang_reason reason)
931{
932 struct sk_buff *vendor_event;
933 enum qca_wlan_vendor_hang_reason hang_reason;
934
Dustin Brown491d54b2018-03-14 12:39:11 -0700935 hdd_enter();
Anurag Chouhan4085ff72017-10-05 18:09:56 +0530936
937 if (!hdd_ctx) {
938 hdd_err("HDD context is null");
939 return -EINVAL;
940 }
941
942 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
943 NULL,
944 sizeof(uint32_t),
945 HANG_REASON_INDEX,
946 GFP_KERNEL);
947 if (!vendor_event) {
948 hdd_err("cfg80211_vendor_event_alloc failed");
949 return -ENOMEM;
950 }
951
952 hang_reason = hdd_convert_hang_reason(reason);
953
954 if (nla_put_u32(vendor_event, QCA_WLAN_VENDOR_ATTR_HANG_REASON,
Mahesh Kumar Kalikot Veetil9111a572017-10-10 16:11:11 -0700955 (uint32_t)hang_reason)) {
Anurag Chouhan4085ff72017-10-05 18:09:56 +0530956 hdd_err("QCA_WLAN_VENDOR_ATTR_HANG_REASON put fail");
957 kfree_skb(vendor_event);
958 return -EINVAL;
959 }
960
961 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
962
Dustin Browne74003f2018-03-14 12:51:58 -0700963 hdd_exit();
Anurag Chouhan4085ff72017-10-05 18:09:56 +0530964 return 0;
965}
Mahesh Kumar Kalikot Veetil9111a572017-10-10 16:11:11 -0700966
Anurag Chouhan4085ff72017-10-05 18:09:56 +0530967#undef HANG_REASON_INDEX
968
Ajit Pal Singh5edd6982017-05-10 11:04:13 +0530969/**
970 * wlan_hdd_get_adjacent_chan(): Gets next/previous channel
971 * with respect to the channel passed.
972 * @chan: Channel
973 * @upper: If "true" then next channel is returned or else
974 * previous channel is returned.
975 *
976 * This function returns the next/previous adjacent-channel to
977 * the channel passed. If "upper = true" then next channel is
978 * returned else previous is returned.
979 */
980int wlan_hdd_get_adjacent_chan(uint8_t chan, bool upper)
981{
982 enum channel_enum ch_idx = reg_get_chan_enum(chan);
983
984 if (ch_idx == INVALID_CHANNEL)
985 return -EINVAL;
986
987 if (upper && (ch_idx < (NUM_CHANNELS - 1)))
988 ch_idx++;
989 else if (!upper && (ch_idx > CHAN_ENUM_1))
990 ch_idx--;
991 else
992 return -EINVAL;
993
994 return WLAN_REG_CH_NUM(ch_idx);
995}
996
997/**
998 * wlan_hdd_send_avoid_freq_for_dnbs(): Sends list of frequencies to be
999 * avoided when Do_Not_Break_Stream is active.
Jeff Johnsonb8944722017-09-03 09:03:19 -07001000 * @hdd_ctx: HDD Context
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301001 * @op_chan: AP/P2P-GO operating channel
1002 *
1003 * This function sends list of frequencies to be avoided when
1004 * Do_Not_Break_Stream is active.
1005 * To clear the avoid_frequency_list in the application,
1006 * op_chan = 0 can be passed.
1007 *
1008 * Return: 0 on success and errno on failure
1009 */
Jeff Johnsonb8944722017-09-03 09:03:19 -07001010int wlan_hdd_send_avoid_freq_for_dnbs(struct hdd_context *hdd_ctx, uint8_t op_chan)
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301011{
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001012 struct ch_avoid_ind_type p2p_avoid_freq_list;
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301013 uint8_t min_chan, max_chan;
1014 int ret;
1015 int chan;
1016
Dustin Brown491d54b2018-03-14 12:39:11 -07001017 hdd_enter();
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301018
Jeff Johnsonb8944722017-09-03 09:03:19 -07001019 if (!hdd_ctx) {
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301020 hdd_err("invalid param");
1021 return -EINVAL;
1022 }
1023
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001024 qdf_mem_zero(&p2p_avoid_freq_list, sizeof(struct ch_avoid_ind_type));
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301025 /*
1026 * If channel passed is zero, clear the avoid_freq list in application.
1027 */
1028 if (!op_chan) {
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301029#ifdef FEATURE_WLAN_CH_AVOID
Jeff Johnsonb8944722017-09-03 09:03:19 -07001030 mutex_lock(&hdd_ctx->avoid_freq_lock);
1031 qdf_mem_zero(&hdd_ctx->dnbs_avoid_freq_list,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001032 sizeof(struct ch_avoid_ind_type));
Jeff Johnsonb8944722017-09-03 09:03:19 -07001033 if (hdd_ctx->coex_avoid_freq_list.ch_avoid_range_cnt)
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301034 memcpy(&p2p_avoid_freq_list,
Jeff Johnsonb8944722017-09-03 09:03:19 -07001035 &hdd_ctx->coex_avoid_freq_list,
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001036 sizeof(struct ch_avoid_ind_type));
Jeff Johnsonb8944722017-09-03 09:03:19 -07001037 mutex_unlock(&hdd_ctx->avoid_freq_lock);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301038#endif
Jeff Johnsonb8944722017-09-03 09:03:19 -07001039 ret = wlan_hdd_send_avoid_freq_event(hdd_ctx,
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301040 &p2p_avoid_freq_list);
1041 if (ret)
1042 hdd_err("wlan_hdd_send_avoid_freq_event error:%d",
1043 ret);
1044
1045 return ret;
1046 }
1047
1048 if (WLAN_REG_IS_24GHZ_CH(op_chan)) {
1049 min_chan = REG_MIN_24GHZ_CH_NUM;
1050 max_chan = REG_MAX_24GHZ_CH_NUM;
1051 } else if WLAN_REG_IS_5GHZ_CH(op_chan) {
1052 min_chan = REG_MIN_5GHZ_CH_NUM;
1053 max_chan = REG_MAX_5GHZ_CH_NUM;
1054 } else {
1055 hdd_err("invalid channel:%d", op_chan);
1056 return -EINVAL;
1057 }
1058
1059 if ((op_chan > min_chan) && (op_chan < max_chan)) {
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001060 p2p_avoid_freq_list.ch_avoid_range_cnt = 2;
1061 p2p_avoid_freq_list.avoid_freq_range[0].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301062 wlan_chan_to_freq(min_chan);
1063
1064 /* Get channel before the op_chan */
1065 chan = wlan_hdd_get_adjacent_chan(op_chan, false);
1066 if (chan < 0)
1067 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001068 p2p_avoid_freq_list.avoid_freq_range[0].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301069 wlan_chan_to_freq(chan);
1070
1071 /* Get channel next to the op_chan */
1072 chan = wlan_hdd_get_adjacent_chan(op_chan, true);
1073 if (chan < 0)
1074 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001075 p2p_avoid_freq_list.avoid_freq_range[1].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301076 wlan_chan_to_freq(chan);
1077
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001078 p2p_avoid_freq_list.avoid_freq_range[1].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301079 wlan_chan_to_freq(max_chan);
1080 } else if (op_chan == min_chan) {
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001081 p2p_avoid_freq_list.ch_avoid_range_cnt = 1;
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301082
1083 chan = wlan_hdd_get_adjacent_chan(op_chan, true);
1084 if (chan < 0)
1085 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001086 p2p_avoid_freq_list.avoid_freq_range[0].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301087 wlan_chan_to_freq(chan);
1088
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001089 p2p_avoid_freq_list.avoid_freq_range[0].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301090 wlan_chan_to_freq(max_chan);
1091 } else {
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001092 p2p_avoid_freq_list.ch_avoid_range_cnt = 1;
1093 p2p_avoid_freq_list.avoid_freq_range[0].start_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301094 wlan_chan_to_freq(min_chan);
1095
1096 chan = wlan_hdd_get_adjacent_chan(op_chan, false);
1097 if (chan < 0)
1098 return -EINVAL;
Kiran Kumar Lokere48795792017-07-07 15:34:29 -07001099 p2p_avoid_freq_list.avoid_freq_range[0].end_freq =
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301100 wlan_chan_to_freq(chan);
1101 }
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301102#ifdef FEATURE_WLAN_CH_AVOID
Jeff Johnsonb8944722017-09-03 09:03:19 -07001103 mutex_lock(&hdd_ctx->avoid_freq_lock);
1104 hdd_ctx->dnbs_avoid_freq_list = p2p_avoid_freq_list;
1105 if (hdd_ctx->coex_avoid_freq_list.ch_avoid_range_cnt) {
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301106 ret = wlan_hdd_merge_avoid_freqs(&p2p_avoid_freq_list,
Jeff Johnsonb8944722017-09-03 09:03:19 -07001107 &hdd_ctx->coex_avoid_freq_list);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301108 if (ret) {
Jeff Johnsonb8944722017-09-03 09:03:19 -07001109 mutex_unlock(&hdd_ctx->avoid_freq_lock);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301110 hdd_err("avoid freq merge failed");
1111 return ret;
1112 }
1113 }
Jeff Johnsonb8944722017-09-03 09:03:19 -07001114 mutex_unlock(&hdd_ctx->avoid_freq_lock);
Ajit Pal Singh2c7aecd2017-05-19 15:09:23 +05301115#endif
Jeff Johnsonb8944722017-09-03 09:03:19 -07001116 ret = wlan_hdd_send_avoid_freq_event(hdd_ctx, &p2p_avoid_freq_list);
Ajit Pal Singh5edd6982017-05-10 11:04:13 +05301117 if (ret)
1118 hdd_err("wlan_hdd_send_avoid_freq_event error:%d", ret);
1119
1120 return ret;
1121}
1122
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001123/* vendor specific events */
1124static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001125 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
1126 .vendor_id =
1127 QCA_NL80211_VENDOR_ID,
1128 .subcmd =
1129 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
1130 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001131
1132#ifdef WLAN_FEATURE_NAN
1133 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
1134 .vendor_id =
1135 QCA_NL80211_VENDOR_ID,
1136 .subcmd =
1137 QCA_NL80211_VENDOR_SUBCMD_NAN
1138 },
1139#endif
1140
1141#ifdef WLAN_FEATURE_STATS_EXT
1142 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
1143 .vendor_id =
1144 QCA_NL80211_VENDOR_ID,
1145 .subcmd =
1146 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
1147 },
1148#endif /* WLAN_FEATURE_STATS_EXT */
1149#ifdef FEATURE_WLAN_EXTSCAN
1150 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
1151 .vendor_id =
1152 QCA_NL80211_VENDOR_ID,
1153 .subcmd =
1154 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
1155 },
1156 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
1157 .vendor_id =
1158 QCA_NL80211_VENDOR_ID,
1159 .subcmd =
1160 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
1161 },
1162 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
1163 .
1164 vendor_id
1165 =
1166 QCA_NL80211_VENDOR_ID,
1167 .subcmd =
1168 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
1169 },
1170 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
1171 .
1172 vendor_id
1173 =
1174 QCA_NL80211_VENDOR_ID,
1175 .
1176 subcmd =
1177 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
1178 },
1179 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
1180 .
1181 vendor_id
1182 =
1183 QCA_NL80211_VENDOR_ID,
1184 .
1185 subcmd
1186 =
1187 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
1188 },
1189 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
1190 .
1191 vendor_id
1192 =
1193 QCA_NL80211_VENDOR_ID,
1194 .subcmd =
1195 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
1196 },
1197 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
1198 .vendor_id =
1199 QCA_NL80211_VENDOR_ID,
1200 .subcmd =
1201 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
1202 },
1203 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
1204 .
1205 vendor_id
1206 =
1207 QCA_NL80211_VENDOR_ID,
1208 .subcmd =
1209 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
1210 },
1211 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
1212 .
1213 vendor_id
1214 =
1215 QCA_NL80211_VENDOR_ID,
1216 .subcmd =
1217 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
1218 },
1219 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
1220 .
1221 vendor_id
1222 =
1223 QCA_NL80211_VENDOR_ID,
1224 .
1225 subcmd
1226 =
1227 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
1228 },
1229 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
1230 .
1231 vendor_id
1232 =
1233 QCA_NL80211_VENDOR_ID,
1234 .
1235 subcmd =
1236 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
1237 },
1238 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
1239 .
1240 vendor_id
1241 =
1242 QCA_NL80211_VENDOR_ID,
1243 .
1244 subcmd
1245 =
1246 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
1247 },
1248 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
1249 .
1250 vendor_id
1251 =
1252 QCA_NL80211_VENDOR_ID,
1253 .
1254 subcmd
1255 =
1256 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
1257 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001258#endif /* FEATURE_WLAN_EXTSCAN */
1259
1260#ifdef WLAN_FEATURE_LINK_LAYER_STATS
1261 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
1262 .vendor_id =
1263 QCA_NL80211_VENDOR_ID,
1264 .subcmd =
1265 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
1266 },
1267 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
1268 .vendor_id =
1269 QCA_NL80211_VENDOR_ID,
1270 .subcmd =
1271 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
1272 },
1273 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
1274 .vendor_id =
1275 QCA_NL80211_VENDOR_ID,
1276 .subcmd =
1277 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
1278 },
1279 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
1280 .vendor_id =
1281 QCA_NL80211_VENDOR_ID,
1282 .subcmd =
1283 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
1284 },
1285 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
1286 .vendor_id =
1287 QCA_NL80211_VENDOR_ID,
1288 .subcmd =
1289 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
1290 },
1291 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
1292 .vendor_id =
1293 QCA_NL80211_VENDOR_ID,
1294 .subcmd =
1295 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
1296 },
Zhang Qianca38fb12016-12-23 11:10:48 +08001297 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX] = {
1298 .vendor_id =
1299 QCA_NL80211_VENDOR_ID,
1300 .subcmd =
1301 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT
1302 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001303#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
1304 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
1305 .vendor_id =
1306 QCA_NL80211_VENDOR_ID,
1307 .subcmd =
1308 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
1309 },
1310 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
1311 .vendor_id = QCA_NL80211_VENDOR_ID,
1312 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
1313 },
1314#ifdef WLAN_FEATURE_ROAM_OFFLOAD
1315 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
1316 .vendor_id =
1317 QCA_NL80211_VENDOR_ID,
1318 .subcmd =
1319 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1320 },
1321#endif
1322 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1323 .vendor_id =
1324 QCA_NL80211_VENDOR_ID,
1325 .subcmd =
1326 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1327 },
1328 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1329 .vendor_id =
1330 QCA_NL80211_VENDOR_ID,
1331 .subcmd =
1332 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1333 },
1334 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1335 .vendor_id =
1336 QCA_NL80211_VENDOR_ID,
1337 .subcmd =
1338 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1339 },
1340 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1341 .vendor_id =
1342 QCA_NL80211_VENDOR_ID,
1343 .subcmd =
1344 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1345 },
1346 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1347 .vendor_id =
1348 QCA_NL80211_VENDOR_ID,
1349 .subcmd =
1350 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1351 },
1352#ifdef FEATURE_WLAN_EXTSCAN
1353 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1354 .vendor_id = QCA_NL80211_VENDOR_ID,
1355 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1356 },
1357 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1358 .vendor_id = QCA_NL80211_VENDOR_ID,
1359 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1360 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001361 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1362 .vendor_id = QCA_NL80211_VENDOR_ID,
1363 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1364 },
1365#endif /* FEATURE_WLAN_EXTSCAN */
1366 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1367 .vendor_id = QCA_NL80211_VENDOR_ID,
1368 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1369 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001370#ifdef WLAN_FEATURE_TSF
1371 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1372 .vendor_id = QCA_NL80211_VENDOR_ID,
1373 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1374 },
1375#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001376 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1377 .vendor_id = QCA_NL80211_VENDOR_ID,
1378 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1379 },
1380 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1381 .vendor_id = QCA_NL80211_VENDOR_ID,
1382 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1383 },
1384 /* OCB events */
1385 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1386 .vendor_id = QCA_NL80211_VENDOR_ID,
1387 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1388 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001389#ifdef FEATURE_LFR_SUBNET_DETECTION
1390 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1391 .vendor_id = QCA_NL80211_VENDOR_ID,
1392 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1393 },
1394#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001395
1396#ifdef WLAN_FEATURE_NAN_DATAPATH
1397 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1398 .vendor_id = QCA_NL80211_VENDOR_ID,
1399 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1400 },
1401#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001402
1403 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1404 .vendor_id = QCA_NL80211_VENDOR_ID,
1405 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1406 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301407 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1408 .vendor_id = QCA_NL80211_VENDOR_ID,
1409 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1410 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301411 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1412 .vendor_id = QCA_NL80211_VENDOR_ID,
1413 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1414 },
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05301415 [QCA_NL80211_VENDOR_SUBCMD_PWR_SAVE_FAIL_DETECTED_INDEX] = {
1416 .vendor_id = QCA_NL80211_VENDOR_ID,
1417 .subcmd = QCA_NL80211_VENDOR_SUBCMD_CHIP_PWRSAVE_FAILURE
Anurag Chouhan3920c0f2017-09-11 17:10:56 +05301418 },
1419 [QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET_INDEX] = {
1420 .vendor_id = QCA_NL80211_VENDOR_ID,
1421 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET,
1422 },
Anurag Chouhan4085ff72017-10-05 18:09:56 +05301423 [QCA_NL80211_VENDOR_SUBCMD_HANG_REASON_INDEX] = {
1424 .vendor_id = QCA_NL80211_VENDOR_ID,
1425 .subcmd = QCA_NL80211_VENDOR_SUBCMD_HANG,
1426 },
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +05301427 [QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO_INDEX] = {
1428 .vendor_id = QCA_NL80211_VENDOR_ID,
1429 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO,
1430 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001431#ifdef WLAN_UMAC_CONVERGENCE
1432 COMMON_VENDOR_EVENTS
1433#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001434};
1435
1436/**
1437 * __is_driver_dfs_capable() - get driver DFS capability
1438 * @wiphy: pointer to wireless wiphy structure.
1439 * @wdev: pointer to wireless_dev structure.
1440 * @data: Pointer to the data to be passed via vendor interface
1441 * @data_len:Length of the data to be passed
1442 *
1443 * This function is called by userspace to indicate whether or not
1444 * the driver supports DFS offload.
1445 *
1446 * Return: 0 on success, negative errno on failure
1447 */
1448static int __is_driver_dfs_capable(struct wiphy *wiphy,
1449 struct wireless_dev *wdev,
1450 const void *data,
1451 int data_len)
1452{
1453 u32 dfs_capability = 0;
1454 struct sk_buff *temp_skbuff;
1455 int ret_val;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07001456 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001457
Dustin Brownfdf17c12018-03-14 12:55:34 -07001458 hdd_enter_dev(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001459
1460 ret_val = wlan_hdd_validate_context(hdd_ctx);
1461 if (ret_val)
1462 return ret_val;
1463
Anurag Chouhan6d760662016-02-20 16:05:43 +05301464 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001465 hdd_err("Command not allowed in FTM mode");
1466 return -EPERM;
1467 }
1468
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001469 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001470
1471 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1472 NLMSG_HDRLEN);
1473
1474 if (temp_skbuff != NULL) {
1475 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1476 dfs_capability);
1477 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001478 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001479 kfree_skb(temp_skbuff);
1480
1481 return ret_val;
1482 }
1483
1484 return cfg80211_vendor_cmd_reply(temp_skbuff);
1485 }
1486
Jeff Johnson020db452016-06-29 14:37:26 -07001487 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001488 return -ENOMEM;
1489}
1490
1491/**
1492 * is_driver_dfs_capable() - get driver DFS capability
1493 * @wiphy: pointer to wireless wiphy structure.
1494 * @wdev: pointer to wireless_dev structure.
1495 * @data: Pointer to the data to be passed via vendor interface
1496 * @data_len:Length of the data to be passed
1497 *
1498 * This function is called by userspace to indicate whether or not
1499 * the driver supports DFS offload. This is an SSR-protected
1500 * wrapper function.
1501 *
1502 * Return: 0 on success, negative errno on failure
1503 */
1504static int is_driver_dfs_capable(struct wiphy *wiphy,
1505 struct wireless_dev *wdev,
1506 const void *data,
1507 int data_len)
1508{
1509 int ret;
1510
1511 cds_ssr_protect(__func__);
1512 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1513 cds_ssr_unprotect(__func__);
1514
1515 return ret;
1516}
1517
1518/**
1519 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1520 *
1521 * @adapter: SAP adapter pointer
1522 *
1523 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1524 * radio. So in case of DFS MCC scenario override current SAP given config
1525 * to follow concurrent SAP DFS config
1526 *
1527 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1528 */
Jeff Johnsone5006672017-08-29 14:39:02 -07001529int wlan_hdd_sap_cfg_dfs_override(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001530{
Jeff Johnsone5006672017-08-29 14:39:02 -07001531 struct hdd_adapter *con_sap_adapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001532 tsap_Config_t *sap_config, *con_sap_config;
1533 int con_ch;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07001534 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001535
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001536 if (!hdd_ctx) {
1537 hdd_err("hdd context is NULL");
1538 return 0;
1539 }
1540
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001541 /*
1542 * Check if AP+AP case, once primary AP chooses a DFS
1543 * channel secondary AP should always follow primary APs channel
1544 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001545 if (!policy_mgr_concurrent_beaconing_sessions_running(
1546 hdd_ctx->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001547 return 0;
1548
1549 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1550 if (!con_sap_adapter)
1551 return 0;
1552
Jeff Johnsonb9424862017-10-30 08:49:35 -07001553 sap_config = &adapter->session.ap.sap_config;
1554 con_sap_config = &con_sap_adapter->session.ap.sap_config;
1555 con_ch = con_sap_adapter->session.ap.operating_channel;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001556
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001557 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, con_ch))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001558 return 0;
1559
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001560 hdd_debug("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001561 sap_config->channel, con_ch);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001562 hdd_debug("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001563 sap_config->channel = con_ch;
1564
1565 if (con_sap_config->acs_cfg.acs_mode == true) {
1566 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1567 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001568 hdd_err("Primary AP channel config error");
1569 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001570 con_ch, con_sap_config->acs_cfg.pri_ch,
1571 con_sap_config->acs_cfg.ht_sec_ch);
1572 return -EINVAL;
1573 }
1574 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1575 * MCC restriction. So free ch list allocated in do_acs
1576 * func for Sec AP and realloc for Pri AP ch list size
1577 */
1578 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301579 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001580
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301581 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001582 &con_sap_config->acs_cfg,
1583 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301584 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001585 sizeof(uint8_t) *
1586 con_sap_config->acs_cfg.ch_list_count);
1587 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001588 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001589 return -ENOMEM;
1590 }
1591
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301592 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001593 con_sap_config->acs_cfg.ch_list,
1594 con_sap_config->acs_cfg.ch_list_count);
1595
1596 } else {
1597 sap_config->acs_cfg.pri_ch = con_ch;
1598 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1599 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1600 }
1601
1602 return con_ch;
1603}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001604
1605/**
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05301606 * wlan_hdd_reset_force_acs_chan_range: Set acs channel ranges as per force ACS
1607 * configuration.
1608 * @hdd_ctx: pointer to hdd context
1609 * @sap_config: pointer to SAP config struct
1610 *
1611 * Return: 0 if success else error code
1612 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07001613static int wlan_hdd_reset_force_acs_chan_range(struct hdd_context *hdd_ctx,
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05301614 tsap_Config_t *sap_config)
1615{
1616 bool is_dfs_mode_enabled = false;
1617 uint32_t i, num_channels = 0;
1618 uint8_t channels[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05301619 eCsrPhyMode hw_mode;
1620 tSirMacHTChannelWidth ch_width;
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05301621
1622 if (hdd_ctx->config->force_sap_acs_st_ch >
1623 hdd_ctx->config->force_sap_acs_end_ch) {
1624 hdd_err("invalid configuration for start and end channel");
1625 return -EINVAL;
1626 }
1627 if (hdd_ctx->config->enableDFSMasterCap)
1628 is_dfs_mode_enabled = true;
1629
1630 sap_config->acs_cfg.start_ch =
1631 hdd_ctx->config->force_sap_acs_st_ch;
1632 sap_config->acs_cfg.end_ch =
1633 hdd_ctx->config->force_sap_acs_end_ch;
1634
1635 for (i = sap_config->acs_cfg.start_ch;
1636 i <= sap_config->acs_cfg.end_ch; i++) {
1637 if ((CHANNEL_STATE_ENABLE ==
1638 wlan_reg_get_channel_state(hdd_ctx->hdd_pdev, i)) ||
1639 (is_dfs_mode_enabled &&
1640 CHANNEL_STATE_DFS ==
1641 wlan_reg_get_channel_state(hdd_ctx->hdd_pdev, i))) {
1642 channels[num_channels] = i;
1643 num_channels++;
1644 }
1645 }
1646 if (sap_config->acs_cfg.ch_list)
1647 qdf_mem_free(sap_config->acs_cfg.ch_list);
1648
1649 sap_config->acs_cfg.ch_list = qdf_mem_malloc(num_channels);
1650 if (!sap_config->acs_cfg.ch_list) {
1651 hdd_err("ACS config alloc fail");
1652 return -ENOMEM;
1653 }
1654 qdf_mem_copy(sap_config->acs_cfg.ch_list, channels, num_channels);
1655 sap_config->acs_cfg.ch_list_count = num_channels;
1656
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05301657 /* Derive ACS HW mode */
1658 hw_mode = hdd_cfg_xlate_to_csr_phy_mode(hdd_ctx->config->dot11Mode);
1659 if (hw_mode == eCSR_DOT11_MODE_AUTO) {
1660 if (sme_is_feature_supported_by_fw(DOT11AX))
1661 hw_mode = eCSR_DOT11_MODE_11ax;
1662 else
1663 hw_mode = eCSR_DOT11_MODE_11ac;
1664 }
1665
1666 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1667 if (hw_mode == eCSR_DOT11_MODE_11ac ||
1668 hw_mode == eCSR_DOT11_MODE_11ac_ONLY)
1669 hw_mode = eCSR_DOT11_MODE_11n;
1670 }
1671
1672 if ((hw_mode == eCSR_DOT11_MODE_11b ||
1673 hw_mode == eCSR_DOT11_MODE_11g ||
1674 hw_mode == eCSR_DOT11_MODE_11g_ONLY) &&
1675 sap_config->acs_cfg.start_ch > 14) {
1676 hdd_err("Invalid ACS HW Mode %d + CH range <%d - %d>",
1677 hw_mode, sap_config->acs_cfg.start_ch,
1678 sap_config->acs_cfg.end_ch);
1679 return -EINVAL;
1680 }
1681 sap_config->acs_cfg.hw_mode = hw_mode;
1682
1683 /* Derive ACS BW */
1684 ch_width = eHT_CHANNEL_WIDTH_20MHZ;
1685 if (hw_mode == eCSR_DOT11_MODE_11ac ||
1686 hw_mode == eCSR_DOT11_MODE_11ac_ONLY ||
1687 hw_mode == eCSR_DOT11_MODE_11ax ||
1688 hw_mode == eCSR_DOT11_MODE_11ax_ONLY) {
1689 ch_width = hdd_ctx->config->vhtChannelWidth;
1690 /* VHT in 2.4G depends on gChannelBondingMode24GHz INI param */
1691 if (sap_config->acs_cfg.end_ch <= 14)
1692 ch_width =
1693 hdd_ctx->config->nChannelBondingMode24GHz ?
1694 eHT_CHANNEL_WIDTH_40MHZ :
1695 eHT_CHANNEL_WIDTH_20MHZ;
1696 }
1697
1698 if (hw_mode == eCSR_DOT11_MODE_11n ||
1699 hw_mode == eCSR_DOT11_MODE_11n_ONLY) {
1700 if (sap_config->acs_cfg.end_ch <= 14)
1701 ch_width =
1702 hdd_ctx->config->nChannelBondingMode24GHz ?
1703 eHT_CHANNEL_WIDTH_40MHZ :
1704 eHT_CHANNEL_WIDTH_20MHZ;
1705 else
1706 ch_width =
1707 hdd_ctx->config->nChannelBondingMode5GHz ?
1708 eHT_CHANNEL_WIDTH_40MHZ :
1709 eHT_CHANNEL_WIDTH_20MHZ;
1710 }
1711 sap_config->acs_cfg.ch_width = ch_width;
1712
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05301713 return 0;
1714}
1715
1716/**
wadesong1795e142018-01-05 11:13:07 +08001717 * wlan_hdd_set_acs_ch_range : Populate ACS hw mode and channel range values
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001718 * @sap_cfg: pointer to SAP config struct
wadesong1795e142018-01-05 11:13:07 +08001719 * @hw_mode: hw mode retrieved from vendor command buffer
1720 * @ht_enabled: whether HT phy mode is enabled
1721 * @vht_enabled: whether VHT phy mode is enabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001722 *
wadesong1795e142018-01-05 11:13:07 +08001723 * This function populates the ACS hw mode based on the configuration retrieved
1724 * from the vendor command buffer; and sets ACS start and end channel for the
1725 * given band.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001726 *
wadesong1795e142018-01-05 11:13:07 +08001727 * Return: 0 if success; -EINVAL if ACS channel list is NULL
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001728 */
wadesong1795e142018-01-05 11:13:07 +08001729static int wlan_hdd_set_acs_ch_range(
1730 tsap_Config_t *sap_cfg, enum qca_wlan_vendor_acs_hw_mode hw_mode,
1731 bool ht_enabled, bool vht_enabled)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001732{
1733 int i;
Srinivas Girigowda576b2352017-08-25 14:44:26 -07001734
wadesong1795e142018-01-05 11:13:07 +08001735 if (hw_mode == QCA_ACS_MODE_IEEE80211B) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001736 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001737 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1738 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_14);
wadesong1795e142018-01-05 11:13:07 +08001739 } else if (hw_mode == QCA_ACS_MODE_IEEE80211G) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001740 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001741 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1742 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_13);
wadesong1795e142018-01-05 11:13:07 +08001743 } else if (hw_mode == QCA_ACS_MODE_IEEE80211A) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001744 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001745 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_36);
1746 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
wadesong1795e142018-01-05 11:13:07 +08001747 } else if (hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001748 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001749 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1750 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001751 }
1752
1753 if (ht_enabled)
1754 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1755
1756 if (vht_enabled)
1757 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1758
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001759 /* Parse ACS Chan list from hostapd */
1760 if (!sap_cfg->acs_cfg.ch_list)
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05301761 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001762
1763 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1764 sap_cfg->acs_cfg.end_ch =
1765 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1766 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301767 /* avoid channel as start channel */
1768 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1769 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001770 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1771 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1772 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1773 }
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05301774
1775 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001776}
1777
1778
1779static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1780
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301781
1782static void hdd_update_acs_channel_list(tsap_Config_t *sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001783 enum band_info band)
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301784{
1785 int i, temp_count = 0;
1786 int acs_list_count = sap_config->acs_cfg.ch_list_count;
1787
1788 for (i = 0; i < acs_list_count; i++) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001789 if (BAND_2G == band) {
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301790 if (WLAN_REG_IS_24GHZ_CH(
1791 sap_config->acs_cfg.ch_list[i])) {
1792 sap_config->acs_cfg.ch_list[temp_count] =
1793 sap_config->acs_cfg.ch_list[i];
1794 temp_count++;
1795 }
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001796 } else if (BAND_5G == band) {
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301797 if (WLAN_REG_IS_5GHZ_CH(
1798 sap_config->acs_cfg.ch_list[i])) {
1799 sap_config->acs_cfg.ch_list[temp_count] =
1800 sap_config->acs_cfg.ch_list[i];
1801 temp_count++;
1802 }
1803 }
1804 }
1805 sap_config->acs_cfg.ch_list_count = temp_count;
1806}
1807
1808
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001809/**
1810 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1811 * @adapter: pointer to SAP adapter struct
1812 *
1813 * This function starts the ACS procedure if there are no
1814 * constraints like MBSSID DFS restrictions.
1815 *
1816 * Return: Status of ACS Start procedure
1817 */
Jeff Johnsone5006672017-08-29 14:39:02 -07001818int wlan_hdd_cfg80211_start_acs(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001819{
1820
Kiran Kumar Lokere85cb36b2017-09-14 15:19:14 -07001821 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001822 tsap_Config_t *sap_config;
1823 tpWLAN_SAPEventCB acs_event_callback;
1824 int status;
1825
Kiran Kumar Lokere85cb36b2017-09-14 15:19:14 -07001826 if (!adapter) {
1827 hdd_err("adapater is NULL");
1828 return -EINVAL;
1829 }
1830 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb9424862017-10-30 08:49:35 -07001831 sap_config = &adapter->session.ap.sap_config;
Agrawal Ashish65634612016-08-18 13:24:32 +05301832 if (hdd_ctx->acs_policy.acs_channel)
1833 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1834 else
1835 sap_config->channel = AUTO_CHANNEL_SELECT;
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301836 /*
1837 * No DFS SCC is allowed in Auto use case. Hence not
1838 * calling DFS override
1839 */
1840 if (QDF_MCC_TO_SCC_SWITCH_FORCE_PREFERRED_WITHOUT_DISCONNECTION !=
1841 hdd_ctx->config->WlanMccToSccSwitchMode) {
1842 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1843 if (status < 0)
1844 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001845
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301846 if (status > 0) {
1847 /*notify hostapd about channel override */
1848 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1849 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1850 return 0;
1851 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001852 }
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301853 /* When first 2 connections are on the same frequency band,
1854 * then PCL would include only channels from the other
1855 * frequency band on which no connections are active
1856 */
1857 if ((policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) == 2) &&
1858 (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY)) {
1859 struct policy_mgr_conc_connection_info *conc_connection_info;
1860 uint32_t i;
Jeff Johnson68755312017-02-10 11:46:55 -08001861
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301862 conc_connection_info = policy_mgr_get_conn_info(&i);
1863 if (conc_connection_info[0].mac ==
1864 conc_connection_info[1].mac) {
1865 if (WLAN_REG_IS_5GHZ_CH(sap_config->acs_cfg.
1866 pcl_channels[0])) {
1867 sap_config->acs_cfg.band =
1868 QCA_ACS_MODE_IEEE80211A;
1869 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001870 BAND_5G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301871 } else {
1872 sap_config->acs_cfg.band =
1873 QCA_ACS_MODE_IEEE80211G;
1874 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08001875 BAND_2G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05301876 }
1877 }
1878 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001879 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1880 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001881 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001882 return -EINVAL;
1883 }
1884
1885 acs_event_callback = hdd_hostapd_sap_event_cb;
1886
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301887 qdf_mem_copy(sap_config->self_macaddr.bytes,
Jeff Johnson1e851a12017-10-28 14:36:12 -07001888 adapter->mac_addr.bytes, sizeof(struct qdf_mac_addr));
Dustin Brown5e89ef82018-03-14 11:50:23 -07001889 hdd_info("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001890 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001891 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001892 acs_event_callback, sap_config, adapter->dev);
1893
1894
1895 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001896 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001897 return -EINVAL;
1898 }
bings394afdd2017-01-09 11:22:38 +08001899 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1900 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001901 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1902
1903 return 0;
1904}
1905
1906/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301907 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1908 * @hdd_ctx: hdd context
1909 * @acs_chan_params: external acs channel params
1910 * @sap_config: SAP config
1911 *
1912 * This API provides unsorted pcl list.
1913 * this list is a subset of the valid channel list given by hostapd.
1914 * if channel is not present in pcl, weightage will be given as zero
1915 *
1916 * Return: Zero on success, non-zero on failure
1917 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07001918static void hdd_update_vendor_pcl_list(struct hdd_context *hdd_ctx,
Kapil Gupta8878ad92017-02-13 11:56:04 +05301919 struct hdd_vendor_acs_chan_params *acs_chan_params,
1920 tsap_Config_t *sap_config)
1921{
1922 int i, j;
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301923 /*
1924 * PCL shall contain only the preferred channels from the
1925 * application. If those channels are not present in the
1926 * driver PCL, then set the weight to zero
1927 */
1928 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1929 acs_chan_params->vendor_pcl_list[i] =
1930 sap_config->acs_cfg.ch_list[i];
1931 acs_chan_params->vendor_weight_list[i] = 0;
1932 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1933 if (sap_config->acs_cfg.ch_list[i] ==
1934 sap_config->acs_cfg.pcl_channels[j]) {
1935 acs_chan_params->vendor_weight_list[i] =
1936 sap_config->
1937 acs_cfg.pcl_channels_weight_list[j];
1938 break;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301939 }
1940 }
1941 }
Adesh Keremane25ce2dc2017-05-29 17:55:39 +05301942 acs_chan_params->pcl_count = sap_config->acs_cfg.ch_list_count;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301943}
1944
1945/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301946 * hdd_update_reg_chan_info : This API contructs channel info
1947 * for all the given channel
1948 * @adapter: pointer to SAP adapter struct
1949 * @channel_count: channel count
1950 * @channel_list: channel list
1951 *
1952 * Return: Status of of channel information updation
1953 */
Jeff Johnsone5006672017-08-29 14:39:02 -07001954static int hdd_update_reg_chan_info(struct hdd_adapter *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301955 uint32_t channel_count,
1956 uint8_t *channel_list)
1957{
1958 int i;
1959 struct hdd_channel_info *icv;
Amar Singhal5cccafe2017-02-15 12:42:58 -08001960 struct ch_params ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301961 uint8_t bw_offset = 0, chan = 0;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07001962 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb9424862017-10-30 08:49:35 -07001963 tsap_Config_t *sap_config = &adapter->session.ap.sap_config;
Kapil Gupta086c6202016-12-11 18:17:06 +05301964
1965 /* memory allocation */
1966 sap_config->channel_info = qdf_mem_malloc(
1967 sizeof(struct hdd_channel_info) *
1968 channel_count);
1969 if (!sap_config->channel_info) {
1970 hdd_err("memory allocation failed");
1971 return -ENOMEM;
1972
1973 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05301974 sap_config->channel_info_count = channel_count;
Kapil Gupta086c6202016-12-11 18:17:06 +05301975 for (i = 0; i < channel_count; i++) {
1976 icv = &sap_config->channel_info[i];
1977 chan = channel_list[i];
1978
1979 if (chan == 0)
1980 continue;
1981
1982 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1983 bw_offset = 1 << BW_40_OFFSET_BIT;
1984 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1985 bw_offset = 1 << BW_20_OFFSET_BIT;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001986 icv->freq = wlan_reg_get_channel_freq(hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301987 icv->ieee_chan_number = chan;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001988 icv->max_reg_power = wlan_reg_get_channel_reg_power(
1989 hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301990
1991 /* filling demo values */
1992 icv->max_radio_power = HDD_MAX_TX_POWER;
1993 icv->min_radio_power = HDD_MIN_TX_POWER;
1994 /* not supported in current driver */
1995 icv->max_antenna_gain = 0;
1996
1997 icv->reg_class_id = wlan_hdd_find_opclass(
1998 WLAN_HDD_GET_HAL_CTX(adapter),
1999 chan, bw_offset);
2000
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002001 if (WLAN_REG_IS_5GHZ_CH(chan)) {
Kapil Gupta086c6202016-12-11 18:17:06 +05302002 ch_params.ch_width = sap_config->acs_cfg.ch_width;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002003 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan,
2004 0, &ch_params);
Kapil Gupta086c6202016-12-11 18:17:06 +05302005 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
2006 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
2007 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002008
Kapil Gupta086c6202016-12-11 18:17:06 +05302009 icv->flags = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07002010 icv->flags = cds_get_vendor_reg_flags(hdd_ctx->hdd_pdev, chan,
Kapil Gupta086c6202016-12-11 18:17:06 +05302011 sap_config->acs_cfg.ch_width,
2012 sap_config->acs_cfg.is_ht_enabled,
2013 sap_config->acs_cfg.is_vht_enabled,
2014 hdd_ctx->config->enable_sub_20_channel_width);
Kapil Guptac1224bf2017-06-22 21:22:40 +05302015 if (icv->flags & IEEE80211_CHAN_PASSIVE)
2016 icv->flagext |= IEEE80211_CHAN_DFS;
Kapil Gupta086c6202016-12-11 18:17:06 +05302017
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +05302018 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 +05302019 icv->freq, icv->flags,
2020 icv->flagext, icv->ieee_chan_number,
2021 icv->max_reg_power, icv->max_radio_power,
2022 icv->min_radio_power, icv->reg_class_id,
2023 icv->max_antenna_gain, icv->vht_center_freq_seg0,
2024 icv->vht_center_freq_seg1);
2025 }
2026 return 0;
2027}
2028
2029/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
2030#define CHAN_INFO_ATTR_FLAGS \
2031 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
2032#define CHAN_INFO_ATTR_FLAG_EXT \
2033 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
2034#define CHAN_INFO_ATTR_FREQ \
2035 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
2036#define CHAN_INFO_ATTR_MAX_REG_POWER \
2037 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
2038#define CHAN_INFO_ATTR_MAX_POWER \
2039 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
2040#define CHAN_INFO_ATTR_MIN_POWER \
2041 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
2042#define CHAN_INFO_ATTR_REG_CLASS_ID \
2043 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
2044#define CHAN_INFO_ATTR_ANTENNA_GAIN \
2045 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
2046#define CHAN_INFO_ATTR_VHT_SEG_0 \
2047 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
2048#define CHAN_INFO_ATTR_VHT_SEG_1 \
2049 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
2050
2051/**
2052 * hdd_cfg80211_update_channel_info() - add channel info attributes
2053 * @skb: pointer to sk buff
2054 * @hdd_ctx: pointer to hdd station context
2055 * @idx: attribute index
2056 *
2057 * Return: Success(0) or reason code for failure
2058 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05302059static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05302060hdd_cfg80211_update_channel_info(struct sk_buff *skb,
2061 tsap_Config_t *sap_config, int idx)
2062{
2063 struct nlattr *nla_attr, *channel;
2064 struct hdd_channel_info *icv;
2065 int i;
2066
2067 nla_attr = nla_nest_start(skb, idx);
2068 if (!nla_attr)
2069 goto fail;
2070
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302071 for (i = 0; i < sap_config->channel_info_count; i++) {
Kapil Gupta086c6202016-12-11 18:17:06 +05302072 channel = nla_nest_start(skb, i);
2073 if (!channel)
2074 goto fail;
2075
2076 icv = &sap_config->channel_info[i];
2077 if (!icv) {
2078 hdd_err("channel info not found");
2079 goto fail;
2080 }
2081 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
2082 icv->freq) ||
2083 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
2084 icv->flags) ||
Kapil Gupta63e75282017-05-18 20:55:10 +05302085 nla_put_u32(skb, CHAN_INFO_ATTR_FLAG_EXT,
Kapil Gupta086c6202016-12-11 18:17:06 +05302086 icv->flagext) ||
2087 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
2088 icv->max_reg_power) ||
2089 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
2090 icv->max_radio_power) ||
2091 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
2092 icv->min_radio_power) ||
2093 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
2094 icv->reg_class_id) ||
2095 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
2096 icv->max_antenna_gain) ||
2097 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
2098 icv->vht_center_freq_seg0) ||
2099 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
2100 icv->vht_center_freq_seg1)) {
2101 hdd_err("put fail");
2102 goto fail;
2103 }
2104 nla_nest_end(skb, channel);
2105 }
2106 nla_nest_end(skb, nla_attr);
2107 return 0;
2108fail:
2109 hdd_err("nl channel update failed");
2110 return -EINVAL;
2111}
2112#undef CHAN_INFO_ATTR_FLAGS
2113#undef CHAN_INFO_ATTR_FLAG_EXT
2114#undef CHAN_INFO_ATTR_FREQ
2115#undef CHAN_INFO_ATTR_MAX_REG_POWER
2116#undef CHAN_INFO_ATTR_MAX_POWER
2117#undef CHAN_INFO_ATTR_MIN_POWER
2118#undef CHAN_INFO_ATTR_REG_CLASS_ID
2119#undef CHAN_INFO_ATTR_ANTENNA_GAIN
2120#undef CHAN_INFO_ATTR_VHT_SEG_0
2121#undef CHAN_INFO_ATTR_VHT_SEG_1
2122
2123/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05302124 * hdd_cfg80211_update_pcl() - add pcl info attributes
2125 * @skb: pointer to sk buff
2126 * @hdd_ctx: pointer to hdd station context
2127 * @idx: attribute index
2128 * @vendor_pcl_list: PCL list
2129 * @vendor_weight_list: PCL weights
2130 *
2131 * Return: Success(0) or reason code for failure
2132 */
2133static int32_t
2134hdd_cfg80211_update_pcl(struct sk_buff *skb,
2135 uint8_t ch_list_count, int idx,
2136 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
2137{
2138 struct nlattr *nla_attr, *channel;
2139 int i;
2140
2141 nla_attr = nla_nest_start(skb, idx);
2142
2143 if (!nla_attr)
2144 goto fail;
2145
2146 for (i = 0; i < ch_list_count; i++) {
2147 channel = nla_nest_start(skb, i);
2148 if (!channel)
2149 goto fail;
Kapil Gupta63e75282017-05-18 20:55:10 +05302150 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CHANNEL,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302151 vendor_pcl_list[i]) ||
Kapil Gupta63e75282017-05-18 20:55:10 +05302152 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302153 vendor_weight_list[i])) {
2154 hdd_err("put fail");
2155 goto fail;
2156 }
2157 nla_nest_end(skb, channel);
2158 }
2159 nla_nest_end(skb, nla_attr);
2160
2161 return 0;
2162fail:
2163 hdd_err("updating pcl list failed");
2164 return -EINVAL;
2165}
2166
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002167static void hdd_get_scan_band(struct hdd_context *hdd_ctx,
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302168 tsap_Config_t *sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002169 enum band_info *band)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302170{
2171 /* Get scan band */
Kapil Guptac1224bf2017-06-22 21:22:40 +05302172 if ((sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211B) ||
2173 (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211G)) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002174 *band = BAND_2G;
Kapil Guptac1224bf2017-06-22 21:22:40 +05302175 } else if (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211A) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002176 *band = BAND_5G;
Kapil Guptac1224bf2017-06-22 21:22:40 +05302177 } else if (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002178 *band = BAND_ALL;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302179 }
2180 /* Auto is not supported currently */
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002181 if (!((*band == BAND_2G) || (BAND_5G == *band))) {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302182 hdd_err("invalid band");
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302183 if (HDD_EXTERNAL_ACS_FREQ_BAND_24GHZ ==
2184 hdd_ctx->config->external_acs_freq_band)
Himanshu Agarwale9949702018-03-01 17:30:01 +05302185 *band = BAND_2G;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302186 else
Himanshu Agarwale9949702018-03-01 17:30:01 +05302187 *band = BAND_5G;
2188
2189 hdd_update_acs_channel_list(sap_config, *band);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302190 }
Himanshu Agarwale9949702018-03-01 17:30:01 +05302191
2192 if (*band == BAND_2G &&
2193 (sap_config->acs_cfg.ch_width == CH_WIDTH_80MHZ ||
2194 sap_config->acs_cfg.ch_width == CH_WIDTH_160MHZ ||
2195 sap_config->acs_cfg.ch_width == CH_WIDTH_80P80MHZ))
2196 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302197}
2198
Kapil Gupta63e75282017-05-18 20:55:10 +05302199
2200/**
2201 * hdd_get_freq_list: API to get Frequency list based on channel list
2202 * @channel_list: channel list
2203 * @freq_list: frequency list
2204 * @channel_count: channel count
2205 *
2206 * Return: None
2207 */
2208static void hdd_get_freq_list(uint8_t *channel_list, uint32_t *freq_list,
2209 uint32_t channel_count)
2210{
2211 int count;
2212
2213 for (count = 0; count < channel_count ; count++)
2214 freq_list[count] = cds_chan_to_freq(channel_list[count]);
2215}
2216
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302217int hdd_cfg80211_update_acs_config(struct hdd_adapter *adapter,
2218 uint8_t reason)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302219{
2220 struct sk_buff *skb;
2221 tsap_Config_t *sap_config;
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302222 uint32_t channel_count = 0, status = -EINVAL;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302223 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
Kapil Gupta63e75282017-05-18 20:55:10 +05302224 uint32_t freq_list[QDF_MAX_NUM_CHAN] = {0};
Kapil Gupta8878ad92017-02-13 11:56:04 +05302225 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
2226 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
2227 struct hdd_vendor_acs_chan_params acs_chan_params;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002228 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002229 enum band_info band = BAND_2G;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302230 eCsrPhyMode phy_mode;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302231 enum qca_wlan_vendor_attr_external_acs_policy acs_policy;
2232 uint32_t i;
2233
Kapil Gupta8878ad92017-02-13 11:56:04 +05302234
2235 if (!hdd_ctx) {
2236 hdd_err("HDD context is NULL");
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302237 return -EINVAL;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302238 }
2239
Dustin Brown491d54b2018-03-14 12:39:11 -07002240 hdd_enter();
Jeff Johnsonb9424862017-10-30 08:49:35 -07002241 sap_config = &adapter->session.ap.sap_config;
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302242 /* When first 2 connections are on the same frequency band,
2243 * then PCL would include only channels from the other
2244 * frequency band on which no connections are active
2245 */
2246 if ((policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) == 2) &&
2247 (sap_config->acs_cfg.band == QCA_ACS_MODE_IEEE80211ANY)) {
2248 struct policy_mgr_conc_connection_info *conc_connection_info;
2249
2250 conc_connection_info = policy_mgr_get_conn_info(&i);
2251 if (conc_connection_info[0].mac ==
2252 conc_connection_info[1].mac) {
2253
2254 if (WLAN_REG_IS_5GHZ_CH(sap_config->acs_cfg.
2255 pcl_channels[0])) {
2256 sap_config->acs_cfg.band =
2257 QCA_ACS_MODE_IEEE80211A;
2258 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002259 BAND_5G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302260 } else {
2261 sap_config->acs_cfg.band =
2262 QCA_ACS_MODE_IEEE80211G;
2263 hdd_update_acs_channel_list(sap_config,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08002264 BAND_2G);
Jayachandran Sreekumaran5c7cd972017-09-27 18:51:41 +05302265 }
2266 }
2267 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302268
Jeff Johnsonb9424862017-10-30 08:49:35 -07002269 hdd_get_scan_band(hdd_ctx, &adapter->session.ap.sap_config, &band);
Nachiket Kukade3208c162017-08-29 17:40:59 +05302270
2271 if (sap_config->acs_cfg.ch_list) {
2272 /* Copy INI or hostapd provided ACS channel range*/
2273 qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
2274 sap_config->acs_cfg.ch_list_count);
2275 channel_count = sap_config->acs_cfg.ch_list_count;
2276 } else {
2277 /* No channel list provided, copy all valid channels */
2278 wlan_hdd_sap_get_valid_channellist(adapter,
2279 &channel_count,
2280 channel_list,
2281 band);
2282 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302283
2284 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
Kapil Gupta63e75282017-05-18 20:55:10 +05302285 hdd_get_freq_list(channel_list, freq_list, channel_count);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302286 /* Get phymode */
Jeff Johnsonb9424862017-10-30 08:49:35 -07002287 phy_mode = adapter->session.ap.sap_config.acs_cfg.hw_mode;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302288
2289 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
2290 &(adapter->wdev),
2291 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
2292 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
2293 GFP_KERNEL);
2294
2295 if (!skb) {
2296 hdd_err("cfg80211_vendor_event_alloc failed");
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302297 return -ENOMEM;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302298 }
2299 /*
2300 * Application expects pcl to be a subset of channel list
2301 * Remove all channels which are not in channel list from pcl
2302 * and add weight as zero
2303 */
2304 acs_chan_params.channel_count = channel_count;
2305 acs_chan_params.channel_list = channel_list;
2306 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
2307 acs_chan_params.vendor_weight_list = vendor_weight_list;
2308
2309 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
2310 sap_config);
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302311
2312 if (acs_chan_params.channel_count) {
2313 hdd_debug("ACS channel list: len: %d",
2314 acs_chan_params.channel_count);
2315 for (i = 0; i < acs_chan_params.channel_count; i++)
2316 hdd_debug("%d ", acs_chan_params.channel_list[i]);
2317 }
2318
2319 if (acs_chan_params.pcl_count) {
2320 hdd_debug("ACS PCL list: len: %d",
2321 acs_chan_params.pcl_count);
2322 for (i = 0; i < acs_chan_params.pcl_count; i++)
2323 hdd_debug("channel:%d, weight:%d ",
2324 acs_chan_params.
2325 vendor_pcl_list[i],
2326 acs_chan_params.
2327 vendor_weight_list[i]);
2328 }
2329
2330 if (HDD_EXTERNAL_ACS_PCL_MANDATORY ==
2331 hdd_ctx->config->external_acs_policy) {
2332 acs_policy =
2333 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY;
2334 } else {
2335 acs_policy =
2336 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED;
2337 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302338 /* Update values in NL buffer */
2339 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
2340 reason) ||
Kapil Gupta63e75282017-05-18 20:55:10 +05302341 nla_put_flag(skb,
2342 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED) ||
2343 nla_put_flag(skb,
2344 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT)
2345 ||
Kapil Gupta8878ad92017-02-13 11:56:04 +05302346 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
2347 sap_config->acs_cfg.ch_width) ||
Kapil Gupta8878ad92017-02-13 11:56:04 +05302348 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
2349 band) ||
2350 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
2351 phy_mode) ||
SaidiReddy Yenugae14cfb82017-05-04 18:50:37 +05302352 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST,
Kapil Gupta63e75282017-05-18 20:55:10 +05302353 channel_count * sizeof(uint32_t), freq_list)) {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302354 hdd_err("nla put fail");
2355 goto fail;
2356 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302357 status =
2358 hdd_cfg80211_update_pcl(skb,
2359 acs_chan_params.
2360 pcl_count,
2361 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
2362 vendor_pcl_list,
2363 vendor_weight_list);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302364
2365 if (status != 0)
2366 goto fail;
2367
2368 status = hdd_cfg80211_update_channel_info(skb, sap_config,
2369 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
2370
Kapil Gupta63e75282017-05-18 20:55:10 +05302371 qdf_mem_free(sap_config->channel_info);
Kapil Gupta8878ad92017-02-13 11:56:04 +05302372 if (status != 0)
2373 goto fail;
2374
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302375 status = nla_put_u32(skb,
2376 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY,
2377 acs_policy);
2378
2379 if (status != 0)
2380 goto fail;
2381
Kapil Gupta8878ad92017-02-13 11:56:04 +05302382 cfg80211_vendor_event(skb, GFP_KERNEL);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302383 return 0;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302384fail:
2385 if (skb)
2386 kfree_skb(skb);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302387 return status;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302388}
2389
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302390/**
2391 * hdd_create_acs_timer(): Initialize vendor ACS timer
2392 * @adapter: pointer to SAP adapter struct
2393 *
2394 * This function initializes the vendor ACS timer.
2395 *
2396 * Return: Status of create vendor ACS timer
2397 */
Jeff Johnsone5006672017-08-29 14:39:02 -07002398static int hdd_create_acs_timer(struct hdd_adapter *adapter)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302399{
2400 struct hdd_external_acs_timer_context *timer_context;
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302401 QDF_STATUS status;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302402
Jeff Johnsonb9424862017-10-30 08:49:35 -07002403 if (adapter->session.ap.vendor_acs_timer_initialized)
Kapil Gupta8878ad92017-02-13 11:56:04 +05302404 return 0;
2405
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302406 hdd_debug("Starting vendor app based ACS");
Kapil Gupta8878ad92017-02-13 11:56:04 +05302407 timer_context = qdf_mem_malloc(sizeof(*timer_context));
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302408 if (!timer_context) {
2409 hdd_err("Could not allocate for timer_context");
2410 return -ENOMEM;
2411 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302412 timer_context->adapter = adapter;
2413
2414 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
Jeff Johnsonb9424862017-10-30 08:49:35 -07002415 status = qdf_mc_timer_init(&adapter->session.ap.vendor_acs_timer,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302416 QDF_TIMER_TYPE_SW,
2417 hdd_acs_response_timeout_handler, timer_context);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302418 if (status != QDF_STATUS_SUCCESS) {
2419 hdd_err("Failed to initialize acs response timeout timer");
2420 return -EFAULT;
2421 }
Jeff Johnsonb9424862017-10-30 08:49:35 -07002422 adapter->session.ap.vendor_acs_timer_initialized = true;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302423 return 0;
2424}
2425
Ashish Kumar Dhanotiyacc770eb2017-06-08 19:31:15 +05302426static const struct nla_policy
2427wlan_hdd_cfg80211_do_acs_policy[QCA_WLAN_VENDOR_ATTR_ACS_MAX+1] = {
2428 [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
2429 [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
2430 [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
2431 [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
2432 [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
2433 [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_UNSPEC },
2434 [QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST] = { .type = NLA_UNSPEC },
2435};
2436
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302437int hdd_start_vendor_acs(struct hdd_adapter *adapter)
2438{
2439 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2440 int status;
2441
2442 status = hdd_create_acs_timer(adapter);
2443 if (status != 0) {
2444 hdd_err("failed to create acs timer");
2445 return status;
2446 }
2447 status = hdd_update_acs_timer_reason(adapter,
2448 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2449 if (status != 0) {
2450 hdd_err("failed to update acs timer reason");
2451 return status;
2452 }
2453
2454 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2455 status = qdf_status_to_os_return(wlan_sap_set_vendor_acs(
2456 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2457 true));
2458 else
2459 status = qdf_status_to_os_return(wlan_sap_set_vendor_acs(
2460 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2461 false));
2462
2463 return status;
2464}
2465
Kapil Gupta8878ad92017-02-13 11:56:04 +05302466/**
Ashish Kumar Dhanotiyacc770eb2017-06-08 19:31:15 +05302467 * __wlan_hdd_cfg80211_do_acs(): CFG80211 handler function for DO_ACS Vendor CMD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002468 * @wiphy: Linux wiphy struct pointer
2469 * @wdev: Linux wireless device struct pointer
2470 * @data: ACS information from hostapd
2471 * @data_len: ACS information length
2472 *
2473 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2474 * and starts ACS procedure.
2475 *
2476 * Return: ACS procedure start status
2477 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002478static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2479 struct wireless_dev *wdev,
2480 const void *data, int data_len)
2481{
2482 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07002483 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002484 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002485 tsap_Config_t *sap_config;
2486 struct sk_buff *temp_skbuff;
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302487 int ret, i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002488 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
2489 bool ht_enabled, ht40_enabled, vht_enabled;
wadesong1795e142018-01-05 11:13:07 +08002490 uint8_t ch_width;
2491 enum qca_wlan_vendor_acs_hw_mode hw_mode;
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05302492 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002493
2494 /* ***Note*** Donot set SME config related to ACS operation here because
2495 * ACS operation is not synchronouse and ACS for Second AP may come when
2496 * ACS operation for first AP is going on. So only do_acs is split to
2497 * seperate start_acs routine. Also SME-PMAC struct that is used to
2498 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
2499 * config shall be set only from start_acs.
2500 */
2501
Dustin Brownfdf17c12018-03-14 12:55:34 -07002502 hdd_enter_dev(ndev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08002503
Anurag Chouhan6d760662016-02-20 16:05:43 +05302504 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002505 hdd_err("Command not allowed in FTM mode");
2506 return -EPERM;
2507 }
2508
Kapil Gupta8878ad92017-02-13 11:56:04 +05302509 if (hdd_ctx->config->force_sap_acs &&
2510 !hdd_ctx->config->vendor_acs_support) {
Jeff Johnson020db452016-06-29 14:37:26 -07002511 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002512 return -EPERM;
2513 }
2514
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302515 ret = wlan_hdd_validate_context(hdd_ctx);
2516 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002517 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302518
Naveen Rawat64e477e2016-05-20 10:34:56 -07002519 if (cds_is_sub_20_mhz_enabled()) {
2520 hdd_err("ACS not supported in sub 20 MHz ch wd.");
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302521 ret = -EINVAL;
Naveen Rawat64e477e2016-05-20 10:34:56 -07002522 goto out;
2523 }
2524
Abhinav Kumar5eda62d2018-02-13 13:00:39 +05302525 if (qdf_atomic_inc_return(&hdd_ctx->is_acs_allowed) > 1) {
2526 hdd_err("ACS rejected as previous req already in progress");
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302527 ret = -EINVAL;
Abhinav Kumar5eda62d2018-02-13 13:00:39 +05302528 goto out;
2529 }
2530
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302531 ret = wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data,
Dustin Brown4ea21db2018-01-05 14:13:17 -08002532 data_len,
2533 wlan_hdd_cfg80211_do_acs_policy);
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302534 if (ret) {
Jeff Johnson020db452016-06-29 14:37:26 -07002535 hdd_err("Invalid ATTR");
Abhinav Kumar5eda62d2018-02-13 13:00:39 +05302536 qdf_atomic_set(&hdd_ctx->is_acs_allowed, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002537 goto out;
2538 }
2539
2540 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002541 hdd_err("Attr hw_mode failed");
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302542 ret = -EINVAL;
Abhinav Kumar5eda62d2018-02-13 13:00:39 +05302543 qdf_atomic_set(&hdd_ctx->is_acs_allowed, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002544 goto out;
2545 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05302546 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002547
2548 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
2549 ht_enabled =
2550 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
2551 else
2552 ht_enabled = 0;
2553
2554 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
2555 ht40_enabled =
2556 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
2557 else
2558 ht40_enabled = 0;
2559
Kapil Guptac1224bf2017-06-22 21:22:40 +05302560 hdd_debug("ht40_enabled %d", ht40_enabled);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002561 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
2562 vht_enabled =
2563 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
2564 else
2565 vht_enabled = 0;
2566
Bala Venkateshb9cf3362017-11-09 15:48:46 +05302567 if (((adapter->device_mode == QDF_SAP_MODE) &&
2568 (hdd_ctx->config->sap_force_11n_for_11ac)) ||
2569 ((adapter->device_mode == QDF_P2P_GO_MODE) &&
2570 (hdd_ctx->config->go_force_11n_for_11ac))) {
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302571 vht_enabled = 0;
Dustin Brownbacc48f2018-03-14 14:48:44 -07002572 hdd_info("VHT is Disabled in ACS");
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302573 }
2574
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002575 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
2576 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
2577 } else {
2578 if (ht_enabled && ht40_enabled)
2579 ch_width = 40;
2580 else
2581 ch_width = 20;
2582 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302583
Bala Venkateshb9cf3362017-11-09 15:48:46 +05302584 /* this may be possible, when sap_force_11n_for_11ac or
2585 * go_force_11n_for_11ac is set
2586 */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302587 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
2588 if (ht_enabled && ht40_enabled)
2589 ch_width = 40;
2590 else
2591 ch_width = 20;
2592 }
2593
Hanumanth Reddy Pothula560d5712018-03-15 18:11:27 +05302594 sap_config = &adapter->session.ap.sap_config;
2595
2596 /* Check and free if memory is already allocated for acs channel list */
2597 wlan_hdd_undo_acs(adapter);
2598
2599 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
2600
Kapil Guptac1224bf2017-06-22 21:22:40 +05302601 hdd_debug("channel width =%d", ch_width);
Himanshu Agarwal75e74412018-02-01 20:51:47 +05302602 if (ch_width == 160)
2603 sap_config->acs_cfg.ch_width = CH_WIDTH_160MHZ;
2604 else if (ch_width == 80)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002605 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
2606 else if (ch_width == 40)
2607 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
2608 else
2609 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
2610
2611 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
2612 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
2613 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
2614 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
2615 * since it contains the frequency values of the channels in
2616 * the channel list.
2617 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
2618 * is present
2619 */
Himanshu Agarwal1b3be702018-02-20 12:16:57 +05302620
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002621 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
2622 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
Srinivas Girigowda576b2352017-08-25 14:44:26 -07002623
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002624 sap_config->acs_cfg.ch_list_count = nla_len(
2625 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
2626 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302627 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002628 sizeof(uint8_t) *
2629 sap_config->acs_cfg.ch_list_count);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302630 if (!sap_config->acs_cfg.ch_list) {
2631 hdd_err("ACS config alloc fail");
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302632 ret = -ENOMEM;
Abhinav Kumar5eda62d2018-02-13 13:00:39 +05302633 qdf_atomic_set(&hdd_ctx->is_acs_allowed, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002634 goto out;
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302635 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002636
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302637 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002638 sap_config->acs_cfg.ch_list_count);
2639 }
2640 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
2641 uint32_t *freq =
2642 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
2643 sap_config->acs_cfg.ch_list_count = nla_len(
2644 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
2645 sizeof(uint32_t);
2646 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302647 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002648 sap_config->acs_cfg.ch_list_count);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302649 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07002650 hdd_err("ACS config alloc fail");
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302651 ret = -ENOMEM;
Abhinav Kumar5eda62d2018-02-13 13:00:39 +05302652 qdf_atomic_set(&hdd_ctx->is_acs_allowed, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002653 goto out;
2654 }
2655
2656 /* convert frequency to channel */
2657 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
2658 sap_config->acs_cfg.ch_list[i] =
2659 ieee80211_frequency_to_channel(freq[i]);
2660 }
2661 }
2662
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302663 if (!sap_config->acs_cfg.ch_list_count) {
2664 ret = -EINVAL;
2665 goto out;
2666 }
2667
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002668 hdd_debug("get pcl for DO_ACS vendor command");
2669
2670 /* consult policy manager to get PCL */
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05302671 qdf_status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc, PM_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05302672 sap_config->acs_cfg.pcl_channels,
2673 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302674 sap_config->acs_cfg.pcl_channels_weight_list,
2675 QDF_MAX_NUM_CHAN);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302676 if (qdf_status != QDF_STATUS_SUCCESS)
Jeff Johnson020db452016-06-29 14:37:26 -07002677 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002678
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302679 if (sap_config->acs_cfg.pcl_ch_count) {
2680 hdd_debug("ACS config PCL: len: %d",
2681 sap_config->acs_cfg.pcl_ch_count);
2682 for (i = 0; i < sap_config->acs_cfg.pcl_ch_count; i++)
2683 hdd_debug("channel:%d, weight:%d ",
2684 sap_config->acs_cfg.
2685 pcl_channels[i],
2686 sap_config->acs_cfg.
2687 pcl_channels_weight_list[i]);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05302688 }
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05302689
Tushnim Bhattacharyya087bff32018-02-21 13:25:15 -08002690 if (hw_mode == QCA_ACS_MODE_IEEE80211ANY)
2691 policy_mgr_trim_acs_channel_list(hdd_ctx->hdd_psoc,
2692 sap_config->acs_cfg.ch_list,
2693 &sap_config->acs_cfg.ch_list_count);
2694
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05302695 if (hdd_ctx->config->force_sap_acs) {
2696 hdd_debug("forcing SAP acs start and end channel");
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302697 ret = wlan_hdd_reset_force_acs_chan_range(hdd_ctx,
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05302698 sap_config);
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302699 if (ret) {
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302700 hdd_err("reset force acs channel range failed");
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05302701 goto out;
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302702 }
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05302703 }
Kapil Guptac1224bf2017-06-22 21:22:40 +05302704
2705 sap_config->acs_cfg.band = hw_mode;
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302706 ret = wlan_hdd_set_acs_ch_range(sap_config, hw_mode,
Himanshu Agarwal8b3d3e92018-02-08 23:03:54 +05302707 ht_enabled, vht_enabled);
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302708 if (ret) {
Himanshu Agarwal8b3d3e92018-02-08 23:03:54 +05302709 hdd_err("set acs channel range failed");
2710 goto out;
2711 }
2712
Nachiket Kukadec3f92f72017-08-07 17:04:50 +05302713 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302714 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
Himanshu Agarwal8b3d3e92018-02-08 23:03:54 +05302715 sap_config->acs_cfg.end_ch >= WLAN_REG_CH_NUM(CHAN_ENUM_36) &&
Bala Venkateshb9cf3362017-11-09 15:48:46 +05302716 !(((adapter->device_mode == QDF_SAP_MODE) &&
2717 (hdd_ctx->config->sap_force_11n_for_11ac)) ||
2718 ((adapter->device_mode == QDF_P2P_GO_MODE) &&
2719 (hdd_ctx->config->go_force_11n_for_11ac)))) {
Kapil Guptac1224bf2017-06-22 21:22:40 +05302720 hdd_debug("ACS Config override for 11AC vhtChannelWidth %d",
2721 hdd_ctx->config->vhtChannelWidth);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002722 vht_enabled = 1;
2723 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2724 sap_config->acs_cfg.ch_width =
2725 hdd_ctx->config->vhtChannelWidth;
Himanshu Agarwal29a9a3e2018-02-21 17:44:37 +05302726 }
2727
2728 /* No VHT80 in 2.4G so perform ACS accordingly */
2729 if (sap_config->acs_cfg.end_ch <= 14 &&
2730 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
2731 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
2732 hdd_debug("resetting to 40Mhz in 2.4Ghz");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002733 }
2734
Kapil Guptac1224bf2017-06-22 21:22:40 +05302735 hdd_debug("ACS Config for %s: HW_MODE: %d ACS_BW: %d HT: %d VHT: %d START_CH: %d END_CH: %d band %d",
2736 adapter->dev->name, sap_config->acs_cfg.hw_mode,
Himanshu Agarwal1ed8bff2018-02-07 12:50:41 +05302737 sap_config->acs_cfg.ch_width, ht_enabled, vht_enabled,
Kapil Guptac1224bf2017-06-22 21:22:40 +05302738 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch,
2739 sap_config->acs_cfg.band);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002740
gaoleze5108942017-03-31 16:56:42 +08002741 if (hdd_ctx->config->auto_channel_select_weight)
2742 sap_config->auto_channel_select_weight =
2743 hdd_ctx->config->auto_channel_select_weight;
2744
Kapil Gupta8878ad92017-02-13 11:56:04 +05302745 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2746 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2747
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002748 if (sap_config->acs_cfg.ch_list_count) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002749 hdd_debug("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002750 sap_config->acs_cfg.ch_list_count);
2751 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002752 hdd_debug("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002753 }
2754 sap_config->acs_cfg.acs_mode = true;
2755 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002756 /* ***Note*** Completion variable usage is not allowed
2757 * here since ACS scan operation may take max 2.2 sec
2758 * for 5G band:
2759 * 9 Active channel X 40 ms active scan time +
2760 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002761 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2762 * for this long. So we split up the scanning part.
2763 */
2764 set_bit(ACS_PENDING, &adapter->event_flags);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002765 hdd_debug("ACS Pending for %s", adapter->dev->name);
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302766 ret = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002767 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302768 /* Check if vendor specific acs is enabled */
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302769 if (hdd_ctx->config->vendor_acs_support)
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302770 ret = hdd_start_vendor_acs(adapter);
Himanshu Agarwaldfc4dca2017-08-29 19:49:05 +05302771 else
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302772 ret = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002773 }
2774
2775out:
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302776 if (ret == 0) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002777 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2778 NLMSG_HDRLEN);
2779 if (temp_skbuff != NULL)
2780 return cfg80211_vendor_cmd_reply(temp_skbuff);
2781 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002782 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002783 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2784
Yeshwanth Sriram Guntukad1f8ca72018-03-02 12:31:38 +05302785 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002786}
2787
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002788/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002789 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2790 * @wiphy: Linux wiphy struct pointer
2791 * @wdev: Linux wireless device struct pointer
2792 * @data: ACS information from hostapd
2793 * @data_len: ACS information len
2794 *
2795 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2796 * and starts ACS procedure.
2797 *
2798 * Return: ACS procedure start status
2799 */
2800
2801static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2802 struct wireless_dev *wdev,
2803 const void *data, int data_len)
2804{
2805 int ret;
2806
2807 cds_ssr_protect(__func__);
2808 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2809 cds_ssr_unprotect(__func__);
2810
2811 return ret;
2812}
2813
2814/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002815 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2816 * @adapter: Pointer to adapter struct
2817 *
2818 * This function handle cleanup of what was done in DO_ACS, including free
2819 * memory.
2820 *
2821 * Return: void
2822 */
2823
Jeff Johnsone5006672017-08-29 14:39:02 -07002824void wlan_hdd_undo_acs(struct hdd_adapter *adapter)
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002825{
2826 if (adapter == NULL)
2827 return;
Jeff Johnsonb9424862017-10-30 08:49:35 -07002828 if (adapter->session.ap.sap_config.acs_cfg.ch_list) {
2829 qdf_mem_free(adapter->session.ap.sap_config.acs_cfg.ch_list);
2830 adapter->session.ap.sap_config.acs_cfg.ch_list = NULL;
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002831 }
2832}
2833
2834/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002835 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2836 * @work: Linux workqueue struct pointer for ACS work
2837 *
2838 * This function starts the ACS procedure which was marked pending when an ACS
2839 * procedure was in progress for a concurrent SAP interface.
2840 *
2841 * Return: None
2842 */
2843
2844static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2845{
Jeff Johnsone5006672017-08-29 14:39:02 -07002846 struct hdd_adapter *adapter = container_of(work, struct hdd_adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002847 acs_pending_work.work);
Kiran Kumar Lokere85cb36b2017-09-14 15:19:14 -07002848 if (!adapter)
2849 return;
2850 clear_bit(ACS_PENDING, &adapter->event_flags);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002851 wlan_hdd_cfg80211_start_acs(adapter);
2852}
2853
2854/**
2855 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2856 * @adapter: Pointer to SAP adapter struct
2857 * @pri_channel: SAP ACS procedure selected Primary channel
2858 * @sec_channel: SAP ACS procedure selected secondary channel
2859 *
2860 * This is a callback function from SAP module on ACS procedure is completed.
2861 * This function send the ACS selected channel information to hostapd
2862 *
2863 * Return: None
2864 */
2865
Jeff Johnsone5006672017-08-29 14:39:02 -07002866void wlan_hdd_cfg80211_acs_ch_select_evt(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002867{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07002868 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnson91df29d2017-10-27 19:29:50 -07002869 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002870 struct sk_buff *vendor_event;
2871 int ret_val;
Jeff Johnsone5006672017-08-29 14:39:02 -07002872 struct hdd_adapter *con_sap_adapter;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002873 uint16_t ch_width;
2874
2875 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002876 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002877 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2878 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2879 GFP_KERNEL);
2880
2881 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002882 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002883 return;
2884 }
2885
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002886 ret_val = nla_put_u8(vendor_event,
2887 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2888 sap_cfg->acs_cfg.pri_ch);
2889 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002890 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002891 kfree_skb(vendor_event);
2892 return;
2893 }
2894
2895 ret_val = nla_put_u8(vendor_event,
2896 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2897 sap_cfg->acs_cfg.ht_sec_ch);
2898 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002899 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002900 kfree_skb(vendor_event);
2901 return;
2902 }
2903
2904 ret_val = nla_put_u8(vendor_event,
2905 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2906 sap_cfg->acs_cfg.vht_seg0_center_ch);
2907 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002908 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002909 kfree_skb(vendor_event);
2910 return;
2911 }
2912
2913 ret_val = nla_put_u8(vendor_event,
2914 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2915 sap_cfg->acs_cfg.vht_seg1_center_ch);
2916 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002917 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002918 kfree_skb(vendor_event);
2919 return;
2920 }
2921
Himanshu Agarwal75e74412018-02-01 20:51:47 +05302922 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_160MHZ)
2923 ch_width = 160;
2924 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002925 ch_width = 80;
2926 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2927 ch_width = 40;
2928 else
2929 ch_width = 20;
2930
2931 ret_val = nla_put_u16(vendor_event,
2932 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2933 ch_width);
2934 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002935 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002936 kfree_skb(vendor_event);
2937 return;
2938 }
2939 if (sap_cfg->acs_cfg.pri_ch > 14)
2940 ret_val = nla_put_u8(vendor_event,
2941 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2942 QCA_ACS_MODE_IEEE80211A);
2943 else
2944 ret_val = nla_put_u8(vendor_event,
2945 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2946 QCA_ACS_MODE_IEEE80211G);
2947
2948 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002949 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002950 kfree_skb(vendor_event);
2951 return;
2952 }
2953
Mahesh Kumar Kalikot Veetilec1da142017-09-20 10:01:13 -07002954 hdd_debug("ACS result for %s: PRI_CH: %d SEC_CH: %d VHT_SEG0: %d VHT_SEG1: %d ACS_BW: %d",
2955 adapter->dev->name, sap_cfg->acs_cfg.pri_ch,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002956 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2957 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2958
2959 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2960 /* ***Note*** As already mentioned Completion variable usage is not
2961 * allowed here since ACS scan operation may take max 2.2 sec.
2962 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2963 * operation.
2964 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2965 * when Primary AP ACS is complete and secondary AP ACS is started here
2966 * immediately, Primary AP start_bss may come inbetween ACS operation
2967 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
2968 * delay. This path and below constraint will be removed on sessionizing
2969 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2970 * As per design constraint user space control application must take
2971 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2972 * this code path. Sec AP hostapd should be started after Primary AP
2973 * start beaconing which can be confirmed by getchannel iwpriv command
2974 */
2975
2976 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2977 if (con_sap_adapter &&
2978 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002979 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2980 wlan_hdd_cfg80211_start_pending_acs);
hqu71a1a3b2018-01-23 15:38:13 +08002981 /* Lets give 1500ms for OBSS + START_BSS to complete */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002982 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
hqu71a1a3b2018-01-23 15:38:13 +08002983 msecs_to_jiffies(1500));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002984 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002985}
2986
2987static int
2988__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2989 struct wireless_dev *wdev,
2990 const void *data,
2991 int data_len)
2992{
Jeff Johnsonb8944722017-09-03 09:03:19 -07002993 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002994 struct sk_buff *skb = NULL;
2995 uint32_t fset = 0;
2996 int ret;
2997
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002998 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302999
Anurag Chouhan6d760662016-02-20 16:05:43 +05303000 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003001 hdd_err("Command not allowed in FTM mode");
3002 return -EPERM;
3003 }
3004
Jeff Johnsonb8944722017-09-03 09:03:19 -07003005 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303006 if (ret)
3007 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003008
3009 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003010 hdd_debug("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003011 fset |= WIFI_FEATURE_INFRA;
3012 }
Jeff Johnsonb8944722017-09-03 09:03:19 -07003013 if (true == hdd_is_5g_supported(hdd_ctx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003014 hdd_debug("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003015 fset |= WIFI_FEATURE_INFRA_5G;
3016 }
3017#ifdef WLAN_FEATURE_P2P
3018 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
3019 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003020 hdd_debug("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003021 fset |= WIFI_FEATURE_P2P;
3022 }
3023#endif
3024 fset |= WIFI_FEATURE_SOFT_AP;
3025
3026 /* HOTSPOT is a supplicant feature, enable it by default */
3027 fset |= WIFI_FEATURE_HOTSPOT;
3028
3029#ifdef FEATURE_WLAN_EXTSCAN
Jeff Johnsonb8944722017-09-03 09:03:19 -07003030 if (hdd_ctx->config->extscan_enabled &&
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05303031 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003032 hdd_debug("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003033 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
3034 }
3035#endif
3036 if (wlan_hdd_nan_is_supported()) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003037 hdd_debug("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003038 fset |= WIFI_FEATURE_NAN;
3039 }
3040 if (sme_is_feature_supported_by_fw(RTT)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003041 hdd_debug("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003042 fset |= WIFI_FEATURE_D2D_RTT;
3043 fset |= WIFI_FEATURE_D2AP_RTT;
3044 }
3045#ifdef FEATURE_WLAN_SCAN_PNO
Jeff Johnsonb8944722017-09-03 09:03:19 -07003046 if (hdd_ctx->config->configPNOScanSupport &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003047 sme_is_feature_supported_by_fw(PNO)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003048 hdd_debug("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003049 fset |= WIFI_FEATURE_PNO;
3050 }
3051#endif
3052 fset |= WIFI_FEATURE_ADDITIONAL_STA;
3053#ifdef FEATURE_WLAN_TDLS
Jeff Johnsonb8944722017-09-03 09:03:19 -07003054 if ((true == hdd_ctx->config->fEnableTDLSSupport) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003055 sme_is_feature_supported_by_fw(TDLS)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003056 hdd_debug("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003057 fset |= WIFI_FEATURE_TDLS;
3058 }
3059 if (sme_is_feature_supported_by_fw(TDLS) &&
Jeff Johnsonb8944722017-09-03 09:03:19 -07003060 (true == hdd_ctx->config->fEnableTDLSOffChannel) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003061 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003062 hdd_debug("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003063 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
3064 }
3065#endif
3066#ifdef WLAN_AP_STA_CONCURRENCY
3067 fset |= WIFI_FEATURE_AP_STA;
3068#endif
3069 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07003070 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Srinivas Girigowda5a1da622017-07-12 17:07:44 -07003071 fset |= WIFI_FEATURE_SET_TX_POWER_LIMIT;
Sourav Mohapatra804359e2017-12-07 13:52:05 +05303072 fset |= WIFI_FEATURE_CONFIG_NDO;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003073
3074 if (hdd_link_layer_stats_supported())
3075 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
3076
Jeff Johnsonb8944722017-09-03 09:03:19 -07003077 if (hdd_roaming_supported(hdd_ctx))
Srinivas Girigowda8df27ea2017-01-06 12:42:16 -08003078 fset |= WIFI_FEATURE_CONTROL_ROAMING;
3079
3080 if (hdd_scan_random_mac_addr_supported())
3081 fset |= WIFI_FEATURE_SCAN_RAND;
3082
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003083 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
3084 NLMSG_HDRLEN);
3085 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003086 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003087 return -EINVAL;
3088 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003089 hdd_debug("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003090 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003091 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003092 goto nla_put_failure;
3093 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303094 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05303095 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003096nla_put_failure:
3097 kfree_skb(skb);
3098 return -EINVAL;
3099}
3100
3101/**
3102 * wlan_hdd_cfg80211_get_supported_features() - get supported features
3103 * @wiphy: pointer to wireless wiphy structure.
3104 * @wdev: pointer to wireless_dev structure.
3105 * @data: Pointer to the data to be passed via vendor interface
3106 * @data_len:Length of the data to be passed
3107 *
3108 * Return: Return the Success or Failure code.
3109 */
3110static int
3111wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
3112 struct wireless_dev *wdev,
3113 const void *data, int data_len)
3114{
3115 int ret = 0;
3116
3117 cds_ssr_protect(__func__);
3118 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
3119 data, data_len);
3120 cds_ssr_unprotect(__func__);
3121
3122 return ret;
3123}
3124
3125/**
3126 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
3127 * @wiphy: pointer to wireless wiphy structure.
3128 * @wdev: pointer to wireless_dev structure.
3129 * @data: Pointer to the data to be passed via vendor interface
3130 * @data_len:Length of the data to be passed
3131 *
3132 * Set the MAC address that is to be used for scanning.
3133 *
3134 * Return: Return the Success or Failure code.
3135 */
3136static int
3137__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
3138 struct wireless_dev *wdev,
3139 const void *data,
3140 int data_len)
3141{
3142 tpSirScanMacOui pReqMsg = NULL;
Jeff Johnsonb8944722017-09-03 09:03:19 -07003143 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003144 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303145 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003146 int ret;
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003147 int len;
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +05303148 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07003149 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003150
Dustin Brownfdf17c12018-03-14 12:55:34 -07003151 hdd_enter_dev(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003152
Anurag Chouhan6d760662016-02-20 16:05:43 +05303153 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003154 hdd_err("Command not allowed in FTM mode");
3155 return -EPERM;
3156 }
3157
Jeff Johnsonb8944722017-09-03 09:03:19 -07003158 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303159 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003160 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003161
Jeff Johnsonb8944722017-09-03 09:03:19 -07003162 if (false == hdd_ctx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07003163 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003164 return -ENOTSUPP;
3165 }
3166
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003167 /*
3168 * audit note: it is ok to pass a NULL policy here since only
3169 * one attribute is parsed and it is explicitly validated
3170 */
Dustin Brown4ea21db2018-01-05 14:13:17 -08003171 if (wlan_cfg80211_nla_parse(tb,
3172 QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
3173 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003174 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003175 return -EINVAL;
3176 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303177 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003178 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07003179 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003180 return -ENOMEM;
3181 }
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003182
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003183 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003184 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003185 goto fail;
3186 }
Jeff Johnson63d1ac82017-06-01 09:06:48 -07003187
3188 len = nla_len(tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]);
3189 if (len != sizeof(pReqMsg->oui)) {
3190 hdd_err("attr mac oui invalid size %d expected %zu",
3191 len, sizeof(pReqMsg->oui));
3192 goto fail;
3193 }
3194
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003195 nla_memcpy(&pReqMsg->oui[0],
3196 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
3197 sizeof(pReqMsg->oui));
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +05303198
3199 /* populate pReqMsg for mac addr randomization */
Jeff Johnson1b780e42017-10-31 14:11:45 -07003200 pReqMsg->vdev_id = adapter->session_id;
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +05303201 pReqMsg->enb_probe_req_sno_randomization = true;
3202
3203 hdd_debug("Oui (%02x:%02x:%02x), vdev_id = %d", pReqMsg->oui[0],
3204 pReqMsg->oui[1], pReqMsg->oui[2], pReqMsg->vdev_id);
Rajeev Kumar Sirasanagandlaaec0b082017-06-21 11:59:41 +05303205
Jeff Johnsonb8944722017-09-03 09:03:19 -07003206 hdd_update_ie_whitelist_attr(&pReqMsg->ie_whitelist, hdd_ctx->config);
Rajeev Kumar Sirasanagandlaaec0b082017-06-21 11:59:41 +05303207
Jeff Johnsonb8944722017-09-03 09:03:19 -07003208 status = sme_set_scanning_mac_oui(hdd_ctx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303209 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003210 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003211 goto fail;
3212 }
3213 return 0;
3214fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303215 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003216 return -EINVAL;
3217}
3218
3219/**
3220 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
3221 * @wiphy: pointer to wireless wiphy structure.
3222 * @wdev: pointer to wireless_dev structure.
3223 * @data: Pointer to the data to be passed via vendor interface
3224 * @data_len:Length of the data to be passed
3225 *
3226 * Set the MAC address that is to be used for scanning. This is an
3227 * SSR-protecting wrapper function.
3228 *
3229 * Return: Return the Success or Failure code.
3230 */
3231static int
3232wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
3233 struct wireless_dev *wdev,
3234 const void *data,
3235 int data_len)
3236{
3237 int ret;
3238
3239 cds_ssr_protect(__func__);
3240 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
3241 data, data_len);
3242 cds_ssr_unprotect(__func__);
3243
3244 return ret;
3245}
3246
Rajeev Kumar Sirasanagandlabff450c2017-06-05 19:03:25 +05303247#define MAX_CONCURRENT_MATRIX \
3248 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX
3249#define MATRIX_CONFIG_PARAM_SET_SIZE_MAX \
3250 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX
3251static const struct nla_policy
3252wlan_hdd_get_concurrency_matrix_policy[MAX_CONCURRENT_MATRIX + 1] = {
3253 [MATRIX_CONFIG_PARAM_SET_SIZE_MAX] = {.type = NLA_U32},
3254};
3255
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003256/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303257 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
3258 * @wiphy: pointer phy adapter
3259 * @wdev: pointer to wireless device structure
3260 * @data: pointer to data buffer
3261 * @data_len: length of data
3262 *
3263 * This routine will give concurrency matrix
3264 *
3265 * Return: int status code
3266 */
3267static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
3268 struct wireless_dev *wdev,
3269 const void *data,
3270 int data_len)
3271{
3272 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
3273 uint8_t i, feature_sets, max_feature_sets;
Rajeev Kumar Sirasanagandlabff450c2017-06-05 19:03:25 +05303274 struct nlattr *tb[MAX_CONCURRENT_MATRIX + 1];
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303275 struct sk_buff *reply_skb;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07003276 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303277 int ret;
3278
Dustin Brownfdf17c12018-03-14 12:55:34 -07003279 hdd_enter_dev(wdev->netdev);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303280
3281 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3282 hdd_err("Command not allowed in FTM mode");
3283 return -EPERM;
3284 }
3285
3286 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303287 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303288 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303289
Dustin Brown4ea21db2018-01-05 14:13:17 -08003290 if (wlan_cfg80211_nla_parse(tb, MAX_CONCURRENT_MATRIX, data, data_len,
3291 wlan_hdd_get_concurrency_matrix_policy)) {
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303292 hdd_err("Invalid ATTR");
3293 return -EINVAL;
3294 }
3295
3296 /* Parse and fetch max feature set */
Rajeev Kumar Sirasanagandlabff450c2017-06-05 19:03:25 +05303297 if (!tb[MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303298 hdd_err("Attr max feature set size failed");
3299 return -EINVAL;
3300 }
Rajeev Kumar Sirasanagandlabff450c2017-06-05 19:03:25 +05303301 max_feature_sets = nla_get_u32(tb[MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003302 hdd_debug("Max feature set size: %d", max_feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303303
3304 /* Fill feature combination matrix */
3305 feature_sets = 0;
3306 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07003307 WIFI_FEATURE_P2P;
3308 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
3309 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303310 /* Add more feature combinations here */
3311
3312 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003313 hdd_debug("Number of feature sets: %d", feature_sets);
3314 hdd_debug("Feature set matrix");
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303315 for (i = 0; i < feature_sets; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003316 hdd_debug("[%d] 0x%02X", i, feature_set_matrix[i]);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303317
3318 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
3319 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
3320 if (!reply_skb) {
3321 hdd_err("Feature set matrix: buffer alloc fail");
3322 return -ENOMEM;
3323 }
3324
3325 if (nla_put_u32(reply_skb,
Jeff Johnson59eb5fd2017-10-05 09:42:39 -07003326 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
3327 feature_sets) ||
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303328 nla_put(reply_skb,
Jeff Johnson59eb5fd2017-10-05 09:42:39 -07003329 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
3330 sizeof(u32) * feature_sets,
3331 feature_set_matrix)) {
3332 hdd_err("nla put fail");
3333 kfree_skb(reply_skb);
3334 return -EINVAL;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303335 }
3336 return cfg80211_vendor_cmd_reply(reply_skb);
3337}
3338
Rajeev Kumar Sirasanagandlabff450c2017-06-05 19:03:25 +05303339#undef MAX_CONCURRENT_MATRIX
3340#undef MATRIX_CONFIG_PARAM_SET_SIZE_MAX
3341
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05303342/**
3343 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
3344 * @wiphy: pointer to wireless wiphy structure.
3345 * @wdev: pointer to wireless_dev structure.
3346 * @data: Pointer to the data to be passed via vendor interface
3347 * @data_len:Length of the data to be passed
3348 *
3349 * Retrieves the concurrency feature set matrix
3350 *
3351 * Return: 0 on success, negative errno on failure
3352 */
3353static int
3354wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
3355 struct wireless_dev *wdev,
3356 const void *data,
3357 int data_len)
3358{
3359 int ret;
3360
3361 cds_ssr_protect(__func__);
3362 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
3363 data, data_len);
3364 cds_ssr_unprotect(__func__);
3365
3366 return ret;
3367}
3368
3369/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003370 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
3371 * @feature_flags: pointer to the byte array of features.
3372 * @feature: Feature to be turned ON in the byte array.
3373 *
3374 * Return: None
3375 *
3376 * This is called to turn ON or SET the feature flag for the requested feature.
3377 **/
3378#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07003379static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
3380 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003381{
3382 uint32_t index;
3383 uint8_t bit_mask;
3384
3385 index = feature / NUM_BITS_IN_BYTE;
3386 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
3387 feature_flags[index] |= bit_mask;
3388}
3389
3390/**
3391 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
3392 * @wiphy: pointer to wireless wiphy structure.
3393 * @wdev: pointer to wireless_dev structure.
3394 * @data: Pointer to the data to be passed via vendor interface
3395 * @data_len:Length of the data to be passed
3396 *
3397 * This is called when wlan driver needs to send supported feature set to
3398 * supplicant upon a request/query from the supplicant.
3399 *
3400 * Return: Return the Success or Failure code.
3401 **/
3402#define MAX_CONCURRENT_CHAN_ON_24G 2
3403#define MAX_CONCURRENT_CHAN_ON_5G 2
3404static int
3405__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
3406 struct wireless_dev *wdev,
3407 const void *data, int data_len)
3408{
3409 struct sk_buff *skb = NULL;
3410 uint32_t dbs_capability = 0;
3411 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303412 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003413 int ret_val;
3414
3415 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07003416 struct hdd_context *hdd_ctx_ptr = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003417
Dustin Brownfdf17c12018-03-14 12:55:34 -07003418 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08003419
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003420 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
3421 if (ret_val)
3422 return ret_val;
3423
Anurag Chouhan6d760662016-02-20 16:05:43 +05303424 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003425 hdd_err("Command not allowed in FTM mode");
3426 return -EPERM;
3427 }
3428
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07003429 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003430 hdd_debug("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003431 wlan_hdd_cfg80211_set_feature(feature_flags,
3432 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
3433 }
3434
3435 wlan_hdd_cfg80211_set_feature(feature_flags,
3436 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08003437 if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx_ptr->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003438 wlan_hdd_cfg80211_set_feature(feature_flags,
3439 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07003440
3441 if (wma_is_p2p_lo_capable())
3442 wlan_hdd_cfg80211_set_feature(feature_flags,
3443 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
3444
yeshwanth sriram guntuka1413dfb2017-06-23 14:09:48 +05303445 if (hdd_ctx_ptr->config->oce_sta_enabled)
3446 wlan_hdd_cfg80211_set_feature(feature_flags,
3447 QCA_WLAN_VENDOR_FEATURE_OCE_STA);
3448
3449 if (hdd_ctx_ptr->config->oce_sap_enabled)
3450 wlan_hdd_cfg80211_set_feature(feature_flags,
3451 QCA_WLAN_VENDOR_FEATURE_OCE_STA_CFON);
3452
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003453 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
3454 NLMSG_HDRLEN);
3455
3456 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003457 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003458 return -ENOMEM;
3459 }
3460
3461 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
3462 sizeof(feature_flags), feature_flags))
3463 goto nla_put_failure;
3464
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08003465 ret = policy_mgr_get_dbs_hw_modes(hdd_ctx_ptr->hdd_psoc,
3466 &one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303467 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003468 if (one_by_one_dbs)
3469 dbs_capability = DRV_DBS_CAPABILITY_1X1;
3470
3471 if (two_by_two_dbs)
3472 dbs_capability = DRV_DBS_CAPABILITY_2X2;
3473
3474 if (!one_by_one_dbs && !two_by_two_dbs)
3475 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
3476 } else {
3477 hdd_err("wma_get_dbs_hw_mode failed");
3478 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
3479 }
3480
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003481 hdd_debug("dbs_capability is %d", dbs_capability);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003482
3483 if (nla_put_u32(skb,
Ganesh Kondabattinid921ed92017-06-20 16:40:48 +05303484 QCA_WLAN_VENDOR_ATTR_CONCURRENCY_CAPA,
3485 dbs_capability))
3486 goto nla_put_failure;
3487
3488
3489 if (nla_put_u32(skb,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003490 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
3491 MAX_CONCURRENT_CHAN_ON_24G))
3492 goto nla_put_failure;
3493
3494 if (nla_put_u32(skb,
3495 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
3496 MAX_CONCURRENT_CHAN_ON_5G))
3497 goto nla_put_failure;
3498
3499 return cfg80211_vendor_cmd_reply(skb);
3500
3501nla_put_failure:
3502 kfree_skb(skb);
3503 return -EINVAL;
3504}
3505
3506/**
3507 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
3508 * @wiphy: pointer to wireless wiphy structure.
3509 * @wdev: pointer to wireless_dev structure.
3510 * @data: Pointer to the data to be passed via vendor interface
3511 * @data_len:Length of the data to be passed
3512 *
3513 * This is called when wlan driver needs to send supported feature set to
3514 * supplicant upon a request/query from the supplicant.
3515 *
3516 * Return: Return the Success or Failure code.
3517 */
3518static int
3519wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
3520 struct wireless_dev *wdev,
3521 const void *data, int data_len)
3522{
3523 int ret;
3524
3525 cds_ssr_protect(__func__);
3526 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
3527 data, data_len);
3528 cds_ssr_unprotect(__func__);
3529
3530 return ret;
3531}
3532
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303533#define PARAM_NUM_NW \
3534 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
3535#define PARAM_SET_BSSID \
3536 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003537#define PARAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303538#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Ravi Kumar Bokka6cb9b372017-06-08 20:12:39 +05303539#define MAX_ROAMING_PARAM \
3540 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003541#define PARAM_NUM_BSSID \
3542 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID
3543#define PARAM_BSSID_PREFS \
3544 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS
3545#define PARAM_ROAM_BSSID \
3546 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID
3547#define PARAM_RSSI_MODIFIER \
3548 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER
3549#define PARAMS_NUM_BSSID \
3550 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID
3551#define PARAM_BSSID_PARAMS \
3552 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS
3553#define PARAM_A_BAND_BOOST_THLD \
3554 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD
3555#define PARAM_A_BAND_PELT_THLD \
3556 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD
3557#define PARAM_A_BAND_BOOST_FACTOR \
3558 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR
3559#define PARAM_A_BAND_PELT_FACTOR \
3560 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR
3561#define PARAM_A_BAND_MAX_BOOST \
3562 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST
3563#define PARAM_ROAM_HISTERESYS \
3564 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS
3565#define PARAM_RSSI_TRIGGER \
3566 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER
3567#define PARAM_ROAM_ENABLE \
3568 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE
3569
Ravi Kumar Bokka6cb9b372017-06-08 20:12:39 +05303570
3571static const struct nla_policy
3572wlan_hdd_set_roam_param_policy[MAX_ROAMING_PARAM + 1] = {
3573 [QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD] = {.type = NLA_U32},
3574 [QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID] = {.type = NLA_U32},
3575 [PARAM_NUM_NW] = {.type = NLA_U32},
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003576 [PARAM_A_BAND_BOOST_FACTOR] = {.type = NLA_U32},
3577 [PARAM_A_BAND_PELT_FACTOR] = {.type = NLA_U32},
3578 [PARAM_A_BAND_MAX_BOOST] = {.type = NLA_U32},
3579 [PARAM_ROAM_HISTERESYS] = {.type = NLA_S32},
3580 [PARAM_A_BAND_BOOST_THLD] = {.type = NLA_S32},
Srinivas Girigowda4ffe7c82017-07-18 11:45:23 -07003581 [PARAM_A_BAND_PELT_THLD] = {.type = NLA_S32},
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003582 [PARAM_RSSI_TRIGGER] = {.type = NLA_U32},
3583 [PARAM_ROAM_ENABLE] = { .type = NLA_S32},
3584 [PARAM_NUM_BSSID] = {.type = NLA_U32},
3585 [PARAM_RSSI_MODIFIER] = {.type = NLA_U32},
3586 [PARAMS_NUM_BSSID] = {.type = NLA_U32},
3587 [PARAM_ROAM_BSSID] = {.type = NLA_UNSPEC, .len = QDF_MAC_ADDR_SIZE},
3588 [PARAM_SET_BSSID] = {.type = NLA_UNSPEC, .len = QDF_MAC_ADDR_SIZE},
Ravi Kumar Bokka6cb9b372017-06-08 20:12:39 +05303589};
3590
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003591/**
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003592 * hdd_set_white_list() - parse white list
3593 * @hddctx: HDD context
3594 * @roam_params: roam params
3595 * @tb: list of attributes
3596 * @session_id: session id
3597 *
3598 * Return: 0 on success; error number on failure
3599 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07003600static int hdd_set_white_list(struct hdd_context *hddctx,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003601 struct roam_ext_params *roam_params,
3602 struct nlattr **tb, uint8_t session_id)
3603{
3604 int rem, i;
3605 uint32_t buf_len = 0, count;
3606 struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
3607 struct nlattr *curr_attr = NULL;
3608
3609 i = 0;
3610 if (tb[PARAM_NUM_NW]) {
3611 count = nla_get_u32(tb[PARAM_NUM_NW]);
3612 } else {
3613 hdd_err("Number of networks is not provided");
3614 goto fail;
3615 }
3616
3617 if (count && tb[PARAM_SSID_LIST]) {
3618 nla_for_each_nested(curr_attr,
3619 tb[PARAM_SSID_LIST], rem) {
Dustin Brown4ea21db2018-01-05 14:13:17 -08003620 if (wlan_cfg80211_nla_parse(tb2,
3621 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
3622 nla_data(curr_attr),
3623 nla_len(curr_attr),
3624 wlan_hdd_set_roam_param_policy)) {
3625 hdd_err("nla_parse failed");
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003626 goto fail;
3627 }
3628 /* Parse and Fetch allowed SSID list*/
3629 if (!tb2[PARAM_LIST_SSID]) {
3630 hdd_err("attr allowed ssid failed");
3631 goto fail;
3632 }
3633 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
3634 /*
3635 * Upper Layers include a null termination
3636 * character. Check for the actual permissible
3637 * length of SSID and also ensure not to copy
3638 * the NULL termination character to the driver
3639 * buffer.
3640 */
3641 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
3642 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
3643 nla_memcpy(roam_params->ssid_allowed_list[i].ssId,
3644 tb2[PARAM_LIST_SSID], buf_len - 1);
3645 roam_params->ssid_allowed_list[i].length = buf_len - 1;
3646 hdd_debug("SSID[%d]: %.*s,length = %d",
3647 i,
3648 roam_params->ssid_allowed_list[i].length,
3649 roam_params->ssid_allowed_list[i].ssId,
3650 roam_params->ssid_allowed_list[i].length);
3651 i++;
3652 } else {
3653 hdd_err("Invalid buffer length");
3654 }
3655 }
3656 }
3657
3658 if (i != count) {
3659 hdd_err("Invalid number of SSIDs i = %d, count = %d", i, count);
3660 goto fail;
3661 }
3662
3663 roam_params->num_ssid_allowed_list = i;
3664 hdd_debug("Num of Allowed SSID %d", roam_params->num_ssid_allowed_list);
3665 sme_update_roam_params(hddctx->hHal, session_id,
3666 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
3667 return 0;
3668
3669fail:
3670 return -EINVAL;
3671}
3672
3673/**
3674 * hdd_set_bssid_prefs() - parse set bssid prefs
3675 * @hddctx: HDD context
3676 * @roam_params: roam params
3677 * @tb: list of attributes
3678 * @session_id: session id
3679 *
3680 * Return: 0 on success; error number on failure
3681 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07003682static int hdd_set_bssid_prefs(struct hdd_context *hddctx,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003683 struct roam_ext_params *roam_params,
3684 struct nlattr **tb, uint8_t session_id)
3685{
3686 int rem, i;
3687 uint32_t count;
3688 struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
3689 struct nlattr *curr_attr = NULL;
3690
3691 /* Parse and fetch number of preferred BSSID */
3692 if (!tb[PARAM_NUM_BSSID]) {
3693 hdd_err("attr num of preferred bssid failed");
3694 goto fail;
3695 }
3696 count = nla_get_u32(tb[PARAM_NUM_BSSID]);
3697 if (count > MAX_BSSID_FAVORED) {
3698 hdd_err("Preferred BSSID count %u exceeds max %u",
3699 count, MAX_BSSID_FAVORED);
3700 goto fail;
3701 }
3702 hdd_debug("Num of Preferred BSSID (%d)", count);
3703 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS]) {
3704 hdd_err("attr Preferred BSSID failed");
3705 goto fail;
3706 }
3707
3708 i = 0;
3709 nla_for_each_nested(curr_attr,
3710 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
3711 rem) {
3712 if (i == count) {
3713 hdd_warn("Ignoring excess Preferred BSSID");
3714 break;
3715 }
3716
Dustin Brown4ea21db2018-01-05 14:13:17 -08003717 if (wlan_cfg80211_nla_parse(tb2,
3718 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3719 nla_data(curr_attr),
3720 nla_len(curr_attr),
3721 wlan_hdd_set_roam_param_policy)) {
3722 hdd_err("nla_parse failed");
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003723 goto fail;
3724 }
3725 /* Parse and fetch MAC address */
3726 if (!tb2[PARAM_ROAM_BSSID]) {
3727 hdd_err("attr mac address failed");
3728 goto fail;
3729 }
3730 nla_memcpy(roam_params->bssid_favored[i].bytes,
3731 tb2[PARAM_ROAM_BSSID],
3732 QDF_MAC_ADDR_SIZE);
3733 hdd_debug(MAC_ADDRESS_STR,
3734 MAC_ADDR_ARRAY(roam_params->bssid_favored[i].bytes));
3735 /* Parse and fetch preference factor*/
3736 if (!tb2[PARAM_RSSI_MODIFIER]) {
3737 hdd_err("BSSID Preference score failed");
3738 goto fail;
3739 }
3740 roam_params->bssid_favored_factor[i] = nla_get_u32(
3741 tb2[PARAM_RSSI_MODIFIER]);
3742 hdd_debug("BSSID Preference score (%d)",
3743 roam_params->bssid_favored_factor[i]);
3744 i++;
3745 }
3746 if (i < count)
3747 hdd_warn("Num Preferred BSSID %u less than expected %u",
3748 i, count);
3749
3750 roam_params->num_bssid_favored = i;
3751 sme_update_roam_params(hddctx->hHal, session_id,
3752 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3753
3754 return 0;
3755
3756fail:
3757 return -EINVAL;
3758}
3759
3760/**
3761 * hdd_set_blacklist_bssid() - parse set blacklist bssid
3762 * @hddctx: HDD context
3763 * @roam_params: roam params
3764 * @tb: list of attributes
3765 * @session_id: session id
3766 *
3767 * Return: 0 on success; error number on failure
3768 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07003769static int hdd_set_blacklist_bssid(struct hdd_context *hddctx,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003770 struct roam_ext_params *roam_params,
3771 struct nlattr **tb,
3772 uint8_t session_id)
3773{
3774 int rem, i;
3775 uint32_t count;
3776 struct nlattr *tb2[MAX_ROAMING_PARAM + 1];
3777 struct nlattr *curr_attr = NULL;
3778
3779 /* Parse and fetch number of blacklist BSSID */
3780 if (!tb[PARAMS_NUM_BSSID]) {
3781 hdd_err("attr num of blacklist bssid failed");
3782 goto fail;
3783 }
3784 count = nla_get_u32(tb[PARAMS_NUM_BSSID]);
3785 if (count > MAX_BSSID_AVOID_LIST) {
3786 hdd_err("Blacklist BSSID count %u exceeds max %u",
3787 count, MAX_BSSID_AVOID_LIST);
3788 goto fail;
3789 }
3790 hdd_debug("Num of blacklist BSSID (%d)", count);
3791
3792 i = 0;
3793 if (count && tb[PARAM_BSSID_PARAMS]) {
3794 nla_for_each_nested(curr_attr,
3795 tb[PARAM_BSSID_PARAMS],
3796 rem) {
3797 if (i == count) {
3798 hdd_warn("Ignoring excess Blacklist BSSID");
3799 break;
3800 }
3801
Dustin Brown4ea21db2018-01-05 14:13:17 -08003802 if (wlan_cfg80211_nla_parse(tb2,
Dustin Brown3fb15042017-08-15 15:54:49 -07003803 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3804 nla_data(curr_attr),
3805 nla_len(curr_attr),
3806 wlan_hdd_set_roam_param_policy)) {
Dustin Brown4ea21db2018-01-05 14:13:17 -08003807 hdd_err("nla_parse failed");
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003808 goto fail;
3809 }
3810 /* Parse and fetch MAC address */
3811 if (!tb2[PARAM_SET_BSSID]) {
3812 hdd_err("attr blacklist addr failed");
3813 goto fail;
3814 }
3815 nla_memcpy(roam_params->bssid_avoid_list[i].bytes,
3816 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3817 hdd_debug(MAC_ADDRESS_STR,
3818 MAC_ADDR_ARRAY(roam_params->bssid_avoid_list[i].bytes));
3819 i++;
3820 }
3821 }
3822
3823 if (i < count)
3824 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3825 i, count);
3826
3827 roam_params->num_bssid_avoid_list = i;
3828 sme_update_roam_params(hddctx->hHal, session_id,
3829 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3830
3831 return 0;
3832fail:
3833 return -EINVAL;
3834}
3835
3836/**
3837 * hdd_set_ext_roam_params() - parse ext roam params
3838 * @hddctx: HDD context
3839 * @roam_params: roam params
3840 * @tb: list of attributes
3841 * @session_id: session id
3842 *
3843 * Return: 0 on success; error number on failure
3844 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07003845static int hdd_set_ext_roam_params(struct hdd_context *hddctx,
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003846 const void *data, int data_len,
3847 uint8_t session_id,
3848 struct roam_ext_params *roam_params)
3849{
3850 uint32_t cmd_type, req_id;
3851 struct nlattr *tb[MAX_ROAMING_PARAM + 1];
3852 int ret;
3853
Dustin Brown4ea21db2018-01-05 14:13:17 -08003854 if (wlan_cfg80211_nla_parse(tb, MAX_ROAMING_PARAM, data, data_len,
3855 wlan_hdd_set_roam_param_policy)) {
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003856 hdd_err("Invalid ATTR");
3857 return -EINVAL;
3858 }
3859 /* Parse and fetch Command Type */
3860 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
3861 hdd_err("roam cmd type failed");
3862 goto fail;
3863 }
3864
3865 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
3866 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
3867 hdd_err("attr request id failed");
3868 goto fail;
3869 }
3870 req_id = nla_get_u32(
3871 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
3872 hdd_debug("Req Id: %u Cmd Type: %u", req_id, cmd_type);
3873 switch (cmd_type) {
3874 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
3875 ret = hdd_set_white_list(hddctx, roam_params, tb, session_id);
3876 if (ret)
3877 goto fail;
3878 break;
3879
3880 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
3881 /* Parse and fetch 5G Boost Threshold */
3882 if (!tb[PARAM_A_BAND_BOOST_THLD]) {
3883 hdd_err("5G boost threshold failed");
3884 goto fail;
3885 }
3886 roam_params->raise_rssi_thresh_5g = nla_get_s32(
3887 tb[PARAM_A_BAND_BOOST_THLD]);
3888 hdd_debug("5G Boost Threshold (%d)",
3889 roam_params->raise_rssi_thresh_5g);
3890 /* Parse and fetch 5G Penalty Threshold */
Srinivas Girigowda4ffe7c82017-07-18 11:45:23 -07003891 if (!tb[PARAM_A_BAND_PELT_THLD]) {
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003892 hdd_err("5G penalty threshold failed");
3893 goto fail;
3894 }
3895 roam_params->drop_rssi_thresh_5g = nla_get_s32(
Srinivas Girigowda4ffe7c82017-07-18 11:45:23 -07003896 tb[PARAM_A_BAND_PELT_THLD]);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003897 hdd_debug("5G Penalty Threshold (%d)",
3898 roam_params->drop_rssi_thresh_5g);
3899 /* Parse and fetch 5G Boost Factor */
3900 if (!tb[PARAM_A_BAND_BOOST_FACTOR]) {
3901 hdd_err("5G boost Factor failed");
3902 goto fail;
3903 }
3904 roam_params->raise_factor_5g = nla_get_u32(
3905 tb[PARAM_A_BAND_BOOST_FACTOR]);
3906 hdd_debug("5G Boost Factor (%d)",
3907 roam_params->raise_factor_5g);
3908 /* Parse and fetch 5G Penalty factor */
3909 if (!tb[PARAM_A_BAND_PELT_FACTOR]) {
3910 hdd_err("5G Penalty Factor failed");
3911 goto fail;
3912 }
3913 roam_params->drop_factor_5g = nla_get_u32(
3914 tb[PARAM_A_BAND_PELT_FACTOR]);
3915 hdd_debug("5G Penalty factor (%d)",
3916 roam_params->drop_factor_5g);
3917 /* Parse and fetch 5G Max Boost */
3918 if (!tb[PARAM_A_BAND_MAX_BOOST]) {
3919 hdd_err("5G Max Boost failed");
3920 goto fail;
3921 }
3922 roam_params->max_raise_rssi_5g = nla_get_u32(
3923 tb[PARAM_A_BAND_MAX_BOOST]);
3924 hdd_debug("5G Max Boost (%d)",
3925 roam_params->max_raise_rssi_5g);
3926 /* Parse and fetch Rssi Diff */
3927 if (!tb[PARAM_ROAM_HISTERESYS]) {
3928 hdd_err("Rssi Diff failed");
3929 goto fail;
3930 }
3931 roam_params->rssi_diff = nla_get_s32(
3932 tb[PARAM_ROAM_HISTERESYS]);
3933 hdd_debug("RSSI Diff (%d)",
3934 roam_params->rssi_diff);
3935 /* Parse and fetch Alert Rssi Threshold */
3936 if (!tb[PARAM_RSSI_TRIGGER]) {
3937 hdd_err("Alert Rssi Threshold failed");
3938 goto fail;
3939 }
3940 roam_params->alert_rssi_threshold = nla_get_u32(
3941 tb[PARAM_RSSI_TRIGGER]);
3942 hdd_debug("Alert RSSI Threshold (%d)",
3943 roam_params->alert_rssi_threshold);
3944 sme_update_roam_params(hddctx->hHal, session_id,
3945 roam_params,
3946 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
3947 break;
3948 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
3949 /* Parse and fetch Activate Good Rssi Roam */
3950 if (!tb[PARAM_ROAM_ENABLE]) {
3951 hdd_err("Activate Good Rssi Roam failed");
3952 goto fail;
3953 }
3954 roam_params->good_rssi_roam = nla_get_s32(
3955 tb[PARAM_ROAM_ENABLE]);
3956 hdd_debug("Activate Good Rssi Roam (%d)",
3957 roam_params->good_rssi_roam);
3958 sme_update_roam_params(hddctx->hHal, session_id,
3959 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
3960 break;
3961 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
3962 ret = hdd_set_bssid_prefs(hddctx, roam_params, tb, session_id);
3963 if (ret)
3964 goto fail;
3965 break;
3966 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3967 ret = hdd_set_blacklist_bssid(hddctx, roam_params, tb, session_id);
3968 if (ret)
3969 goto fail;
3970 break;
3971 }
3972
3973 return 0;
3974
3975fail:
3976 return -EINVAL;
3977}
3978
3979/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003980 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
3981 * @wiphy: The wiphy structure
3982 * @wdev: The wireless device
3983 * @data: Data passed by framework
3984 * @data_len: Parameters to be configured passed as data
3985 *
3986 * The roaming related parameters are configured by the framework
3987 * using this interface.
3988 *
3989 * Return: Return either success or failure code.
3990 */
3991static int
3992__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3993 struct wireless_dev *wdev, const void *data, int data_len)
3994{
3995 struct net_device *dev = wdev->netdev;
Jeff Johnsonce2ba702017-10-02 13:30:24 -07003996 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -07003997 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07003998 struct roam_ext_params *roam_params = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003999 int ret;
4000
Dustin Brownfdf17c12018-03-14 12:55:34 -07004001 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08004002
Anurag Chouhan6d760662016-02-20 16:05:43 +05304003 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004004 hdd_err("Command not allowed in FTM mode");
4005 return -EPERM;
4006 }
4007
Jeff Johnsonb8944722017-09-03 09:03:19 -07004008 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304009 if (ret)
4010 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004011
Jeff Johnsonb8944722017-09-03 09:03:19 -07004012 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05304013 hdd_err("Driver Modules are closed");
4014 return -EINVAL;
4015 }
4016
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004017 roam_params = qdf_mem_malloc(sizeof(*roam_params));
4018 if (!roam_params) {
4019 hdd_err("failed to allocate memory");
4020 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004021 }
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004022
Jeff Johnsonb8944722017-09-03 09:03:19 -07004023 ret = hdd_set_ext_roam_params(hdd_ctx, data, data_len,
Jeff Johnson1b780e42017-10-31 14:11:45 -07004024 adapter->session_id, roam_params);
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004025 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004026 goto fail;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05304027
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004028 if (roam_params)
4029 qdf_mem_free(roam_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004030 return 0;
4031fail:
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004032 if (roam_params)
4033 qdf_mem_free(roam_params);
4034
4035 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004036}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05304037#undef PARAM_NUM_NW
4038#undef PARAM_SET_BSSID
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004039#undef PARAM_SSID_LIST
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05304040#undef PARAM_LIST_SSID
Srinivas Girigowda72f30392017-07-13 18:55:09 -07004041#undef MAX_ROAMING_PARAM
4042#undef PARAM_NUM_BSSID
4043#undef PARAM_BSSID_PREFS
4044#undef PARAM_ROAM_BSSID
4045#undef PARAM_RSSI_MODIFIER
4046#undef PARAMS_NUM_BSSID
4047#undef PARAM_BSSID_PARAMS
4048#undef PARAM_A_BAND_BOOST_THLD
4049#undef PARAM_A_BAND_PELT_THLD
4050#undef PARAM_A_BAND_BOOST_FACTOR
4051#undef PARAM_A_BAND_PELT_FACTOR
4052#undef PARAM_A_BAND_MAX_BOOST
4053#undef PARAM_ROAM_HISTERESYS
4054#undef PARAM_RSSI_TRIGGER
4055#undef PARAM_ROAM_ENABLE
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05304056
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004057
4058/**
4059 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
4060 * @wiphy: pointer to wireless wiphy structure.
4061 * @wdev: pointer to wireless_dev structure.
4062 * @data: Pointer to the data to be passed via vendor interface
4063 * @data_len:Length of the data to be passed
4064 *
4065 * Return: Return the Success or Failure code.
4066 */
4067static int
4068wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
4069 struct wireless_dev *wdev,
4070 const void *data,
4071 int data_len)
4072{
4073 int ret;
4074
4075 cds_ssr_protect(__func__);
4076 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
4077 data, data_len);
4078 cds_ssr_unprotect(__func__);
4079
4080 return ret;
4081}
4082
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304083#define PWR_SAVE_FAIL_CMD_INDEX \
4084 QCA_NL80211_VENDOR_SUBCMD_PWR_SAVE_FAIL_DETECTED_INDEX
4085/**
4086 * hdd_chip_pwr_save_fail_detected_cb() - chip power save failure detected
4087 * callback
4088 * @hddctx: HDD context
4089 * @data: chip power save failure detected data
4090 *
4091 * This function reads the chip power save failure detected data and fill in
4092 * the skb with NL attributes and send up the NL event.
4093 * This callback execute in atomic context and must not invoke any
4094 * blocking calls.
4095 *
4096 * Return: none
4097 */
4098void hdd_chip_pwr_save_fail_detected_cb(void *hddctx,
4099 struct chip_pwr_save_fail_detected_params
4100 *data)
4101{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004102 struct hdd_context *hdd_ctx = hddctx;
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304103 struct sk_buff *skb;
4104 int flags = cds_get_gfp_flags();
4105
Dustin Brown491d54b2018-03-14 12:39:11 -07004106 hdd_enter();
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304107
4108 if (wlan_hdd_validate_context(hdd_ctx))
4109 return;
4110
4111 if (!data) {
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -07004112 hdd_debug("data is null");
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304113 return;
4114 }
4115
4116 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
4117 NULL, NLMSG_HDRLEN +
4118 sizeof(data->failure_reason_code) +
4119 NLMSG_HDRLEN, PWR_SAVE_FAIL_CMD_INDEX,
4120 flags);
4121
4122 if (!skb) {
Dustin Brown5e89ef82018-03-14 11:50:23 -07004123 hdd_info("cfg80211_vendor_event_alloc failed");
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304124 return;
4125 }
4126
Dustin Brownbacc48f2018-03-14 14:48:44 -07004127 hdd_debug("failure reason code: %u", data->failure_reason_code);
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304128
4129 if (nla_put_u32(skb,
4130 QCA_ATTR_CHIP_POWER_SAVE_FAILURE_REASON,
4131 data->failure_reason_code))
4132 goto fail;
4133
4134 cfg80211_vendor_event(skb, flags);
Dustin Browne74003f2018-03-14 12:51:58 -07004135 hdd_exit();
Ravi Kumar Bokka05c14e52017-03-27 14:48:23 +05304136 return;
4137
4138fail:
4139 kfree_skb(skb);
4140}
4141#undef PWR_SAVE_FAIL_CMD_INDEX
4142
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004143static const struct nla_policy
4144wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
4145 +1] = {
4146 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
4147};
4148
4149/**
4150 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
4151 * @hdd_ctx: HDD context
4152 * @device_mode: device mode
4153 * Return: bool
4154 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004155static bool wlan_hdd_check_dfs_channel_for_adapter(struct hdd_context *hdd_ctx,
Jeff Johnsonc1e62782017-11-09 09:50:17 -08004156 enum QDF_OPMODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004157{
Jeff Johnsone5006672017-08-29 14:39:02 -07004158 struct hdd_adapter *adapter;
Jeff Johnson87251032017-08-29 13:31:11 -07004159 struct hdd_ap_ctx *ap_ctx;
Jeff Johnson40dae4e2017-08-29 14:00:25 -07004160 struct hdd_station_ctx *sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004161
Dustin Brown920397d2017-12-13 16:27:50 -08004162 hdd_for_each_adapter(hdd_ctx, adapter) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004163 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08004164 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004165 ap_ctx =
4166 WLAN_HDD_GET_AP_CTX_PTR(adapter);
4167
4168 /*
4169 * if there is SAP already running on DFS channel,
4170 * do not disable scan on dfs channels. Note that
4171 * with SAP on DFS, there cannot be conurrency on
4172 * single radio. But then we can have multiple
4173 * radios !!
4174 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07004175 if (CHANNEL_STATE_DFS == wlan_reg_get_channel_state(
4176 hdd_ctx->hdd_pdev,
Jeff Johnson01206862017-10-27 20:55:59 -07004177 ap_ctx->operating_channel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004178 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004179 return true;
4180 }
4181 }
4182
4183 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08004184 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004185 sta_ctx =
4186 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
4187
4188 /*
4189 * if STA is already connected on DFS channel,
4190 * do not disable scan on dfs channels
4191 */
4192 if (hdd_conn_is_connected(sta_ctx) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07004193 (CHANNEL_STATE_DFS ==
4194 wlan_reg_get_channel_state(hdd_ctx->hdd_pdev,
4195 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07004196 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004197 return true;
4198 }
4199 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004200 }
4201
4202 return false;
4203}
4204
4205/**
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004206 * wlan_hdd_enable_dfs_chan_scan() - disable/enable DFS channels
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004207 * @hdd_ctx: HDD context within host driver
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004208 * @enable_dfs_channels: If true, DFS channels can be used for scanning
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004209 *
4210 * Loops through devices to see who is operating on DFS channels
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004211 * and then disables/enables DFS channels.
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004212 * Fails the disable request if any device is active on a DFS channel.
4213 *
4214 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004215 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004216
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004217int wlan_hdd_enable_dfs_chan_scan(struct hdd_context *hdd_ctx,
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004218 bool enable_dfs_channels)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004219{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304220 QDF_STATUS status;
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004221 bool err;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004222
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004223 if (enable_dfs_channels == hdd_ctx->config->enableDFSChnlScan) {
4224 hdd_info("DFS channels are already %s",
4225 enable_dfs_channels ? "enabled" : "disabled");
4226 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004227 }
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004228
4229 if (!enable_dfs_channels) {
4230 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
4231 QDF_STA_MODE);
4232 if (err)
4233 return -EOPNOTSUPP;
4234
4235 err = wlan_hdd_check_dfs_channel_for_adapter(hdd_ctx,
4236 QDF_SAP_MODE);
4237 if (err)
4238 return -EOPNOTSUPP;
4239 }
4240
4241 hdd_ctx->config->enableDFSChnlScan = enable_dfs_channels;
4242
Min Liu5eaf7242018-03-13 17:32:15 +08004243 status = sme_enable_dfs_chan_scan(hdd_ctx->hHal, enable_dfs_channels);
4244 if (QDF_IS_STATUS_ERROR(status)) {
4245 hdd_err("Failed to set DFS channel scan flag to %d",
4246 enable_dfs_channels);
4247 return qdf_status_to_os_return(status);
4248 }
4249
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004250 hdd_abort_mac_scan_all_adapters(hdd_ctx);
4251
4252 /* pass dfs channel status to regulatory component */
4253 status = ucfg_reg_enable_dfs_channels(hdd_ctx->hdd_pdev,
4254 enable_dfs_channels);
4255
4256 if (QDF_IS_STATUS_ERROR(status))
4257 hdd_err("Failed to %s DFS channels",
4258 enable_dfs_channels ? "enable" : "disable");
4259
4260 return qdf_status_to_os_return(status);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004261}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004262
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004263/**
4264 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
4265 * @wiphy: corestack handler
4266 * @wdev: wireless device
4267 * @data: data
4268 * @data_len: data length
4269 * Return: success(0) or reason code for failure
4270 */
4271static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
4272 struct wireless_dev *wdev,
4273 const void *data,
4274 int data_len)
4275{
4276 struct net_device *dev = wdev->netdev;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004277 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004278 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
4279 int ret_val;
4280 uint32_t no_dfs_flag = 0;
4281
Dustin Brownfdf17c12018-03-14 12:55:34 -07004282 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08004283
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004284 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304285 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004286 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004287
Dustin Brown4ea21db2018-01-05 14:13:17 -08004288 if (wlan_cfg80211_nla_parse(tb,
4289 QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
4290 data, data_len,
4291 wlan_hdd_set_no_dfs_flag_config_policy)) {
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004292 hdd_err("invalid attr");
4293 return -EINVAL;
4294 }
4295
4296 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
4297 hdd_err("attr dfs flag failed");
4298 return -EINVAL;
4299 }
4300
4301 no_dfs_flag = nla_get_u32(
4302 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
4303
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004304 hdd_debug("DFS flag: %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004305
4306 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07004307 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08004308 return -EINVAL;
4309 }
4310
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -07004311 ret_val = wlan_hdd_enable_dfs_chan_scan(hdd_ctx, !no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004312 return ret_val;
4313}
4314
4315/**
4316 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
4317 *
4318 * @wiphy: wiphy device pointer
4319 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07004320 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004321 * @data_len: Buffer length
4322 *
4323 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
4324 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
4325 *
4326 * Return: EOK or other error codes.
4327 */
4328
4329static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
4330 struct wireless_dev *wdev,
4331 const void *data,
4332 int data_len)
4333{
4334 int ret;
4335
4336 cds_ssr_protect(__func__);
4337 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
4338 data, data_len);
4339 cds_ssr_unprotect(__func__);
4340
4341 return ret;
4342}
4343
Manikandan Mohan80dea792016-04-28 16:36:48 -07004344static const struct nla_policy
4345wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
4346 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
4347};
4348
4349/**
4350 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
4351 * @wiphy: wiphy device pointer
4352 * @wdev: wireless device pointer
4353 * @data: Vendor command data buffer
4354 * @data_len: Buffer length
4355 *
4356 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
4357 * setup WISA Mode features.
4358 *
4359 * Return: Success(0) or reason code for failure
4360 */
4361static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
4362 struct wireless_dev *wdev, const void *data, int data_len)
4363{
4364 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07004365 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004366 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Manikandan Mohan80dea792016-04-28 16:36:48 -07004367 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
4368 struct sir_wisa_params wisa;
4369 int ret_val;
4370 QDF_STATUS status;
4371 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07004372 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
4373 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07004374
Dustin Brownfdf17c12018-03-14 12:55:34 -07004375 hdd_enter_dev(dev);
Manikandan Mohan80dea792016-04-28 16:36:48 -07004376 ret_val = wlan_hdd_validate_context(hdd_ctx);
4377 if (ret_val)
4378 goto err;
4379
4380 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
4381 hdd_err("Command not allowed in FTM mode");
4382 return -EPERM;
4383 }
4384
Dustin Brown4ea21db2018-01-05 14:13:17 -08004385 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data,
4386 data_len, wlan_hdd_wisa_cmd_policy)) {
Manikandan Mohan80dea792016-04-28 16:36:48 -07004387 hdd_err("Invalid WISA cmd attributes");
4388 ret_val = -EINVAL;
4389 goto err;
4390 }
4391 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
4392 hdd_err("Invalid WISA mode");
4393 ret_val = -EINVAL;
4394 goto err;
4395 }
4396
4397 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004398 hdd_debug("WISA Mode: %d", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07004399 wisa.mode = wisa_mode;
Jeff Johnson1b780e42017-10-31 14:11:45 -07004400 wisa.vdev_id = adapter->session_id;
Manikandan Mohan80dea792016-04-28 16:36:48 -07004401 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07004402 if (!QDF_IS_STATUS_SUCCESS(status)) {
4403 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07004404 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07004405 }
4406 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07004407 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08004408 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
4409 (struct cdp_pdev *)pdev,
Jeff Johnson1b780e42017-10-31 14:11:45 -07004410 adapter->session_id),
Leo Changfdb45c32016-10-28 11:09:23 -07004411 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07004412err:
Dustin Browne74003f2018-03-14 12:51:58 -07004413 hdd_exit();
Manikandan Mohan80dea792016-04-28 16:36:48 -07004414 return ret_val;
4415}
4416
4417/**
4418 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
4419 * @wiphy: corestack handler
4420 * @wdev: wireless device
4421 * @data: data
4422 * @data_len: data length
4423 *
4424 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
4425 * setup WISA mode features.
4426 *
4427 * Return: Success(0) or reason code for failure
4428 */
4429static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
4430 struct wireless_dev *wdev,
4431 const void *data,
4432 int data_len)
4433{
4434 int ret;
4435
4436 cds_ssr_protect(__func__);
4437 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
4438 cds_ssr_unprotect(__func__);
4439
4440 return ret;
4441}
4442
Anurag Chouhan96919482016-07-13 16:36:57 +05304443/*
4444 * define short names for the global vendor params
4445 * used by __wlan_hdd_cfg80211_get_station_cmd()
4446 */
4447#define STATION_INVALID \
4448 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
4449#define STATION_INFO \
4450 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
4451#define STATION_ASSOC_FAIL_REASON \
4452 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
Will Huang496b36c2017-07-11 16:38:50 +08004453#define STATION_REMOTE \
4454 QCA_WLAN_VENDOR_ATTR_GET_STATION_REMOTE
Anurag Chouhan96919482016-07-13 16:36:57 +05304455#define STATION_MAX \
4456 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
4457
Will Huang496b36c2017-07-11 16:38:50 +08004458/* define short names for get station info attributes */
4459#define LINK_INFO_STANDARD_NL80211_ATTR \
4460 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_LINK_STANDARD_NL80211_ATTR
4461#define AP_INFO_STANDARD_NL80211_ATTR \
4462 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AP_STANDARD_NL80211_ATTR
4463#define INFO_ROAM_COUNT \
4464 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ROAM_COUNT
4465#define INFO_AKM \
4466 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AKM
4467#define WLAN802_11_MODE \
4468 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_802_11_MODE
4469#define AP_INFO_HS20_INDICATION \
4470 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_AP_HS20_INDICATION
4471#define HT_OPERATION \
4472 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_HT_OPERATION
4473#define VHT_OPERATION \
4474 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_VHT_OPERATION
4475#define INFO_ASSOC_FAIL_REASON \
4476 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ASSOC_FAIL_REASON
4477#define REMOTE_MAX_PHY_RATE \
4478 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_MAX_PHY_RATE
4479#define REMOTE_TX_PACKETS \
4480 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_PACKETS
4481#define REMOTE_TX_BYTES \
4482 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_BYTES
4483#define REMOTE_RX_PACKETS \
4484 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_PACKETS
4485#define REMOTE_RX_BYTES \
4486 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_BYTES
4487#define REMOTE_LAST_TX_RATE \
4488 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_LAST_TX_RATE
4489#define REMOTE_LAST_RX_RATE \
4490 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_LAST_RX_RATE
4491#define REMOTE_WMM \
4492 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_WMM
4493#define REMOTE_SUPPORTED_MODE \
4494 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_SUPPORTED_MODE
4495#define REMOTE_AMPDU \
4496 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_AMPDU
4497#define REMOTE_TX_STBC \
4498 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_TX_STBC
4499#define REMOTE_RX_STBC \
4500 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_RX_STBC
4501#define REMOTE_CH_WIDTH\
4502 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_CH_WIDTH
4503#define REMOTE_SGI_ENABLE\
4504 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_SGI_ENABLE
4505#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
4506 #define REMOTE_PAD\
4507 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_PAD
4508#endif
4509
Anurag Chouhan96919482016-07-13 16:36:57 +05304510static const struct nla_policy
4511hdd_get_station_policy[STATION_MAX + 1] = {
4512 [STATION_INFO] = {.type = NLA_FLAG},
4513 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
Will Huang496b36c2017-07-11 16:38:50 +08004514 [STATION_REMOTE] = {.type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE},
Anurag Chouhan96919482016-07-13 16:36:57 +05304515};
4516
4517/**
4518 * hdd_get_station_assoc_fail() - Handle get station assoc fail
4519 * @hdd_ctx: HDD context within host driver
4520 * @wdev: wireless device
4521 *
4522 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
4523 * Validate cmd attributes and send the station info to upper layers.
4524 *
4525 * Return: Success(0) or reason code for failure
4526 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004527static int hdd_get_station_assoc_fail(struct hdd_context *hdd_ctx,
Jeff Johnsone5006672017-08-29 14:39:02 -07004528 struct hdd_adapter *adapter)
Anurag Chouhan96919482016-07-13 16:36:57 +05304529{
4530 struct sk_buff *skb = NULL;
4531 uint32_t nl_buf_len;
Jeff Johnson40dae4e2017-08-29 14:00:25 -07004532 struct hdd_station_ctx *hdd_sta_ctx;
Anurag Chouhan96919482016-07-13 16:36:57 +05304533
4534 nl_buf_len = NLMSG_HDRLEN;
4535 nl_buf_len += sizeof(uint32_t);
4536 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
4537
4538 if (!skb) {
4539 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
4540 return -ENOMEM;
4541 }
4542
4543 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
4544
4545 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
4546 hdd_sta_ctx->conn_info.assoc_status_code)) {
4547 hdd_err("put fail");
4548 goto fail;
4549 }
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05304550
4551 hdd_info("congestion:%d", hdd_sta_ctx->conn_info.cca);
4552 if (nla_put_u32(skb, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
4553 hdd_sta_ctx->conn_info.cca)) {
4554 hdd_err("put fail");
4555 goto fail;
4556 }
4557
Anurag Chouhan96919482016-07-13 16:36:57 +05304558 return cfg80211_vendor_cmd_reply(skb);
4559fail:
4560 if (skb)
4561 kfree_skb(skb);
4562 return -EINVAL;
4563}
4564
4565/**
4566 * hdd_map_auth_type() - transform auth type specific to
4567 * vendor command
4568 * @auth_type: csr auth type
4569 *
4570 * Return: Success(0) or reason code for failure
4571 */
4572static int hdd_convert_auth_type(uint32_t auth_type)
4573{
4574 uint32_t ret_val;
4575
4576 switch (auth_type) {
4577 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
4578 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
4579 break;
4580 case eCSR_AUTH_TYPE_SHARED_KEY:
4581 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
4582 break;
4583 case eCSR_AUTH_TYPE_WPA:
4584 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
4585 break;
4586 case eCSR_AUTH_TYPE_WPA_PSK:
4587 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
4588 break;
4589 case eCSR_AUTH_TYPE_AUTOSWITCH:
4590 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
4591 break;
4592 case eCSR_AUTH_TYPE_WPA_NONE:
4593 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
4594 break;
4595 case eCSR_AUTH_TYPE_RSN:
4596 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
4597 break;
4598 case eCSR_AUTH_TYPE_RSN_PSK:
4599 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
4600 break;
4601 case eCSR_AUTH_TYPE_FT_RSN:
4602 ret_val = QCA_WLAN_AUTH_TYPE_FT;
4603 break;
4604 case eCSR_AUTH_TYPE_FT_RSN_PSK:
4605 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
4606 break;
4607 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
4608 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
4609 break;
4610 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
4611 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
4612 break;
4613 case eCSR_AUTH_TYPE_CCKM_WPA:
4614 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
4615 break;
4616 case eCSR_AUTH_TYPE_CCKM_RSN:
4617 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
4618 break;
4619 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
4620 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
4621 break;
4622 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
4623 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
4624 break;
4625 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
4626 case eCSR_AUTH_TYPE_FAILED:
4627 case eCSR_AUTH_TYPE_NONE:
4628 default:
4629 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
4630 break;
4631 }
4632 return ret_val;
4633}
4634
4635/**
4636 * hdd_map_dot_11_mode() - transform dot11mode type specific to
4637 * vendor command
4638 * @dot11mode: dot11mode
4639 *
4640 * Return: Success(0) or reason code for failure
4641 */
4642static int hdd_convert_dot11mode(uint32_t dot11mode)
4643{
4644 uint32_t ret_val;
4645
4646 switch (dot11mode) {
4647 case eCSR_CFG_DOT11_MODE_11A:
4648 ret_val = QCA_WLAN_802_11_MODE_11A;
4649 break;
4650 case eCSR_CFG_DOT11_MODE_11B:
4651 ret_val = QCA_WLAN_802_11_MODE_11B;
4652 break;
4653 case eCSR_CFG_DOT11_MODE_11G:
4654 ret_val = QCA_WLAN_802_11_MODE_11G;
4655 break;
4656 case eCSR_CFG_DOT11_MODE_11N:
4657 ret_val = QCA_WLAN_802_11_MODE_11N;
4658 break;
4659 case eCSR_CFG_DOT11_MODE_11AC:
4660 ret_val = QCA_WLAN_802_11_MODE_11AC;
4661 break;
4662 case eCSR_CFG_DOT11_MODE_AUTO:
4663 case eCSR_CFG_DOT11_MODE_ABG:
4664 default:
4665 ret_val = QCA_WLAN_802_11_MODE_INVALID;
4666 }
4667 return ret_val;
4668}
4669
4670/**
4671 * hdd_add_tx_bitrate() - add tx bitrate attribute
4672 * @skb: pointer to sk buff
4673 * @hdd_sta_ctx: pointer to hdd station context
4674 * @idx: attribute index
4675 *
4676 * Return: Success(0) or reason code for failure
4677 */
4678static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
Jeff Johnson40dae4e2017-08-29 14:00:25 -07004679 struct hdd_station_ctx *hdd_sta_ctx,
Anurag Chouhan96919482016-07-13 16:36:57 +05304680 int idx)
4681{
4682 struct nlattr *nla_attr;
4683 uint32_t bitrate, bitrate_compat;
4684
4685 nla_attr = nla_nest_start(skb, idx);
4686 if (!nla_attr)
4687 goto fail;
4688 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304689 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->
4690 cache_conn_info.txrate);
Anurag Chouhan96919482016-07-13 16:36:57 +05304691
4692 /* report 16-bit bitrate only if we can */
4693 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
4694 if (bitrate > 0 &&
4695 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
4696 hdd_err("put fail");
4697 goto fail;
4698 }
4699 if (bitrate_compat > 0 &&
4700 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
4701 hdd_err("put fail");
4702 goto fail;
4703 }
4704 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304705 hdd_sta_ctx->cache_conn_info.txrate.nss)) {
Anurag Chouhan96919482016-07-13 16:36:57 +05304706 hdd_err("put fail");
4707 goto fail;
4708 }
4709 nla_nest_end(skb, nla_attr);
4710 return 0;
4711fail:
4712 return -EINVAL;
4713}
4714
4715/**
4716 * hdd_add_sta_info() - add station info attribute
4717 * @skb: pointer to sk buff
4718 * @hdd_sta_ctx: pointer to hdd station context
4719 * @idx: attribute index
4720 *
4721 * Return: Success(0) or reason code for failure
4722 */
4723static int32_t hdd_add_sta_info(struct sk_buff *skb,
Jeff Johnson40dae4e2017-08-29 14:00:25 -07004724 struct hdd_station_ctx *hdd_sta_ctx, int idx)
Anurag Chouhan96919482016-07-13 16:36:57 +05304725{
4726 struct nlattr *nla_attr;
4727
4728 nla_attr = nla_nest_start(skb, idx);
4729 if (!nla_attr)
4730 goto fail;
4731 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304732 (hdd_sta_ctx->cache_conn_info.signal + 100))) {
Anurag Chouhan96919482016-07-13 16:36:57 +05304733 hdd_err("put fail");
4734 goto fail;
4735 }
4736 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
4737 goto fail;
4738 nla_nest_end(skb, nla_attr);
4739 return 0;
4740fail:
4741 return -EINVAL;
4742}
4743
4744/**
4745 * hdd_add_survey_info() - add survey info attribute
4746 * @skb: pointer to sk buff
4747 * @hdd_sta_ctx: pointer to hdd station context
4748 * @idx: attribute index
4749 *
4750 * Return: Success(0) or reason code for failure
4751 */
4752static int32_t hdd_add_survey_info(struct sk_buff *skb,
Jeff Johnson40dae4e2017-08-29 14:00:25 -07004753 struct hdd_station_ctx *hdd_sta_ctx,
Anurag Chouhan96919482016-07-13 16:36:57 +05304754 int idx)
4755{
4756 struct nlattr *nla_attr;
4757
4758 nla_attr = nla_nest_start(skb, idx);
4759 if (!nla_attr)
4760 goto fail;
4761 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304762 hdd_sta_ctx->cache_conn_info.freq) ||
Anurag Chouhan96919482016-07-13 16:36:57 +05304763 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304764 (hdd_sta_ctx->cache_conn_info.noise + 100))) {
Anurag Chouhan96919482016-07-13 16:36:57 +05304765 hdd_err("put fail");
4766 goto fail;
4767 }
4768 nla_nest_end(skb, nla_attr);
4769 return 0;
4770fail:
4771 return -EINVAL;
4772}
4773
4774/**
4775 * hdd_add_link_standard_info() - add link info attribute
4776 * @skb: pointer to sk buff
4777 * @hdd_sta_ctx: pointer to hdd station context
4778 * @idx: attribute index
4779 *
4780 * Return: Success(0) or reason code for failure
4781 */
4782static int32_t
4783hdd_add_link_standard_info(struct sk_buff *skb,
Jeff Johnson40dae4e2017-08-29 14:00:25 -07004784 struct hdd_station_ctx *hdd_sta_ctx, int idx)
Anurag Chouhan96919482016-07-13 16:36:57 +05304785{
4786 struct nlattr *nla_attr;
4787
4788 nla_attr = nla_nest_start(skb, idx);
4789 if (!nla_attr)
4790 goto fail;
4791 if (nla_put(skb,
4792 NL80211_ATTR_SSID,
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304793 hdd_sta_ctx->cache_conn_info.last_ssid.SSID.length,
4794 hdd_sta_ctx->cache_conn_info.last_ssid.SSID.ssId)) {
Anurag Chouhan96919482016-07-13 16:36:57 +05304795 hdd_err("put fail");
4796 goto fail;
4797 }
Ashish Kumar Dhanotiya6e270602018-01-18 15:14:58 +05304798 if (nla_put(skb, NL80211_ATTR_MAC, QDF_MAC_ADDR_SIZE,
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304799 hdd_sta_ctx->cache_conn_info.bssId.bytes)) {
Ashish Kumar Dhanotiya6e270602018-01-18 15:14:58 +05304800 goto fail;
4801 }
Anurag Chouhan96919482016-07-13 16:36:57 +05304802 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
4803 goto fail;
4804 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
4805 goto fail;
4806 nla_nest_end(skb, nla_attr);
4807 return 0;
4808fail:
4809 return -EINVAL;
4810}
4811
4812/**
4813 * hdd_add_ap_standard_info() - add ap info attribute
4814 * @skb: pointer to sk buff
4815 * @hdd_sta_ctx: pointer to hdd station context
4816 * @idx: attribute index
4817 *
4818 * Return: Success(0) or reason code for failure
4819 */
4820static int32_t
4821hdd_add_ap_standard_info(struct sk_buff *skb,
Jeff Johnson40dae4e2017-08-29 14:00:25 -07004822 struct hdd_station_ctx *hdd_sta_ctx, int idx)
Anurag Chouhan96919482016-07-13 16:36:57 +05304823{
4824 struct nlattr *nla_attr;
4825
4826 nla_attr = nla_nest_start(skb, idx);
4827 if (!nla_attr)
4828 goto fail;
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304829 if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_present)
Anurag Chouhan96919482016-07-13 16:36:57 +05304830 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304831 sizeof(hdd_sta_ctx->cache_conn_info.vht_caps),
4832 &hdd_sta_ctx->cache_conn_info.vht_caps)) {
Anurag Chouhan96919482016-07-13 16:36:57 +05304833 hdd_err("put fail");
4834 goto fail;
4835 }
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304836 if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_present)
Anurag Chouhan96919482016-07-13 16:36:57 +05304837 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304838 sizeof(hdd_sta_ctx->cache_conn_info.ht_caps),
4839 &hdd_sta_ctx->cache_conn_info.ht_caps)) {
Anurag Chouhan96919482016-07-13 16:36:57 +05304840 hdd_err("put fail");
4841 goto fail;
4842 }
4843 nla_nest_end(skb, nla_attr);
4844 return 0;
4845fail:
4846 return -EINVAL;
4847}
4848
4849/**
4850 * hdd_get_station_info() - send BSS information to supplicant
4851 * @hdd_ctx: pointer to hdd context
4852 * @adapter: pointer to adapter
4853 *
4854 * Return: 0 if success else error status
4855 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07004856static int hdd_get_station_info(struct hdd_context *hdd_ctx,
Jeff Johnsone5006672017-08-29 14:39:02 -07004857 struct hdd_adapter *adapter)
Anurag Chouhan96919482016-07-13 16:36:57 +05304858{
4859 struct sk_buff *skb = NULL;
4860 uint8_t *tmp_hs20 = NULL;
4861 uint32_t nl_buf_len;
Jeff Johnson40dae4e2017-08-29 14:00:25 -07004862 struct hdd_station_ctx *hdd_sta_ctx;
Anurag Chouhan96919482016-07-13 16:36:57 +05304863
4864 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
4865
4866 nl_buf_len = NLMSG_HDRLEN;
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304867 nl_buf_len += sizeof(hdd_sta_ctx->
4868 cache_conn_info.last_ssid.SSID.length) +
Ashish Kumar Dhanotiya6e270602018-01-18 15:14:58 +05304869 QDF_MAC_ADDR_SIZE +
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304870 sizeof(hdd_sta_ctx->cache_conn_info.freq) +
4871 sizeof(hdd_sta_ctx->cache_conn_info.noise) +
4872 sizeof(hdd_sta_ctx->cache_conn_info.signal) +
Anurag Chouhan96919482016-07-13 16:36:57 +05304873 (sizeof(uint32_t) * 2) +
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304874 sizeof(hdd_sta_ctx->cache_conn_info.txrate.nss) +
4875 sizeof(hdd_sta_ctx->cache_conn_info.roam_count) +
4876 sizeof(hdd_sta_ctx->cache_conn_info.last_auth_type) +
4877 sizeof(hdd_sta_ctx->cache_conn_info.dot11Mode);
4878 if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_present)
4879 nl_buf_len += sizeof(hdd_sta_ctx->cache_conn_info.vht_caps);
4880 if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_present)
4881 nl_buf_len += sizeof(hdd_sta_ctx->cache_conn_info.ht_caps);
4882 if (hdd_sta_ctx->cache_conn_info.conn_flag.hs20_present) {
4883 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->
4884 cache_conn_info.hs20vendor_ie);
4885 nl_buf_len += (sizeof(hdd_sta_ctx->
4886 cache_conn_info.hs20vendor_ie) - 1);
Anurag Chouhan96919482016-07-13 16:36:57 +05304887 }
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304888 if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_op_present)
4889 nl_buf_len += sizeof(hdd_sta_ctx->
4890 cache_conn_info.ht_operation);
4891 if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_op_present)
4892 nl_buf_len += sizeof(hdd_sta_ctx->
4893 cache_conn_info.vht_operation);
Anurag Chouhan96919482016-07-13 16:36:57 +05304894
4895
4896 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
4897 if (!skb) {
Dustin Brownbacc48f2018-03-14 14:48:44 -07004898 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Anurag Chouhan96919482016-07-13 16:36:57 +05304899 return -ENOMEM;
4900 }
4901
4902 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
4903 LINK_INFO_STANDARD_NL80211_ATTR)) {
4904 hdd_err("put fail");
4905 goto fail;
4906 }
4907 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
4908 AP_INFO_STANDARD_NL80211_ATTR)) {
4909 hdd_err("put fail");
4910 goto fail;
4911 }
4912 if (nla_put_u32(skb, INFO_ROAM_COUNT,
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304913 hdd_sta_ctx->cache_conn_info.roam_count) ||
Anurag Chouhan96919482016-07-13 16:36:57 +05304914 nla_put_u32(skb, INFO_AKM,
4915 hdd_convert_auth_type(
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304916 hdd_sta_ctx->cache_conn_info.last_auth_type)) ||
Anurag Chouhan96919482016-07-13 16:36:57 +05304917 nla_put_u32(skb, WLAN802_11_MODE,
4918 hdd_convert_dot11mode(
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304919 hdd_sta_ctx->cache_conn_info.dot11Mode))) {
Anurag Chouhan96919482016-07-13 16:36:57 +05304920 hdd_err("put fail");
4921 goto fail;
4922 }
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304923 if (hdd_sta_ctx->cache_conn_info.conn_flag.ht_op_present)
Anurag Chouhan96919482016-07-13 16:36:57 +05304924 if (nla_put(skb, HT_OPERATION,
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304925 (sizeof(hdd_sta_ctx->cache_conn_info.ht_operation)),
4926 &hdd_sta_ctx->cache_conn_info.ht_operation)) {
Anurag Chouhan96919482016-07-13 16:36:57 +05304927 hdd_err("put fail");
4928 goto fail;
4929 }
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304930 if (hdd_sta_ctx->cache_conn_info.conn_flag.vht_op_present)
Anurag Chouhan96919482016-07-13 16:36:57 +05304931 if (nla_put(skb, VHT_OPERATION,
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304932 (sizeof(hdd_sta_ctx->
4933 cache_conn_info.vht_operation)),
4934 &hdd_sta_ctx->cache_conn_info.vht_operation)) {
Anurag Chouhan96919482016-07-13 16:36:57 +05304935 hdd_err("put fail");
4936 goto fail;
4937 }
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304938 if (hdd_sta_ctx->cache_conn_info.conn_flag.hs20_present)
Anurag Chouhan96919482016-07-13 16:36:57 +05304939 if (nla_put(skb, AP_INFO_HS20_INDICATION,
Ashish Kumar Dhanotiya36d19b02018-02-22 00:59:49 +05304940 (sizeof(hdd_sta_ctx->cache_conn_info.hs20vendor_ie)
4941 - 1),
Anurag Chouhan96919482016-07-13 16:36:57 +05304942 tmp_hs20 + 1)) {
4943 hdd_err("put fail");
4944 goto fail;
4945 }
4946
4947 return cfg80211_vendor_cmd_reply(skb);
4948fail:
4949 if (skb)
4950 kfree_skb(skb);
4951 return -EINVAL;
4952}
4953
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +05304954struct hdd_station_info *hdd_get_stainfo(struct hdd_station_info *astainfo,
4955 struct qdf_mac_addr mac_addr)
Will Huang496b36c2017-07-11 16:38:50 +08004956{
Jeff Johnson82155922017-09-30 16:54:14 -07004957 struct hdd_station_info *stainfo = NULL;
Will Huang496b36c2017-07-11 16:38:50 +08004958 int i;
4959
4960 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +05304961 if (!qdf_mem_cmp(&astainfo[i].sta_mac,
Will Huang496b36c2017-07-11 16:38:50 +08004962 &mac_addr,
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +05304963 QDF_MAC_ADDR_SIZE)) {
4964 stainfo = &astainfo[i];
4965 break;
4966 }
Will Huang496b36c2017-07-11 16:38:50 +08004967 }
4968
4969 return stainfo;
4970}
4971
4972#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
4973static inline int32_t remote_station_put_u64(struct sk_buff *skb,
4974 int32_t attrtype,
4975 uint64_t value)
4976{
4977 return nla_put_u64_64bit(skb, attrtype, value, REMOTE_PAD);
4978}
4979#else
4980static inline int32_t remote_station_put_u64(struct sk_buff *skb,
4981 int32_t attrtype,
4982 uint64_t value)
4983{
4984 return nla_put_u64(skb, attrtype, value);
4985}
4986#endif
4987
4988/**
Hanumanth Reddy Pothulaf79fbdf2017-10-23 20:10:46 +05304989 * hdd_add_survey_info_sap_get_len - get data length used in
4990 * hdd_add_survey_info_sap()
4991 *
4992 * This function calculates the data length used in hdd_add_survey_info_sap()
4993 *
4994 * Return: total data length used in hdd_add_survey_info_sap()
4995 */
4996static uint32_t hdd_add_survey_info_sap_get_len(void)
4997{
4998 return ((NLA_HDRLEN) + (sizeof(uint32_t) + NLA_HDRLEN));
4999}
5000
5001/**
5002 * hdd_add_survey_info - add survey info attribute
5003 * @skb: pointer to response skb buffer
5004 * @stainfo: station information
5005 * @idx: attribute type index for nla_next_start()
5006 *
5007 * This function adds survey info attribute to response skb buffer
5008 *
5009 * Return : 0 on success and errno on failure
5010 */
5011static int32_t hdd_add_survey_info_sap(struct sk_buff *skb,
5012 struct hdd_station_info *stainfo,
5013 int idx)
5014{
5015 struct nlattr *nla_attr;
5016
5017 nla_attr = nla_nest_start(skb, idx);
5018 if (!nla_attr)
5019 goto fail;
5020 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
5021 stainfo->freq)) {
5022 hdd_err("put fail");
5023 goto fail;
5024 }
5025 nla_nest_end(skb, nla_attr);
5026 return 0;
5027fail:
5028 return -EINVAL;
5029}
5030
5031/**
5032 * hdd_add_tx_bitrate_sap_get_len - get data length used in
5033 * hdd_add_tx_bitrate_sap()
5034 *
5035 * This function calculates the data length used in hdd_add_tx_bitrate_sap()
5036 *
5037 * Return: total data length used in hdd_add_tx_bitrate_sap()
5038 */
5039static uint32_t hdd_add_tx_bitrate_sap_get_len(void)
5040{
5041 return ((NLA_HDRLEN) + (sizeof(uint8_t) + NLA_HDRLEN));
5042}
5043
5044/**
5045 * hdd_add_tx_bitrate_sap - add vhs nss info attribute
5046 * @skb: pointer to response skb buffer
5047 * @stainfo: station information
5048 * @idx: attribute type index for nla_next_start()
5049 *
5050 * This function adds vht nss attribute to response skb buffer
5051 *
5052 * Return : 0 on success and errno on failure
5053 */
5054static int hdd_add_tx_bitrate_sap(struct sk_buff *skb,
5055 struct hdd_station_info *stainfo,
5056 int idx)
5057{
5058 struct nlattr *nla_attr;
5059
5060 nla_attr = nla_nest_start(skb, idx);
5061 if (!nla_attr)
5062 goto fail;
5063
5064 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
5065 stainfo->nss)) {
5066 hdd_err("put fail");
5067 goto fail;
5068 }
5069 nla_nest_end(skb, nla_attr);
5070 return 0;
5071fail:
5072 return -EINVAL;
5073}
5074
5075/**
5076 * hdd_add_sta_info_sap_get_len - get data length used in
5077 * hdd_add_sta_info_sap()
5078 *
5079 * This function calculates the data length used in hdd_add_sta_info_sap()
5080 *
5081 * Return: total data length used in hdd_add_sta_info_sap()
5082 */
5083static uint32_t hdd_add_sta_info_sap_get_len(void)
5084{
5085 return ((NLA_HDRLEN) + (sizeof(uint8_t) + NLA_HDRLEN) +
5086 hdd_add_tx_bitrate_sap_get_len());
5087}
5088
5089/**
5090 * hdd_add_sta_info_sap - add sta signal info attribute
5091 * @skb: pointer to response skb buffer
5092 * @stainfo: station information
5093 * @idx: attribute type index for nla_next_start()
5094 *
5095 * This function adds sta signal attribute to response skb buffer
5096 *
5097 * Return : 0 on success and errno on failure
5098 */
5099static int32_t hdd_add_sta_info_sap(struct sk_buff *skb, int8_t rssi,
5100 struct hdd_station_info *stainfo, int idx)
5101{
5102 struct nlattr *nla_attr;
5103
5104 nla_attr = nla_nest_start(skb, idx);
5105 if (!nla_attr)
5106 goto fail;
5107
5108 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL, rssi)) {
5109 hdd_err("put fail");
5110 goto fail;
5111 }
5112 if (hdd_add_tx_bitrate_sap(skb, stainfo, NL80211_STA_INFO_TX_BITRATE))
5113 goto fail;
5114
5115 nla_nest_end(skb, nla_attr);
5116 return 0;
5117fail:
5118 return -EINVAL;
5119}
5120
5121/**
5122 * hdd_add_link_standard_info_sap_get_len - get data length used in
5123 * hdd_add_link_standard_info_sap()
5124 *
5125 * This function calculates the data length used in
5126 * hdd_add_link_standard_info_sap()
5127 *
5128 * Return: total data length used in hdd_add_link_standard_info_sap()
5129 */
5130static uint32_t hdd_add_link_standard_info_sap_get_len(void)
5131{
5132 return ((NLA_HDRLEN) +
5133 hdd_add_survey_info_sap_get_len() +
5134 hdd_add_sta_info_sap_get_len() +
5135 (sizeof(uint32_t) + NLA_HDRLEN));
5136}
5137
5138/**
5139 * hdd_add_link_standard_info_sap - add add link info attribut
5140 * @skb: pointer to response skb buffer
5141 * @stainfo: station information
5142 * @idx: attribute type index for nla_next_start()
5143 *
5144 * This function adds link info attribut to response skb buffer
5145 *
5146 * Return : 0 on success and errno on failure
5147 */
5148static int hdd_add_link_standard_info_sap(struct sk_buff *skb, int8_t rssi,
5149 struct hdd_station_info *stainfo,
5150 int idx)
5151{
5152 struct nlattr *nla_attr;
5153
5154 nla_attr = nla_nest_start(skb, idx);
5155 if (!nla_attr)
5156 goto fail;
5157 if (hdd_add_survey_info_sap(skb, stainfo, NL80211_ATTR_SURVEY_INFO))
5158 goto fail;
5159 if (hdd_add_sta_info_sap(skb, rssi, stainfo, NL80211_ATTR_STA_INFO))
5160 goto fail;
5161
5162 if (nla_put_u32(skb, NL80211_ATTR_REASON_CODE, stainfo->reason_code)) {
5163 hdd_err("Reason code put fail");
5164 goto fail;
5165 }
5166
5167 nla_nest_end(skb, nla_attr);
5168 return 0;
5169fail:
5170 return -EINVAL;
5171}
5172
5173/**
5174 * hdd_add_ap_standard_info_sap_get_len - get data length used in
5175 * hdd_add_ap_standard_info_sap()
5176 * @stainfo: station information
5177 *
5178 * This function calculates the data length used in
5179 * hdd_add_ap_standard_info_sap()
5180 *
5181 * Return: total data length used in hdd_add_ap_standard_info_sap()
5182 */
5183static uint32_t hdd_add_ap_standard_info_sap_get_len(
5184 struct hdd_station_info *stainfo)
5185{
5186 uint32_t len;
5187
5188 len = NLA_HDRLEN;
5189 if (stainfo->vht_present)
5190 len += (sizeof(stainfo->vht_caps) + NLA_HDRLEN);
5191 if (stainfo->ht_present)
5192 len += (sizeof(stainfo->ht_caps) + NLA_HDRLEN);
5193
5194 return len;
5195}
5196
5197/**
5198 * hdd_add_ap_standard_info_sap - add HT and VHT info attributes
5199 * @skb: pointer to response skb buffer
5200 * @stainfo: station information
5201 * @idx: attribute type index for nla_next_start()
5202 *
5203 * This function adds HT and VHT info attributes to response skb buffer
5204 *
5205 * Return : 0 on success and errno on failure
5206 */
5207static int hdd_add_ap_standard_info_sap(struct sk_buff *skb,
5208 struct hdd_station_info *stainfo,
5209 int idx)
5210{
5211 struct nlattr *nla_attr;
5212
5213 nla_attr = nla_nest_start(skb, idx);
5214 if (!nla_attr)
5215 goto fail;
5216
5217 if (stainfo->vht_present) {
5218 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
5219 sizeof(stainfo->vht_caps),
5220 &stainfo->vht_caps)) {
5221 hdd_err("put fail");
5222 goto fail;
5223 }
5224 }
5225 if (stainfo->ht_present) {
5226 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
5227 sizeof(stainfo->ht_caps),
5228 &stainfo->ht_caps)) {
5229 hdd_err("put fail");
5230 goto fail;
5231 }
5232 }
5233 nla_nest_end(skb, nla_attr);
5234 return 0;
5235fail:
5236 return -EINVAL;
5237}
5238
5239/**
5240 * hdd_decode_ch_width - decode channel band width based
5241 * @ch_width: encoded enum value holding channel band width
5242 *
5243 * This function decodes channel band width from the given encoded enum value.
5244 *
5245 * Returns: decoded channel band width.
5246 */
5247static uint8_t hdd_decode_ch_width(tSirMacHTChannelWidth ch_width)
5248{
5249 switch (ch_width) {
5250 case 0:
5251 return 20;
5252 case 1:
5253 return 40;
5254 case 2:
5255 return 80;
5256 case 3:
5257 case 4:
5258 return 160;
5259 default:
5260 hdd_debug("invalid enum: %d", ch_width);
5261 return 20;
5262 }
5263}
5264
5265/**
5266 * hdd_get_cached_station_remote() - get cached(deleted) peer's info
Will Huang496b36c2017-07-11 16:38:50 +08005267 * @hdd_ctx: hdd context
5268 * @adapter: hostapd interface
5269 * @mac_addr: mac address of requested peer
5270 *
Hanumanth Reddy Pothulaf79fbdf2017-10-23 20:10:46 +05305271 * This function collect and indicate the cached(deleted) peer's info
Will Huang496b36c2017-07-11 16:38:50 +08005272 *
5273 * Return: 0 on success, otherwise error value
5274 */
Hanumanth Reddy Pothulaf79fbdf2017-10-23 20:10:46 +05305275
5276static int hdd_get_cached_station_remote(struct hdd_context *hdd_ctx,
5277 struct hdd_adapter *adapter,
5278 struct qdf_mac_addr mac_addr)
Will Huang496b36c2017-07-11 16:38:50 +08005279{
Hanumanth Reddy Pothulaf79fbdf2017-10-23 20:10:46 +05305280 struct hdd_station_info *stainfo = hdd_get_stainfo(
5281 adapter->cache_sta_info,
5282 mac_addr);
Will Huang496b36c2017-07-11 16:38:50 +08005283 struct sk_buff *skb = NULL;
Hanumanth Reddy Pothulaf79fbdf2017-10-23 20:10:46 +05305284 uint32_t nl_buf_len = NLMSG_HDRLEN;
5285 uint8_t channel_width;
Will Huang496b36c2017-07-11 16:38:50 +08005286
5287 if (!stainfo) {
5288 hdd_err("peer " MAC_ADDRESS_STR " not found",
5289 MAC_ADDR_ARRAY(mac_addr.bytes));
Hanumanth Reddy Pothulaf79fbdf2017-10-23 20:10:46 +05305290 return -EINVAL;
5291 }
5292
5293 nl_buf_len += hdd_add_link_standard_info_sap_get_len() +
5294 hdd_add_ap_standard_info_sap_get_len(stainfo) +
Ashish Kumar Dhanotiyad523f0d2017-10-26 14:15:48 +05305295 (sizeof(stainfo->dot11_mode) + NLA_HDRLEN) +
Hanumanth Reddy Pothulaf79fbdf2017-10-23 20:10:46 +05305296 (sizeof(stainfo->ch_width) + NLA_HDRLEN) +
5297 (sizeof(stainfo->tx_rate) + NLA_HDRLEN) +
5298 (sizeof(stainfo->rx_rate) + NLA_HDRLEN);
5299
5300 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
5301 if (!skb) {
Dustin Brownbacc48f2018-03-14 14:48:44 -07005302 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Hanumanth Reddy Pothulaf79fbdf2017-10-23 20:10:46 +05305303 return -ENOMEM;
5304 }
5305
5306 if (hdd_add_link_standard_info_sap(skb, stainfo->rssi, stainfo,
5307 LINK_INFO_STANDARD_NL80211_ATTR)) {
5308 hdd_err("link standard put fail");
Will Huang496b36c2017-07-11 16:38:50 +08005309 goto fail;
5310 }
5311
Hanumanth Reddy Pothulaf79fbdf2017-10-23 20:10:46 +05305312 if (hdd_add_ap_standard_info_sap(skb, stainfo,
5313 AP_INFO_STANDARD_NL80211_ATTR)) {
5314 hdd_err("ap standard put fail");
5315 goto fail;
5316 }
5317
5318 /* upper layer expects decoded channel BW */
5319 channel_width = hdd_decode_ch_width(stainfo->ch_width);
5320
5321 if (nla_put_u32(skb, REMOTE_SUPPORTED_MODE,
5322 hdd_convert_dot11mode(
5323 stainfo->mode)) ||
5324 nla_put_u8(skb, REMOTE_CH_WIDTH, channel_width)) {
5325 hdd_err("remote ch put fail");
5326 goto fail;
5327 }
5328 if (nla_put_u32(skb, REMOTE_LAST_TX_RATE, stainfo->tx_rate)) {
5329 hdd_err("tx rate put fail");
5330 goto fail;
5331 }
5332 if (nla_put_u32(skb, REMOTE_LAST_RX_RATE, stainfo->rx_rate)) {
5333 hdd_err("rx rate put fail");
5334 goto fail;
5335 }
5336
5337 qdf_mem_zero(stainfo, sizeof(*stainfo));
5338
5339 return cfg80211_vendor_cmd_reply(skb);
5340fail:
5341 if (skb)
5342 kfree_skb(skb);
5343
5344 return -EINVAL;
5345}
5346
5347/**
5348 * hdd_get_cached_station_remote() - get connected peer's info
5349 * @hdd_ctx: hdd context
5350 * @adapter: hostapd interface
5351 * @mac_addr: mac address of requested peer
5352 *
5353 * This function collect and indicate the connected peer's info
5354 *
5355 * Return: 0 on success, otherwise error value
5356 */
5357static int hdd_get_connected_station_info(struct hdd_context *hdd_ctx,
5358 struct hdd_adapter *adapter,
5359 struct qdf_mac_addr mac_addr,
5360 struct hdd_station_info *stainfo)
5361{
5362 struct sk_buff *skb = NULL;
5363 uint32_t nl_buf_len;
5364 struct sir_peer_info_ext peer_info;
5365 bool txrx_rate = true;
5366
Will Huang496b36c2017-07-11 16:38:50 +08005367 nl_buf_len = NLMSG_HDRLEN;
5368 nl_buf_len += (sizeof(stainfo->max_phy_rate) + NLA_HDRLEN) +
5369 (sizeof(stainfo->tx_packets) + NLA_HDRLEN) +
5370 (sizeof(stainfo->tx_bytes) + NLA_HDRLEN) +
5371 (sizeof(stainfo->rx_packets) + NLA_HDRLEN) +
5372 (sizeof(stainfo->rx_bytes) + NLA_HDRLEN) +
Jeff Johnson65fda112017-10-21 13:46:10 -07005373 (sizeof(stainfo->is_qos_enabled) + NLA_HDRLEN) +
Will Huang496b36c2017-07-11 16:38:50 +08005374 (sizeof(stainfo->mode) + NLA_HDRLEN);
5375
5376 if (!hdd_ctx->config->sap_get_peer_info ||
5377 wlan_hdd_get_peer_info(adapter, mac_addr, &peer_info)) {
5378 hdd_err("fail to get tx/rx rate");
5379 txrx_rate = false;
5380 } else {
5381 stainfo->tx_rate = peer_info.tx_rate;
5382 stainfo->rx_rate = peer_info.rx_rate;
5383 nl_buf_len += (sizeof(stainfo->tx_rate) + NLA_HDRLEN) +
5384 (sizeof(stainfo->rx_rate) + NLA_HDRLEN);
5385 }
5386
5387 /* below info is only valid for HT/VHT mode */
5388 if (stainfo->mode > SIR_SME_PHY_MODE_LEGACY)
5389 nl_buf_len += (sizeof(stainfo->ampdu) + NLA_HDRLEN) +
5390 (sizeof(stainfo->tx_stbc) + NLA_HDRLEN) +
5391 (sizeof(stainfo->rx_stbc) + NLA_HDRLEN) +
5392 (sizeof(stainfo->ch_width) + NLA_HDRLEN) +
5393 (sizeof(stainfo->sgi_enable) + NLA_HDRLEN);
5394
5395 hdd_info("buflen %d hdrlen %d", nl_buf_len, NLMSG_HDRLEN);
5396
5397 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
5398 nl_buf_len);
5399 if (!skb) {
5400 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
5401 goto fail;
5402 }
5403
5404 hdd_info("stainfo");
5405 hdd_info("maxrate %x tx_pkts %x tx_bytes %llx",
5406 stainfo->max_phy_rate, stainfo->tx_packets,
5407 stainfo->tx_bytes);
5408 hdd_info("rx_pkts %x rx_bytes %llx mode %x",
5409 stainfo->rx_packets, stainfo->rx_bytes,
5410 stainfo->mode);
5411 if (stainfo->mode > SIR_SME_PHY_MODE_LEGACY) {
5412 hdd_info("ampdu %d tx_stbc %d rx_stbc %d",
5413 stainfo->ampdu, stainfo->tx_stbc,
5414 stainfo->rx_stbc);
5415 hdd_info("wmm %d chwidth %d sgi %d",
Jeff Johnson65fda112017-10-21 13:46:10 -07005416 stainfo->is_qos_enabled,
Will Huang496b36c2017-07-11 16:38:50 +08005417 stainfo->ch_width,
5418 stainfo->sgi_enable);
5419 }
5420
5421 if (nla_put_u32(skb, REMOTE_MAX_PHY_RATE, stainfo->max_phy_rate) ||
5422 nla_put_u32(skb, REMOTE_TX_PACKETS, stainfo->tx_packets) ||
5423 remote_station_put_u64(skb, REMOTE_TX_BYTES, stainfo->tx_bytes) ||
5424 nla_put_u32(skb, REMOTE_RX_PACKETS, stainfo->rx_packets) ||
5425 remote_station_put_u64(skb, REMOTE_RX_BYTES, stainfo->rx_bytes) ||
Jeff Johnson65fda112017-10-21 13:46:10 -07005426 nla_put_u8(skb, REMOTE_WMM, stainfo->is_qos_enabled) ||
Will Huang496b36c2017-07-11 16:38:50 +08005427 nla_put_u8(skb, REMOTE_SUPPORTED_MODE, stainfo->mode)) {
5428 hdd_err("put fail");
5429 goto fail;
5430 }
5431
5432 if (txrx_rate) {
5433 if (nla_put_u32(skb, REMOTE_LAST_TX_RATE, stainfo->tx_rate) ||
5434 nla_put_u32(skb, REMOTE_LAST_RX_RATE, stainfo->rx_rate)) {
5435 hdd_err("put fail");
5436 goto fail;
5437 } else {
5438 hdd_info("tx_rate %x rx_rate %x",
5439 stainfo->tx_rate, stainfo->rx_rate);
5440 }
5441 }
5442
5443 if (stainfo->mode > SIR_SME_PHY_MODE_LEGACY) {
5444 if (nla_put_u8(skb, REMOTE_AMPDU, stainfo->ampdu) ||
5445 nla_put_u8(skb, REMOTE_TX_STBC, stainfo->tx_stbc) ||
5446 nla_put_u8(skb, REMOTE_RX_STBC, stainfo->rx_stbc) ||
5447 nla_put_u8(skb, REMOTE_CH_WIDTH, stainfo->ch_width) ||
5448 nla_put_u8(skb, REMOTE_SGI_ENABLE, stainfo->sgi_enable)) {
5449 hdd_err("put fail");
5450 goto fail;
5451 }
5452 }
5453
5454 return cfg80211_vendor_cmd_reply(skb);
5455
5456fail:
5457 if (skb)
5458 kfree_skb(skb);
5459
5460 return -EINVAL;
5461}
5462
5463/**
Hanumanth Reddy Pothulaf79fbdf2017-10-23 20:10:46 +05305464 * hdd_get_station_remote() - get remote peer's info
5465 * @hdd_ctx: hdd context
5466 * @adapter: hostapd interface
5467 * @mac_addr: mac address of requested peer
5468 *
5469 * This function collect and indicate the remote peer's info
5470 *
5471 * Return: 0 on success, otherwise error value
5472 */
5473static int hdd_get_station_remote(struct hdd_context *hdd_ctx,
5474 struct hdd_adapter *adapter,
5475 struct qdf_mac_addr mac_addr)
5476{
5477 struct hdd_station_info *stainfo = hdd_get_stainfo(adapter->sta_info,
5478 mac_addr);
5479 int status = 0;
5480 bool is_associated = false;
5481
5482 if (!stainfo) {
5483 status = hdd_get_cached_station_remote(hdd_ctx, adapter,
5484 mac_addr);
5485 return status;
5486 }
5487
5488 is_associated = hdd_is_peer_associated(adapter, &mac_addr);
5489 if (!is_associated) {
5490 status = hdd_get_cached_station_remote(hdd_ctx, adapter,
5491 mac_addr);
5492 return status;
5493 }
5494
5495 status = hdd_get_connected_station_info(hdd_ctx, adapter,
5496 mac_addr, stainfo);
5497 return status;
5498}
5499
5500/**
Anurag Chouhan96919482016-07-13 16:36:57 +05305501 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
5502 * @wiphy: corestack handler
5503 * @wdev: wireless device
5504 * @data: data
5505 * @data_len: data length
5506 *
5507 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
5508 * Validate cmd attributes and send the station info to upper layers.
5509 *
5510 * Return: Success(0) or reason code for failure
5511 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05305512static int
Anurag Chouhan96919482016-07-13 16:36:57 +05305513__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
5514 struct wireless_dev *wdev,
5515 const void *data,
5516 int data_len)
5517{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005518 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Anurag Chouhan96919482016-07-13 16:36:57 +05305519 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07005520 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Anurag Chouhan96919482016-07-13 16:36:57 +05305521 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
5522 int32_t status;
5523
Dustin Brownfdf17c12018-03-14 12:55:34 -07005524 hdd_enter_dev(dev);
Anurag Chouhan96919482016-07-13 16:36:57 +05305525 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5526 hdd_err("Command not allowed in FTM mode");
5527 status = -EPERM;
5528 goto out;
5529 }
5530
5531 status = wlan_hdd_validate_context(hdd_ctx);
5532 if (0 != status)
5533 goto out;
5534
5535
Dustin Brown4ea21db2018-01-05 14:13:17 -08005536 status = wlan_cfg80211_nla_parse(tb,
5537 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
5538 data, data_len,
5539 hdd_get_station_policy);
Anurag Chouhan96919482016-07-13 16:36:57 +05305540 if (status) {
5541 hdd_err("Invalid ATTR");
5542 goto out;
5543 }
5544
5545 /* Parse and fetch Command Type*/
5546 if (tb[STATION_INFO]) {
5547 status = hdd_get_station_info(hdd_ctx, adapter);
5548 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
5549 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
Will Huang496b36c2017-07-11 16:38:50 +08005550 } else if (tb[STATION_REMOTE]) {
5551 struct qdf_mac_addr mac_addr;
5552
5553 if (adapter->device_mode != QDF_SAP_MODE &&
5554 adapter->device_mode != QDF_P2P_GO_MODE) {
5555 hdd_err("invalid device_mode:%d", adapter->device_mode);
5556 status = -EINVAL;
5557 goto out;
5558 }
5559
5560 nla_memcpy(mac_addr.bytes, tb[STATION_REMOTE],
5561 QDF_MAC_ADDR_SIZE);
5562
5563 hdd_debug("STATION_REMOTE " MAC_ADDRESS_STR,
5564 MAC_ADDR_ARRAY(mac_addr.bytes));
5565
5566 status = hdd_get_station_remote(hdd_ctx, adapter, mac_addr);
Anurag Chouhan96919482016-07-13 16:36:57 +05305567 } else {
5568 hdd_err("get station info cmd type failed");
5569 status = -EINVAL;
5570 goto out;
5571 }
Dustin Browne74003f2018-03-14 12:51:58 -07005572 hdd_exit();
Anurag Chouhan96919482016-07-13 16:36:57 +05305573out:
5574 return status;
5575}
5576
5577/**
5578 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
5579 * @wiphy: corestack handler
5580 * @wdev: wireless device
5581 * @data: data
5582 * @data_len: data length
5583 *
5584 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
5585 * Validate cmd attributes and send the station info to upper layers.
5586 *
5587 * Return: Success(0) or reason code for failure
5588 */
5589static int32_t
5590hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
5591 struct wireless_dev *wdev,
5592 const void *data,
5593 int data_len)
5594{
5595 int ret;
5596
5597 cds_ssr_protect(__func__);
5598 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
5599 cds_ssr_unprotect(__func__);
5600
5601 return ret;
5602}
5603
5604/*
5605 * undef short names defined for get station command
5606 * used by __wlan_hdd_cfg80211_get_station_cmd()
5607 */
5608#undef STATION_INVALID
5609#undef STATION_INFO
5610#undef STATION_ASSOC_FAIL_REASON
Will Huang496b36c2017-07-11 16:38:50 +08005611#undef STATION_REMOTE
Anurag Chouhan96919482016-07-13 16:36:57 +05305612#undef STATION_MAX
Will Huang496b36c2017-07-11 16:38:50 +08005613#undef LINK_INFO_STANDARD_NL80211_ATTR
5614#undef AP_INFO_STANDARD_NL80211_ATTR
5615#undef INFO_ROAM_COUNT
5616#undef INFO_AKM
5617#undef WLAN802_11_MODE
5618#undef AP_INFO_HS20_INDICATION
5619#undef HT_OPERATION
5620#undef VHT_OPERATION
5621#undef INFO_ASSOC_FAIL_REASON
5622#undef REMOTE_MAX_PHY_RATE
5623#undef REMOTE_TX_PACKETS
5624#undef REMOTE_TX_BYTES
5625#undef REMOTE_RX_PACKETS
5626#undef REMOTE_RX_BYTES
5627#undef REMOTE_LAST_TX_RATE
5628#undef REMOTE_LAST_RX_RATE
5629#undef REMOTE_WMM
5630#undef REMOTE_SUPPORTED_MODE
5631#undef REMOTE_AMPDU
5632#undef REMOTE_TX_STBC
5633#undef REMOTE_RX_STBC
5634#undef REMOTE_CH_WIDTH
5635#undef REMOTE_SGI_ENABLE
5636#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
5637#undef REMOTE_PAD
5638#endif
Anurag Chouhan96919482016-07-13 16:36:57 +05305639
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005640#ifdef WLAN_FEATURE_ROAM_OFFLOAD
5641/**
5642 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
5643 * @wiphy: pointer to wireless wiphy structure.
5644 * @wdev: pointer to wireless_dev structure.
5645 * @data: Pointer to the Key data
5646 * @data_len:Length of the data passed
5647 *
5648 * This is called when wlan driver needs to save the keys received via
5649 * vendor specific command.
5650 *
5651 * Return: Return the Success or Failure code.
5652 */
5653static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
5654 struct wireless_dev *wdev,
5655 const void *data, int data_len)
5656{
5657 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
5658 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07005659 struct hdd_adapter *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005660 struct hdd_context *hdd_ctx_ptr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005661 int status;
Deepak Dhamdhere828f1892017-02-09 11:51:19 -08005662 struct pmkid_mode_bits pmkid_modes;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005663
Dustin Brownfdf17c12018-03-14 12:55:34 -07005664 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08005665
Anurag Chouhan6d760662016-02-20 16:05:43 +05305666 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005667 hdd_err("Command not allowed in FTM mode");
5668 return -EPERM;
5669 }
5670
Hanumanth Reddy Pothula53874852018-03-08 19:57:49 +05305671 if ((data == NULL) || (data_len <= 0) ||
5672 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07005673 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005674 return -EINVAL;
5675 }
5676
5677 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
5678 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07005679 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005680 return -EINVAL;
5681 }
5682
5683 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305684 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005685 return status;
Deepak Dhamdhere828f1892017-02-09 11:51:19 -08005686
5687 hdd_get_pmkid_modes(hdd_ctx_ptr, &pmkid_modes);
5688
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005689 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
Jeff Johnson1b780e42017-10-31 14:11:45 -07005690 hdd_adapter_ptr->session_id,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07005691 true,
Deepak Dhamdhere828f1892017-02-09 11:51:19 -08005692 &pmkid_modes);
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305693 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
5694 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005695 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
Jeff Johnson1b780e42017-10-31 14:11:45 -07005696 hdd_adapter_ptr->session_id, local_pmk, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005697 return 0;
5698}
5699
5700/**
5701 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
5702 * @wiphy: pointer to wireless wiphy structure.
5703 * @wdev: pointer to wireless_dev structure.
5704 * @data: Pointer to the Key data
5705 * @data_len:Length of the data passed
5706 *
5707 * This is called when wlan driver needs to save the keys received via
5708 * vendor specific command.
5709 *
5710 * Return: Return the Success or Failure code.
5711 */
5712static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
5713 struct wireless_dev *wdev,
5714 const void *data, int data_len)
5715{
5716 int ret;
5717
5718 cds_ssr_protect(__func__);
5719 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
5720 cds_ssr_unprotect(__func__);
5721
5722 return ret;
5723}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08005724#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005725
5726static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
5727 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
5728 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
5729 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07005730 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005731};
5732
5733/**
5734 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
5735 * @wiphy: pointer to wireless wiphy structure.
5736 * @wdev: pointer to wireless_dev structure.
5737 * @data: Pointer to the data to be passed via vendor interface
5738 * @data_len:Length of the data to be passed
5739 *
5740 * This is called when wlan driver needs to send wifi driver related info
5741 * (driver/fw version) to the user space application upon request.
5742 *
5743 * Return: Return the Success or Failure code.
5744 */
5745static int
5746__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
5747 struct wireless_dev *wdev,
5748 const void *data, int data_len)
5749{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005750 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005751 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07005752 tSirVersionString driver_version;
5753 tSirVersionString firmware_version;
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07005754 const char *hw_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005755 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07005756 uint32_t sub_id = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005757 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07005758 struct sk_buff *reply_skb;
5759 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005760
Dustin Brownfdf17c12018-03-14 12:55:34 -07005761 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08005762
Anurag Chouhan6d760662016-02-20 16:05:43 +05305763 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005764 hdd_err("Command not allowed in FTM mode");
5765 return -EPERM;
5766 }
5767
5768 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305769 if (status)
5770 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005771
Dustin Brown4ea21db2018-01-05 14:13:17 -08005772 if (wlan_cfg80211_nla_parse(tb_vendor,
5773 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX,
5774 data, data_len,
5775 qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07005776 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005777 return -EINVAL;
5778 }
5779
5780 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08005781 hdd_debug("Rcvd req for Driver version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07005782 strlcpy(driver_version, QWLAN_VERSIONSTR,
5783 sizeof(driver_version));
5784 skb_len += strlen(driver_version) + 1;
5785 count++;
5786 }
5787
5788 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005789 hdd_debug("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005790 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
5791 &crmid);
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07005792 sub_id = (hdd_ctx->target_fw_vers_ext & 0xf0000000) >> 28;
5793 hw_version = hdd_ctx->target_hw_name;
Ryan Hsu7ac88852016-04-28 10:20:34 -07005794 snprintf(firmware_version, sizeof(firmware_version),
Varun Reddy Yeturueb293322017-04-16 21:53:13 -07005795 "FW:%d.%d.%d.%d.%d HW:%s", major_spid, minor_spid,
5796 siid, crmid, sub_id, hw_version);
Ryan Hsu7ac88852016-04-28 10:20:34 -07005797 skb_len += strlen(firmware_version) + 1;
5798 count++;
5799 }
5800
5801 if (count == 0) {
5802 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005803 return -EINVAL;
5804 }
5805
Ryan Hsu7ac88852016-04-28 10:20:34 -07005806 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
5807 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
5808
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005809 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07005810 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005811 return -ENOMEM;
5812 }
5813
Ryan Hsu7ac88852016-04-28 10:20:34 -07005814 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
5815 if (nla_put_string(reply_skb,
5816 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
5817 driver_version))
5818 goto error_nla_fail;
5819 }
5820
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05305821 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07005822 if (nla_put_string(reply_skb,
5823 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
5824 firmware_version))
5825 goto error_nla_fail;
5826 }
5827
5828 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
5829 if (nla_put_u32(reply_skb,
5830 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
5831 hdd_ctx->radio_index))
5832 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005833 }
5834
5835 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07005836
5837error_nla_fail:
5838 hdd_err("nla put fail");
5839 kfree_skb(reply_skb);
5840 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005841}
5842
5843/**
5844 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
5845 * @wiphy: pointer to wireless wiphy structure.
5846 * @wdev: pointer to wireless_dev structure.
5847 * @data: Pointer to the data to be passed via vendor interface
5848 * @data_len:Length of the data to be passed
5849 *
5850 * This is called when wlan driver needs to send wifi driver related info
5851 * (driver/fw version) to the user space application upon request.
5852 *
5853 * Return: Return the Success or Failure code.
5854 */
5855static int
5856wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
5857 struct wireless_dev *wdev,
5858 const void *data, int data_len)
5859{
5860 int ret;
5861
5862 cds_ssr_protect(__func__);
5863 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
5864 cds_ssr_unprotect(__func__);
5865
5866 return ret;
5867}
5868
5869/**
5870 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
5871 * @wiphy: pointer to wireless wiphy structure.
5872 * @wdev: pointer to wireless_dev structure.
5873 * @data: Pointer to the data to be passed via vendor interface
5874 * @data_len:Length of the data to be passed
5875 *
5876 * This is called by userspace to know the supported logger features
5877 *
5878 * Return: Return the Success or Failure code.
5879 */
5880static int
5881__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
5882 struct wireless_dev *wdev,
5883 const void *data, int data_len)
5884{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07005885 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005886 int status;
5887 uint32_t features;
5888 struct sk_buff *reply_skb = NULL;
5889
Dustin Brownfdf17c12018-03-14 12:55:34 -07005890 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08005891
Anurag Chouhan6d760662016-02-20 16:05:43 +05305892 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005893 hdd_err("Command not allowed in FTM mode");
5894 return -EPERM;
5895 }
5896
5897 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305898 if (status)
5899 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005900
5901 features = 0;
5902
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005903 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
5904 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
5905 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
Srinivas Girigowdaa26eac02018-01-23 12:49:20 -08005906 features |= WIFI_LOGGER_DRIVER_DUMP_SUPPORTED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005907
5908 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5909 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
5910 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07005911 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005912 return -ENOMEM;
5913 }
5914
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005915 hdd_debug("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005916 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
5917 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07005918 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005919 kfree_skb(reply_skb);
5920 return -EINVAL;
5921 }
5922
5923 return cfg80211_vendor_cmd_reply(reply_skb);
5924}
5925
5926/**
5927 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
5928 * @wiphy: pointer to wireless wiphy structure.
5929 * @wdev: pointer to wireless_dev structure.
5930 * @data: Pointer to the data to be passed via vendor interface
5931 * @data_len:Length of the data to be passed
5932 *
5933 * This is called by userspace to know the supported logger features
5934 *
5935 * Return: Return the Success or Failure code.
5936 */
5937static int
5938wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
5939 struct wireless_dev *wdev,
5940 const void *data, int data_len)
5941{
5942 int ret;
5943
5944 cds_ssr_protect(__func__);
5945 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
5946 data, data_len);
5947 cds_ssr_unprotect(__func__);
5948
5949 return ret;
5950}
5951
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305952#ifdef WLAN_FEATURE_GTK_OFFLOAD
5953void wlan_hdd_save_gtk_offload_params(struct hdd_adapter *adapter,
5954 uint8_t *kck_ptr, uint8_t *kek_ptr,
5955 uint32_t kek_len, uint8_t *replay_ctr,
5956 bool big_endian)
5957{
5958 struct hdd_station_ctx *hdd_sta_ctx;
5959 uint8_t *buf;
5960 int i;
5961 struct pmo_gtk_req *gtk_req = NULL;
5962 QDF_STATUS status = QDF_STATUS_E_FAILURE;
5963
5964 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
5965 if (!gtk_req) {
5966 hdd_err("cannot allocate gtk_req");
5967 return;
5968 }
5969
5970 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
5971 if (kck_ptr)
5972 qdf_mem_copy(gtk_req->kck, kck_ptr, NL80211_KCK_LEN);
5973
Jeff Johnsone1f2b0e2017-11-14 14:42:55 -08005974 if (kek_ptr) {
5975 /* paranoia */
5976 if (kek_len > sizeof(gtk_req->kek)) {
5977 kek_len = sizeof(gtk_req->kek);
5978 QDF_ASSERT(0);
5979 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305980 qdf_mem_copy(gtk_req->kek, kek_ptr, kek_len);
Jeff Johnsone1f2b0e2017-11-14 14:42:55 -08005981 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05305982
5983 qdf_copy_macaddr(&gtk_req->bssid, &hdd_sta_ctx->conn_info.bssId);
5984
5985 gtk_req->kek_len = kek_len;
5986
5987 /* convert big to little endian since driver work on little endian */
5988 buf = (uint8_t *)&gtk_req->replay_counter;
5989 for (i = 0; i < 8; i++)
5990 buf[7 - i] = replay_ctr[i];
5991
5992 status = pmo_ucfg_cache_gtk_offload_req(adapter->hdd_vdev, gtk_req);
5993 if (status != QDF_STATUS_SUCCESS)
5994 hdd_err("Failed to cache GTK Offload");
5995
5996 qdf_mem_free(gtk_req);
5997}
5998#else
5999void wlan_hdd_save_gtk_offload_params(struct hdd_adapter *adapter,
6000 uint8_t *kck_ptr,
6001 uint8_t *kek_ptr,
6002 uint32_t kek_len,
6003 uint8_t *replay_ctr,
6004 bool big_endian)
6005{
6006}
6007#endif
6008
Sridhar Selvaraje5260442017-08-19 10:12:03 +05306009#if defined(WLAN_FEATURE_FILS_SK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306010/**
6011 * wlan_hdd_add_fils_params_roam_auth_event() - Adds FILS params in roam auth
6012 * @skb: SK buffer
6013 * @roam_info: Roam info
6014 *
6015 * API adds fils params[pmk, pmkid, next sequence number] to roam auth event
6016 *
6017 * Return: zero on success, error code on failure
6018 */
Jeff Johnson172237b2017-11-07 15:32:59 -08006019static int
6020wlan_hdd_add_fils_params_roam_auth_event(struct sk_buff *skb,
6021 struct csr_roam_info *roam_info)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306022{
6023 if (roam_info->pmk_len &&
6024 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMK,
6025 roam_info->pmk_len, roam_info->pmk)) {
6026 hdd_err("pmk send fail");
6027 return -EINVAL;
6028 }
6029
6030 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMKID,
6031 SIR_PMKID_LEN, roam_info->pmkid)) {
6032 hdd_err("pmkid send fail");
6033 return -EINVAL;
6034 }
6035
Vignesh Viswanathan8da68cf2017-09-07 14:00:04 +05306036 hdd_debug("Update ERP Seq Num %d, Next ERP Seq Num %d",
6037 roam_info->update_erp_next_seq_num,
6038 roam_info->next_erp_seq_num);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306039 if (roam_info->update_erp_next_seq_num &&
6040 nla_put_u16(skb,
6041 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_FILS_ERP_NEXT_SEQ_NUM,
6042 roam_info->next_erp_seq_num)) {
6043 hdd_err("ERP seq num send fail");
6044 return -EINVAL;
6045 }
6046
6047 return 0;
6048}
6049#else
Jeff Johnson172237b2017-11-07 15:32:59 -08006050static inline int
6051wlan_hdd_add_fils_params_roam_auth_event(struct sk_buff *skb,
6052 struct csr_roam_info *roam_info)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306053{
6054 return 0;
6055}
6056#endif
6057
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08006058#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006059/**
6060 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05306061 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006062 * @bssid: pointer to bssid of roamed AP.
6063 * @req_rsn_ie: Pointer to request RSN IE
6064 * @req_rsn_len: Length of the request RSN IE
6065 * @rsp_rsn_ie: Pointer to response RSN IE
6066 * @rsp_rsn_len: Length of the response RSN IE
6067 * @roam_info_ptr: Pointer to the roaming related information
6068 *
6069 * This is called when wlan driver needs to send the roaming and
6070 * authorization information after roaming.
6071 *
6072 * The information that would be sent is the request RSN IE, response
6073 * RSN IE and BSSID of the newly roamed AP.
6074 *
6075 * If the Authorized status is authenticated, then additional parameters
6076 * like PTK's KCK and KEK and Replay Counter would also be passed to the
6077 * supplicant.
6078 *
6079 * The supplicant upon receiving this event would ignore the legacy
6080 * cfg80211_roamed call and use the entire information from this event.
6081 * The cfg80211_roamed should still co-exist since the kernel will
6082 * make use of the parameters even if the supplicant ignores it.
6083 *
6084 * Return: Return the Success or Failure code.
6085 */
Jeff Johnsone5006672017-08-29 14:39:02 -07006086int wlan_hdd_send_roam_auth_event(struct hdd_adapter *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006087 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
Jeff Johnson172237b2017-11-07 15:32:59 -08006088 uint32_t rsp_rsn_len, struct csr_roam_info *roam_info_ptr)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006089{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006090 struct hdd_context *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006091 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08006092 eCsrAuthType auth_type;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306093 uint32_t fils_params_len;
6094 int status;
Jeff Johnson4f7f7c62017-10-05 08:53:41 -07006095
Dustin Brown491d54b2018-03-14 12:39:11 -07006096 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006097
Abhishek Singh23edd1c2016-05-05 11:56:06 +05306098 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006099 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006100
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07006101 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08006102 !roam_info_ptr->roamSynchInProgress)
6103 return 0;
6104
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306105 /*
6106 * PMK is sent from FW in Roam Synch Event for FILS Roaming.
6107 * In that case, add three more NL attributes.ie. PMK, PMKID
6108 * and ERP next sequence number. Add corresponding lengths
6109 * with 3 extra NL message headers for each of the
6110 * aforementioned params.
6111 */
6112 fils_params_len = roam_info_ptr->pmk_len + SIR_PMKID_LEN +
6113 sizeof(uint16_t) + (3 * NLMSG_HDRLEN);
6114
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006115 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05306116 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006117 ETH_ALEN + req_rsn_len + rsp_rsn_len +
6118 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306119 SIR_KCK_KEY_LEN + roam_info_ptr->kek_len +
6120 sizeof(uint8_t) + (8 * NLMSG_HDRLEN) +
6121 fils_params_len,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006122 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
6123 GFP_KERNEL);
6124
6125 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07006126 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006127 return -EINVAL;
6128 }
6129
6130 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
6131 ETH_ALEN, bssid) ||
6132 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
6133 req_rsn_len, req_rsn_ie) ||
6134 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
6135 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07006136 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006137 goto nla_put_failure;
6138 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006139 if (roam_info_ptr->synchAuthStatus ==
6140 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07006141 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08006142 if (nla_put_u8(skb,
6143 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
6144 hdd_err("nla put fail");
6145 goto nla_put_failure;
6146 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08006147 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
6148 /* if FT or CCKM connection: dont send replay counter */
6149 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
6150 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
6151 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
6152 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
6153 nla_put(skb,
6154 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
6155 SIR_REPLAY_CTR_LEN,
6156 roam_info_ptr->replay_ctr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006157 hdd_err("non FT/non CCKM connection");
6158 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08006159 goto nla_put_failure;
6160 }
Vignesh Viswanathan62d98992017-11-30 12:30:37 +05306161 if (roam_info_ptr->kek_len > SIR_KEK_KEY_LEN_FILS ||
6162 nla_put(skb,
Naveen Rawat14298b92015-11-25 16:27:41 -08006163 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
6164 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
6165 nla_put(skb,
6166 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306167 roam_info_ptr->kek_len, roam_info_ptr->kek)) {
Vignesh Viswanathan62d98992017-11-30 12:30:37 +05306168 hdd_err("nla put fail, kek_len %d",
6169 roam_info_ptr->kek_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006170 goto nla_put_failure;
6171 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +05306172
6173 status = wlan_hdd_add_fils_params_roam_auth_event(skb,
6174 roam_info_ptr);
6175 if (status)
6176 goto nla_put_failure;
6177
6178 /*
6179 * Save the gtk rekey parameters in HDD STA context. They will
6180 * be used next time when host enables GTK offload and goes
6181 * into power save state.
6182 */
6183 wlan_hdd_save_gtk_offload_params(adapter, roam_info_ptr->kck,
6184 roam_info_ptr->kek,
6185 roam_info_ptr->kek_len,
6186 roam_info_ptr->replay_ctr,
6187 true);
6188 hdd_debug("roam_info_ptr->replay_ctr 0x%llx",
6189 *((uint64_t *)roam_info_ptr->replay_ctr));
6190
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006191 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07006192 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006193 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
6194 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07006195 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006196 goto nla_put_failure;
6197 }
6198 }
6199
Selvaraj, Sridhard1225e62017-03-17 12:56:58 +05306200 hdd_debug("Auth Status = %d Subnet Change Status = %d",
6201 roam_info_ptr->synchAuthStatus,
6202 roam_info_ptr->subnet_change_status);
Ravi Joshi277ae9b2015-11-13 11:30:43 -08006203
6204 /*
6205 * Add subnet change status if subnet has changed
6206 * 0 = unchanged
6207 * 1 = changed
6208 * 2 = unknown
6209 */
6210 if (roam_info_ptr->subnet_change_status) {
6211 if (nla_put_u8(skb,
6212 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
6213 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07006214 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08006215 goto nla_put_failure;
6216 }
6217 }
6218
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006219 cfg80211_vendor_event(skb, GFP_KERNEL);
6220 return 0;
6221
6222nla_put_failure:
6223 kfree_skb(skb);
6224 return -EINVAL;
6225}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08006226#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006227
lifeng907edd62017-05-12 10:10:36 +08006228#define ANT_DIV_PROBE_PERIOD \
6229 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD
6230#define ANT_DIV_STAY_PERIOD \
6231 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD
6232#define ANT_DIV_SNR_DIFF \
6233 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF
6234#define ANT_DIV_PROBE_DWELL_TIME \
6235 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME
6236#define ANT_DIV_MGMT_SNR_WEIGHT \
6237 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT
6238#define ANT_DIV_DATA_SNR_WEIGHT \
6239 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT
6240#define ANT_DIV_ACK_SNR_WEIGHT \
6241 QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT
lifeng66831662017-05-19 16:01:35 +08006242#define RX_REORDER_TIMEOUT_VOICE \
6243 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VOICE
6244#define RX_REORDER_TIMEOUT_VIDEO \
6245 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VIDEO
6246#define RX_REORDER_TIMEOUT_BESTEFFORT \
6247 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BESTEFFORT
6248#define RX_REORDER_TIMEOUT_BACKGROUND \
6249 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BACKGROUND
6250#define RX_BLOCKSIZE_PEER_MAC \
6251 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_PEER_MAC
6252#define RX_BLOCKSIZE_WINLIMIT \
6253 QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_WINLIMIT
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006254static const struct nla_policy
6255wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
6256
6257 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
6258 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
6259 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Jeff Johnson79f6a602017-06-15 09:48:25 -07006260 [QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT] = {.type = NLA_U32},
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05306261 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05306262 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
6263 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08006264 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
6265 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
6266 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
6267 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
6268 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05306269 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
lifeng907edd62017-05-12 10:10:36 +08006270 [ANT_DIV_PROBE_PERIOD] = {.type = NLA_U32},
6271 [ANT_DIV_STAY_PERIOD] = {.type = NLA_U32},
6272 [ANT_DIV_SNR_DIFF] = {.type = NLA_U32},
6273 [ANT_DIV_PROBE_DWELL_TIME] = {.type = NLA_U32},
6274 [ANT_DIV_MGMT_SNR_WEIGHT] = {.type = NLA_U32},
6275 [ANT_DIV_DATA_SNR_WEIGHT] = {.type = NLA_U32},
6276 [ANT_DIV_ACK_SNR_WEIGHT] = {.type = NLA_U32},
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306277 [QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL] = {.type = NLA_U8},
lifeng66831662017-05-19 16:01:35 +08006278 [RX_REORDER_TIMEOUT_VOICE] = {.type = NLA_U32},
6279 [RX_REORDER_TIMEOUT_VIDEO] = {.type = NLA_U32},
6280 [RX_REORDER_TIMEOUT_BESTEFFORT] = {.type = NLA_U32},
6281 [RX_REORDER_TIMEOUT_BACKGROUND] = {.type = NLA_U32},
Jeff Johnson19a5a7e2017-06-15 14:51:26 -07006282 [RX_BLOCKSIZE_PEER_MAC] = {
6283 .type = NLA_UNSPEC,
6284 .len = QDF_MAC_ADDR_SIZE},
lifeng66831662017-05-19 16:01:35 +08006285 [RX_BLOCKSIZE_WINLIMIT] = {.type = NLA_U32},
Mukul Sharma6398b252017-05-01 17:58:12 +05306286 [QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL] = {.type = NLA_U32 },
Poddar, Siddarth4b3f7312017-11-02 17:00:20 +05306287 [QCA_WLAN_VENDOR_ATTR_CONFIG_LRO] = {.type = NLA_U8 },
lifengd217d192017-05-09 19:44:16 +08006288 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA] = {.type = NLA_U32 },
6289 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN] = {.type = NLA_U32 },
6290 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST] = {.type = NLA_U32 },
6291 [QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL] = {.type = NLA_U32 },
Paul Zhang99fe8842017-12-08 14:43:46 +08006292 [QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL] = {.type = NLA_U16 },
Nachiket Kukadeaaf8a712017-07-27 19:15:36 +05306293 [QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT] = {.type = NLA_U8},
Sandeep Puligilla24b7aa72017-10-13 18:05:14 -07006294 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE] = {.type = NLA_U8 },
Abhishek Singh6454ad32017-12-20 10:42:21 +05306295 [QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE] = {.type = NLA_U8},
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006296};
6297
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006298static const struct nla_policy
6299wlan_hdd_wifi_test_config_policy[
6300 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX + 1] = {
6301 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE] = {
6302 .type = NLA_U8},
6303 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ] = {
6304 .type = NLA_U8},
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08006305 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS] = {
6306 .type = NLA_U8},
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08006307 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ] = {
6308 .type = NLA_U8},
Kiran Kumar Lokere5cc2f0d2018-02-08 17:10:05 -08006309 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION] = {
6310 .type = NLA_U8},
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08006311 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE] = {
6312 .type = NLA_U8},
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08006313 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION] = {
6314 .type = NLA_U8},
6315 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID] = {
6316 .type = NLA_U8},
6317 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE] = {
6318 .type = NLA_U8},
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08006319 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK] = {
6320 .type = NLA_U8},
6321 [QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC] = {
6322 .type = NLA_U8},
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08006323};
6324
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006325/**
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306326 * wlan_hdd_add_qcn_ie() - Add QCN IE to a given IE buffer
6327 * @ie_data: IE buffer
6328 * @ie_len: length of the @ie_data
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306329 *
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306330 * Return: QDF_STATUS
6331 */
6332static QDF_STATUS wlan_hdd_add_qcn_ie(uint8_t *ie_data, uint16_t *ie_len)
6333{
6334 tDot11fIEQCN_IE qcn_ie;
6335 uint8_t qcn_ie_hdr[QCN_IE_HDR_LEN]
6336 = {IE_EID_VENDOR, DOT11F_IE_QCN_IE_MAX_LEN,
6337 0x8C, 0xFD, 0xF0, 0x1};
6338
6339 if (((*ie_len) + QCN_IE_HDR_LEN +
6340 QCN_IE_VERSION_SUBATTR_DATA_LEN) > MAX_DEFAULT_SCAN_IE_LEN) {
6341 hdd_err("IE buffer not enough for QCN IE");
6342 return QDF_STATUS_E_FAILURE;
6343 }
6344
6345 /* Add QCN IE header */
6346 qdf_mem_copy(ie_data + (*ie_len), qcn_ie_hdr, QCN_IE_HDR_LEN);
6347 (*ie_len) += QCN_IE_HDR_LEN;
6348
6349 /* Retrieve Version sub-attribute data */
6350 populate_dot11f_qcn_ie(&qcn_ie);
6351
6352 /* Add QCN IE data[version sub attribute] */
6353 qdf_mem_copy(ie_data + (*ie_len), qcn_ie.version,
6354 (QCN_IE_VERSION_SUBATTR_LEN));
6355 (*ie_len) += (QCN_IE_VERSION_SUBATTR_LEN);
6356
6357 return QDF_STATUS_SUCCESS;
6358}
6359
6360/**
6361 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
6362 * @hdd_ctx: HDD context
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306363 * @adapter: Pointer to HDD adapter
6364 * @ie_data: Pointer to Scan IEs buffer
6365 * @ie_len: Length of Scan IEs
6366 *
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306367 * This API is used to store the default scan ies received from
6368 * supplicant. Also saves QCN IE if g_qcn_ie_support INI is enabled
6369 *
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306370 * Return: 0 on success; error number otherwise
6371 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006372static int wlan_hdd_save_default_scan_ies(struct hdd_context *hdd_ctx,
Jeff Johnsone5006672017-08-29 14:39:02 -07006373 struct hdd_adapter *adapter,
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306374 uint8_t *ie_data, uint16_t ie_len)
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306375{
Jeff Johnson37588942017-08-15 16:11:41 -07006376 struct hdd_scan_info *scan_info = &adapter->scan_info;
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306377 bool add_qcn_ie = hdd_ctx->config->qcn_ie_support;
6378
6379 if (!scan_info)
6380 return -EINVAL;
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306381
6382 if (scan_info->default_scan_ies) {
6383 qdf_mem_free(scan_info->default_scan_ies);
6384 scan_info->default_scan_ies = NULL;
6385 }
6386
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05306387 scan_info->default_scan_ies_len = ie_len;
6388
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306389 if (add_qcn_ie)
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05306390 ie_len += (QCN_IE_HDR_LEN + QCN_IE_VERSION_SUBATTR_LEN);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306391
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306392 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05306393 if (!scan_info->default_scan_ies) {
6394 scan_info->default_scan_ies_len = 0;
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306395 return -ENOMEM;
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05306396 }
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306397
Selvaraj, Sridhar8048dea2017-04-20 10:02:19 +05306398 qdf_mem_copy(scan_info->default_scan_ies, ie_data,
6399 scan_info->default_scan_ies_len);
Selvaraj, Sridhar021ee0a2017-04-07 16:53:31 +05306400
6401 /* Add QCN IE if g_qcn_ie_support INI is enabled */
6402 if (add_qcn_ie)
6403 wlan_hdd_add_qcn_ie(scan_info->default_scan_ies,
6404 &(scan_info->default_scan_ies_len));
6405
6406 hdd_debug("Saved default scan IE:");
6407 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
6408 (uint8_t *) scan_info->default_scan_ies,
6409 scan_info->default_scan_ies_len);
6410
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05306411 return 0;
6412}
6413
6414/**
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306415 * wlan_hdd_handle_restrict_offchan_config() -
6416 * Handle wifi configuration attribute :
6417 * QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL
6418 * @adapter: Pointer to HDD adapter
6419 * @restrict_offchan: Restrict offchannel setting done by
6420 * application
6421 *
6422 * Return: 0 on success; error number otherwise
6423 */
Jeff Johnsone5006672017-08-29 14:39:02 -07006424static int wlan_hdd_handle_restrict_offchan_config(struct hdd_adapter *adapter,
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306425 u8 restrict_offchan)
6426{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006427 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonc1e62782017-11-09 09:50:17 -08006428 enum QDF_OPMODE dev_mode = adapter->device_mode;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306429 int ret_val = 0;
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006430 QDF_STATUS status;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306431
6432 if (!(dev_mode == QDF_SAP_MODE || dev_mode == QDF_P2P_GO_MODE)) {
6433 hdd_err("Invalid interface type:%d", dev_mode);
6434 return -EINVAL;
6435 }
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006436 status = wlan_objmgr_vdev_try_get_ref(adapter->hdd_vdev, WLAN_OSIF_ID);
6437 if (status != QDF_STATUS_SUCCESS) {
6438 hdd_err("Access hdd_vdev failed: %d", status);
6439 return -EINVAL;
6440 }
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306441 if (restrict_offchan == 1) {
6442 enum policy_mgr_con_mode pmode =
6443 policy_mgr_convert_device_mode_to_qdf_type(dev_mode);
6444 int chan;
6445
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006446 u32 vdev_id = wlan_vdev_get_id(adapter->hdd_vdev);
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306447
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006448 wlan_vdev_obj_lock(adapter->hdd_vdev);
6449 wlan_vdev_mlme_cap_set(adapter->hdd_vdev,
6450 WLAN_VDEV_C_RESTRICT_OFFCHAN);
6451 wlan_vdev_obj_unlock(adapter->hdd_vdev);
6452 chan = policy_mgr_get_channel(hdd_ctx->hdd_psoc, pmode,
6453 &vdev_id);
6454 if (!chan ||
6455 wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, chan)) {
6456 hdd_err("unable to send avoid_freq");
6457 ret_val = -EINVAL;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306458 }
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006459 hdd_info("vdev %d mode %d dnbs enabled", vdev_id, dev_mode);
6460 } else if (restrict_offchan == 0) {
6461 wlan_vdev_obj_lock(adapter->hdd_vdev);
6462 wlan_vdev_mlme_cap_clear(adapter->hdd_vdev,
6463 WLAN_VDEV_C_RESTRICT_OFFCHAN);
6464 wlan_vdev_obj_unlock(adapter->hdd_vdev);
6465 if (wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, 0)) {
6466 hdd_err("unable to clear avoid_freq");
6467 ret_val = -EINVAL;
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306468 }
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006469 hdd_info("vdev mode %d dnbs disabled", dev_mode);
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306470 } else {
6471 ret_val = -EINVAL;
6472 hdd_err("Invalid RESTRICT_OFFCHAN setting");
6473 }
Liangwei Dongcf5a5062017-12-28 00:51:32 -05006474 wlan_objmgr_vdev_release_ref(adapter->hdd_vdev, WLAN_OSIF_ID);
Ajit Pal Singh747b6802017-05-24 15:42:03 +05306475 return ret_val;
6476}
6477
6478/**
lifeng66831662017-05-19 16:01:35 +08006479 * wlan_hdd_cfg80211_wifi_set_reorder_timeout - set reorder timeout
6480 *
6481 * @hdd_ctx: hdd context
6482 * @tb: array of pointer to struct nlattr
6483 *
6484 * Return: 0 on success; error number otherwise
6485 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006486static int wlan_hdd_cfg80211_wifi_set_reorder_timeout(struct hdd_context *hdd_ctx,
lifeng66831662017-05-19 16:01:35 +08006487 struct nlattr *tb[])
6488{
Min Liuab6ed4f2018-01-09 13:13:57 +08006489 int ret_val = 0;
lifeng66831662017-05-19 16:01:35 +08006490 QDF_STATUS qdf_status;
6491 struct sir_set_rx_reorder_timeout_val reorder_timeout;
6492
6493#define RX_TIMEOUT_VAL_MIN 10
6494#define RX_TIMEOUT_VAL_MAX 1000
6495
6496 if (tb[RX_REORDER_TIMEOUT_VOICE] ||
6497 tb[RX_REORDER_TIMEOUT_VIDEO] ||
6498 tb[RX_REORDER_TIMEOUT_BESTEFFORT] ||
6499 tb[RX_REORDER_TIMEOUT_BACKGROUND]) {
6500
6501 /* if one is specified, all must be specified */
6502 if (!tb[RX_REORDER_TIMEOUT_VOICE] ||
6503 !tb[RX_REORDER_TIMEOUT_VIDEO] ||
6504 !tb[RX_REORDER_TIMEOUT_BESTEFFORT] ||
6505 !tb[RX_REORDER_TIMEOUT_BACKGROUND]) {
6506 hdd_err("four AC timeout val are required MAC");
6507 return -EINVAL;
6508 }
6509
6510 reorder_timeout.rx_timeout_pri[0] = nla_get_u32(
6511 tb[RX_REORDER_TIMEOUT_VOICE]);
6512 reorder_timeout.rx_timeout_pri[1] = nla_get_u32(
6513 tb[RX_REORDER_TIMEOUT_VIDEO]);
6514 reorder_timeout.rx_timeout_pri[2] = nla_get_u32(
6515 tb[RX_REORDER_TIMEOUT_BESTEFFORT]);
6516 reorder_timeout.rx_timeout_pri[3] = nla_get_u32(
6517 tb[RX_REORDER_TIMEOUT_BACKGROUND]);
6518 /* timeout value is required to be in the rang 10 to 1000ms */
6519 if (reorder_timeout.rx_timeout_pri[0] >= RX_TIMEOUT_VAL_MIN &&
6520 reorder_timeout.rx_timeout_pri[0] <= RX_TIMEOUT_VAL_MAX &&
6521 reorder_timeout.rx_timeout_pri[1] >= RX_TIMEOUT_VAL_MIN &&
6522 reorder_timeout.rx_timeout_pri[1] <= RX_TIMEOUT_VAL_MAX &&
6523 reorder_timeout.rx_timeout_pri[2] >= RX_TIMEOUT_VAL_MIN &&
6524 reorder_timeout.rx_timeout_pri[2] <= RX_TIMEOUT_VAL_MAX &&
6525 reorder_timeout.rx_timeout_pri[3] >= RX_TIMEOUT_VAL_MIN &&
6526 reorder_timeout.rx_timeout_pri[3] <= RX_TIMEOUT_VAL_MAX) {
6527 qdf_status = sme_set_reorder_timeout(hdd_ctx->hHal,
6528 &reorder_timeout);
6529 if (qdf_status != QDF_STATUS_SUCCESS) {
6530 hdd_err("failed to set reorder timeout err %d",
6531 qdf_status);
6532 ret_val = -EPERM;
6533 }
6534 } else {
6535 hdd_err("one of the timeout value is not in range");
6536 ret_val = -EINVAL;
6537 }
6538 }
6539
6540 return ret_val;
6541}
6542
6543/**
6544 * wlan_hdd_cfg80211_wifi_set_rx_blocksize - set rx blocksize
6545 *
6546 * @hdd_ctx: hdd context
6547 * @adapter: hdd adapter
6548 * @tb: array of pointer to struct nlattr
6549 *
6550 * Return: 0 on success; error number otherwise
6551 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006552static int wlan_hdd_cfg80211_wifi_set_rx_blocksize(struct hdd_context *hdd_ctx,
Jeff Johnsone5006672017-08-29 14:39:02 -07006553 struct hdd_adapter *adapter,
lifeng66831662017-05-19 16:01:35 +08006554 struct nlattr *tb[])
6555{
Min Liuab6ed4f2018-01-09 13:13:57 +08006556 int ret_val = 0;
lifeng66831662017-05-19 16:01:35 +08006557 uint32_t set_value;
6558 QDF_STATUS qdf_status;
6559 struct sir_peer_set_rx_blocksize rx_blocksize;
6560
6561#define WINDOW_SIZE_VAL_MIN 1
6562#define WINDOW_SIZE_VAL_MAX 64
6563
6564 if (tb[RX_BLOCKSIZE_PEER_MAC] ||
6565 tb[RX_BLOCKSIZE_WINLIMIT]) {
6566
6567 /* if one is specified, both must be specified */
6568 if (!tb[RX_BLOCKSIZE_PEER_MAC] ||
6569 !tb[RX_BLOCKSIZE_WINLIMIT]) {
Dustin Brownbacc48f2018-03-14 14:48:44 -07006570 hdd_err("Both Peer MAC and windows limit required");
lifeng66831662017-05-19 16:01:35 +08006571 return -EINVAL;
6572 }
6573
6574 memcpy(&rx_blocksize.peer_macaddr,
6575 nla_data(tb[RX_BLOCKSIZE_PEER_MAC]),
6576 sizeof(rx_blocksize.peer_macaddr)),
6577
Jeff Johnson1b780e42017-10-31 14:11:45 -07006578 rx_blocksize.vdev_id = adapter->session_id;
lifeng66831662017-05-19 16:01:35 +08006579 set_value = nla_get_u32(tb[RX_BLOCKSIZE_WINLIMIT]);
6580 /* maximum window size is 64 */
6581 if (set_value >= WINDOW_SIZE_VAL_MIN &&
6582 set_value <= WINDOW_SIZE_VAL_MAX) {
6583 rx_blocksize.rx_block_ack_win_limit = set_value;
6584 qdf_status = sme_set_rx_set_blocksize(hdd_ctx->hHal,
6585 &rx_blocksize);
6586 if (qdf_status != QDF_STATUS_SUCCESS) {
6587 hdd_err("failed to set aggr sizes err %d",
6588 qdf_status);
6589 ret_val = -EPERM;
6590 }
6591 } else {
6592 hdd_err("window size val is not in range");
6593 ret_val = -EINVAL;
6594 }
6595 }
6596
6597 return ret_val;
6598}
6599
Jeff Johnson3b2abe92017-12-15 09:03:47 -08006600static int hdd_config_scan_default_ies(struct hdd_adapter *adapter,
6601 const struct nlattr *attr)
6602{
6603 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
6604 uint8_t *scan_ie;
6605 uint16_t scan_ie_len;
6606 QDF_STATUS status;
6607
6608 if (!attr)
6609 return 0;
6610
6611 scan_ie_len = nla_len(attr);
6612 hdd_debug("IE len %d session %d device mode %d",
6613 scan_ie_len, adapter->session_id, adapter->device_mode);
6614
6615 if (!scan_ie_len) {
6616 hdd_err("zero-length IE prohibited");
6617 return -EINVAL;
6618 }
6619
6620 if (scan_ie_len > MAX_DEFAULT_SCAN_IE_LEN) {
6621 hdd_err("IE length %d exceeds max of %d",
6622 scan_ie_len, MAX_DEFAULT_SCAN_IE_LEN);
6623 return -EINVAL;
6624 }
6625
6626 scan_ie = nla_data(attr);
Jeff Johnson4933c3a2018-01-10 19:33:33 -08006627 if (!wlan_is_ie_valid(scan_ie, scan_ie_len)) {
Jeff Johnson3b2abe92017-12-15 09:03:47 -08006628 hdd_err("Invalid default scan IEs");
6629 return -EINVAL;
6630 }
6631
6632 if (wlan_hdd_save_default_scan_ies(hdd_ctx, adapter,
6633 scan_ie, scan_ie_len))
6634 hdd_err("Failed to save default scan IEs");
6635
6636 if (adapter->device_mode == QDF_STA_MODE) {
6637 status = sme_set_default_scan_ie(hdd_ctx->hHal,
6638 adapter->session_id, scan_ie,
6639 scan_ie_len);
6640 if (QDF_STATUS_SUCCESS != status) {
6641 hdd_err("failed to set default scan IEs in sme: %d",
6642 status);
6643 return -EPERM;
6644 }
6645 }
6646
6647 return 0;
6648}
6649
lifeng66831662017-05-19 16:01:35 +08006650/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006651 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
6652 * vendor command
6653 *
6654 * @wiphy: wiphy device pointer
6655 * @wdev: wireless device pointer
6656 * @data: Vendor command data buffer
6657 * @data_len: Buffer length
6658 *
6659 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
6660 *
6661 * Return: Error code.
6662 */
6663static int
6664__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
6665 struct wireless_dev *wdev,
6666 const void *data,
6667 int data_len)
6668{
6669 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07006670 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07006671 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006672 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
Jeff Johnson3b2abe92017-12-15 09:03:47 -08006673 const struct nlattr *attr;
6674 int ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006675 int ret_val = 0;
Mukul Sharma6398b252017-05-01 17:58:12 +05306676 u32 modulated_dtim, override_li;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006677 u16 stats_avg_factor;
6678 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05306679 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07006680 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07006681 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306682 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05306683 int attr_len;
6684 int access_policy = 0;
6685 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
6686 bool vendor_ie_present = false, access_policy_present = false;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05306687 struct sir_set_tx_rx_aggregation_size request;
6688 QDF_STATUS qdf_status;
Sandeep Puligilla24b7aa72017-10-13 18:05:14 -07006689 uint8_t retry, delay, enable_flag;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08006690 uint32_t abs_delay;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08006691 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05306692 uint32_t tx_fail_count;
lifeng907edd62017-05-12 10:10:36 +08006693 uint32_t ant_div_usrcfg;
lifengd217d192017-05-09 19:44:16 +08006694 uint32_t antdiv_enable, antdiv_chain;
6695 uint32_t antdiv_selftest, antdiv_selftest_intvl;
Nachiket Kukadeaaf8a712017-07-27 19:15:36 +05306696 uint8_t bmiss_bcnt;
Paul Zhang99fe8842017-12-08 14:43:46 +08006697 uint16_t latency_level;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05306698
Dustin Brownfdf17c12018-03-14 12:55:34 -07006699 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08006700
Anurag Chouhan6d760662016-02-20 16:05:43 +05306701 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006702 hdd_err("Command not allowed in FTM mode");
6703 return -EPERM;
6704 }
6705
6706 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05306707 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006708 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006709
Dustin Brown4ea21db2018-01-05 14:13:17 -08006710 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX, data,
6711 data_len, wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006712 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006713 return -EINVAL;
6714 }
6715
Krunal Sonie3531942016-04-12 17:43:53 -07006716 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
6717 ftm_capab = nla_get_u32(tb[
6718 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
6719 hdd_ctx->config->fine_time_meas_cap =
6720 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
6721 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Jeff Johnson1b780e42017-10-31 14:11:45 -07006722 adapter->session_id,
Krunal Sonie3531942016-04-12 17:43:53 -07006723 hdd_ctx->config->fine_time_meas_cap);
Naveen Rawatd2657be2017-10-10 14:31:23 -07006724 ucfg_wifi_pos_set_ftm_cap(hdd_ctx->hdd_psoc,
Naveen Rawat5f040ba2017-03-06 12:20:25 -08006725 hdd_ctx->config->fine_time_meas_cap);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006726 hdd_debug("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
Krunal Sonie3531942016-04-12 17:43:53 -07006727 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
6728 hdd_ctx->config->fine_time_meas_cap);
6729 }
6730
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006731 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
6732 modulated_dtim = nla_get_u32(
6733 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
6734
6735 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
Jeff Johnson1b780e42017-10-31 14:11:45 -07006736 adapter->session_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006737 modulated_dtim);
6738
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306739 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006740 ret_val = -EPERM;
6741 }
6742
Mukul Sharma6398b252017-05-01 17:58:12 +05306743 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL]) {
6744 override_li = nla_get_u32(
6745 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL]);
6746
6747 status = sme_override_listen_interval(hdd_ctx->hHal,
Jeff Johnson1b780e42017-10-31 14:11:45 -07006748 adapter->session_id,
Mukul Sharma6398b252017-05-01 17:58:12 +05306749 override_li);
6750
6751 if (status != QDF_STATUS_SUCCESS)
6752 ret_val = -EPERM;
6753 }
Poddar, Siddarth4b3f7312017-11-02 17:00:20 +05306754
6755 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_LRO]) {
6756 enable_flag = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_LRO]);
6757 ret_val = hdd_lro_set_reset(hdd_ctx, adapter,
6758 enable_flag);
6759 }
6760
Sandeep Puligilla24b7aa72017-10-13 18:05:14 -07006761 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE]) {
6762 enable_flag =
6763 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE]);
6764 sme_set_scan_disable(hdd_ctx->hHal, !enable_flag);
6765 }
Mukul Sharma6398b252017-05-01 17:58:12 +05306766
Kapil Gupta6213c012016-09-02 19:39:09 +05306767 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
6768 qpower = nla_get_u8(
6769 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
6770 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
6771 ret_val = -EINVAL;
6772 }
6773
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006774 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
6775 stats_avg_factor = nla_get_u16(
6776 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
6777 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
Jeff Johnson1b780e42017-10-31 14:11:45 -07006778 adapter->session_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006779 stats_avg_factor);
6780
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306781 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006782 ret_val = -EPERM;
6783 }
6784
6785
6786 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
6787 guard_time = nla_get_u32(
6788 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
6789 status = sme_configure_guard_time(hdd_ctx->hHal,
Jeff Johnson1b780e42017-10-31 14:11:45 -07006790 adapter->session_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006791 guard_time);
6792
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306793 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006794 ret_val = -EPERM;
6795 }
6796
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05306797 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
6798 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
6799 attr_len = nla_len(
6800 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
6801 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006802 hdd_err("Invalid value. attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05306803 attr_len);
6804 return -EINVAL;
6805 }
6806
6807 nla_memcpy(&vendor_ie,
6808 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
6809 attr_len);
6810 vendor_ie_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006811 hdd_debug("Access policy vendor ie present.attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05306812 attr_len);
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05306813 }
6814
6815 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
6816 access_policy = (int) nla_get_u32(
6817 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
6818 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
6819 (access_policy >
6820 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006821 hdd_err("Invalid value. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05306822 access_policy);
6823 return -EINVAL;
6824 }
6825 access_policy_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006826 hdd_debug("Access policy present. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05306827 access_policy);
6828 }
6829
Zhang Qiana3bcbe02016-08-12 16:20:36 +08006830 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
6831 retry = nla_get_u8(tb[
6832 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
6833 retry = retry > CFG_NON_AGG_RETRY_MAX ?
6834 CFG_NON_AGG_RETRY_MAX : retry;
6835 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
Jeff Johnson1b780e42017-10-31 14:11:45 -07006836 ret_val = wma_cli_set_command(adapter->session_id, param_id,
Zhang Qiana3bcbe02016-08-12 16:20:36 +08006837 retry, PDEV_CMD);
6838 }
6839
6840 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
6841 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
6842 retry = retry > CFG_AGG_RETRY_MAX ?
6843 CFG_AGG_RETRY_MAX : retry;
6844
6845 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
6846 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
6847 CFG_AGG_RETRY_MIN : retry;
6848 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
Jeff Johnson1b780e42017-10-31 14:11:45 -07006849 ret_val = wma_cli_set_command(adapter->session_id, param_id,
Zhang Qiana3bcbe02016-08-12 16:20:36 +08006850 retry, PDEV_CMD);
6851 }
6852
6853 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
6854 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
6855 retry = retry > CFG_MGMT_RETRY_MAX ?
6856 CFG_MGMT_RETRY_MAX : retry;
6857 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
Jeff Johnson1b780e42017-10-31 14:11:45 -07006858 ret_val = wma_cli_set_command(adapter->session_id, param_id,
Zhang Qiana3bcbe02016-08-12 16:20:36 +08006859 retry, PDEV_CMD);
6860 }
6861
6862 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
6863 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
6864 retry = retry > CFG_CTRL_RETRY_MAX ?
6865 CFG_CTRL_RETRY_MAX : retry;
6866 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
Jeff Johnson1b780e42017-10-31 14:11:45 -07006867 ret_val = wma_cli_set_command(adapter->session_id, param_id,
Zhang Qiana3bcbe02016-08-12 16:20:36 +08006868 retry, PDEV_CMD);
6869 }
6870
6871 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
6872 delay = nla_get_u8(tb[
6873 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
6874 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
6875 CFG_PROPAGATION_DELAY_MAX : delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08006876 abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08006877 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
Jeff Johnson1b780e42017-10-31 14:11:45 -07006878 ret_val = wma_cli_set_command(adapter->session_id, param_id,
Zhang Qiane9fd14b2017-03-08 11:29:00 +08006879 abs_delay, PDEV_CMD);
6880 }
6881
6882 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]) {
6883 abs_delay = nla_get_u8(tb[
6884 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]);
6885 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
Jeff Johnson1b780e42017-10-31 14:11:45 -07006886 ret_val = wma_cli_set_command(adapter->session_id, param_id,
Zhang Qiane9fd14b2017-03-08 11:29:00 +08006887 abs_delay, PDEV_CMD);
Zhang Qiana3bcbe02016-08-12 16:20:36 +08006888 }
6889
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05306890 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
6891 tx_fail_count = nla_get_u32(
6892 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
6893 if (tx_fail_count) {
6894 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
Jeff Johnson1b780e42017-10-31 14:11:45 -07006895 adapter->session_id, tx_fail_count);
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05306896 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006897 hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05306898 status);
6899 return -EINVAL;
6900 }
6901 }
6902 }
6903
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05306904 if (vendor_ie_present && access_policy_present) {
6905 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
6906 access_policy =
6907 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05306908 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05306909 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05306910 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05306911
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006912 hdd_debug("calling sme_update_access_policy_vendor_ie");
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05306913 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
Jeff Johnson1b780e42017-10-31 14:11:45 -07006914 adapter->session_id, &vendor_ie[0],
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05306915 access_policy);
6916 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006917 hdd_err("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05306918 return -EINVAL;
6919 }
6920 }
6921
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05306922 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
6923 set_value = nla_get_u8(
6924 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006925 hdd_debug("set_value: %d", set_value);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05306926 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
6927 }
6928
Jeff Johnson3b2abe92017-12-15 09:03:47 -08006929 attr = tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES];
6930 ret = hdd_config_scan_default_ies(adapter, attr);
6931 if (ret)
6932 ret_val = ret;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05306933
6934 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
6935 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
6936 /* if one is specified, both must be specified */
6937 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
6938 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
6939 hdd_err("Both TX and RX MPDU Aggregation required");
6940 return -EINVAL;
6941 }
6942
6943 request.tx_aggregation_size = nla_get_u8(
6944 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
6945 request.rx_aggregation_size = nla_get_u8(
6946 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
Jeff Johnson1b780e42017-10-31 14:11:45 -07006947 request.vdev_id = adapter->session_id;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05306948
6949 if (request.tx_aggregation_size >=
6950 CFG_TX_AGGREGATION_SIZE_MIN &&
6951 request.tx_aggregation_size <=
6952 CFG_TX_AGGREGATION_SIZE_MAX &&
6953 request.rx_aggregation_size >=
6954 CFG_RX_AGGREGATION_SIZE_MIN &&
6955 request.rx_aggregation_size <=
6956 CFG_RX_AGGREGATION_SIZE_MAX) {
6957 qdf_status = wma_set_tx_rx_aggregation_size(&request);
6958 if (qdf_status != QDF_STATUS_SUCCESS) {
6959 hdd_err("failed to set aggr sizes err %d",
6960 qdf_status);
6961 ret_val = -EPERM;
6962 }
6963 } else {
6964 hdd_err("TX %d RX %d MPDU aggr size not in range",
6965 request.tx_aggregation_size,
6966 request.rx_aggregation_size);
6967 ret_val = -EINVAL;
6968 }
6969 }
6970
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05306971 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
6972 uint8_t ignore_assoc_disallowed;
6973
6974 ignore_assoc_disallowed
6975 = nla_get_u8(tb[
6976 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006977 hdd_debug("Set ignore_assoc_disallowed value - %d",
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05306978 ignore_assoc_disallowed);
6979 if ((ignore_assoc_disallowed <
6980 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
6981 (ignore_assoc_disallowed >
6982 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
6983 return -EPERM;
6984
6985 sme_update_session_param(hdd_ctx->hHal,
Jeff Johnson1b780e42017-10-31 14:11:45 -07006986 adapter->session_id,
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05306987 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
6988 ignore_assoc_disallowed);
6989 }
6990
lifeng907edd62017-05-12 10:10:36 +08006991#define ANT_DIV_SET_PERIOD(probe_period, stay_period) \
6992 ((1<<26)|((probe_period&0x1fff)<<13)|(stay_period&0x1fff))
6993
6994#define ANT_DIV_SET_SNR_DIFF(snr_diff) \
6995 ((1<<27)|(snr_diff&0x1fff))
6996
6997#define ANT_DIV_SET_PROBE_DWELL_TIME(probe_dwell_time) \
6998 ((1<<28)|(probe_dwell_time&0x1fff))
6999
7000#define ANT_DIV_SET_WEIGHT(mgmt_snr_weight, data_snr_weight, ack_snr_weight) \
7001 ((1<<29)|((mgmt_snr_weight&0xff)<<16)|((data_snr_weight&0xff)<<8)| \
7002 (ack_snr_weight&0xff))
7003
7004 if (tb[ANT_DIV_PROBE_PERIOD] ||
7005 tb[ANT_DIV_STAY_PERIOD]) {
7006
7007 if (!tb[ANT_DIV_PROBE_PERIOD] ||
7008 !tb[ANT_DIV_STAY_PERIOD]) {
7009 hdd_err("Both probe and stay period required");
7010 return -EINVAL;
7011 }
7012
7013 ant_div_usrcfg = ANT_DIV_SET_PERIOD(
7014 nla_get_u32(tb[ANT_DIV_PROBE_PERIOD]),
7015 nla_get_u32(tb[ANT_DIV_STAY_PERIOD]));
7016 hdd_debug("ant div set period: %x", ant_div_usrcfg);
Jeff Johnson1b780e42017-10-31 14:11:45 -07007017 ret_val = wma_cli_set_command((int)adapter->session_id,
lifeng907edd62017-05-12 10:10:36 +08007018 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
7019 ant_div_usrcfg, PDEV_CMD);
7020 if (ret_val) {
7021 hdd_err("Failed to set ant div period");
7022 return ret_val;
7023 }
7024 }
7025
7026 if (tb[ANT_DIV_SNR_DIFF]) {
7027 ant_div_usrcfg = ANT_DIV_SET_SNR_DIFF(
7028 nla_get_u32(tb[ANT_DIV_SNR_DIFF]));
7029 hdd_debug("ant div set snr diff: %x", ant_div_usrcfg);
Jeff Johnson1b780e42017-10-31 14:11:45 -07007030 ret_val = wma_cli_set_command((int)adapter->session_id,
lifeng907edd62017-05-12 10:10:36 +08007031 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
7032 ant_div_usrcfg, PDEV_CMD);
7033 if (ret_val) {
7034 hdd_err("Failed to set ant snr diff");
7035 return ret_val;
7036 }
7037 }
7038
7039 if (tb[ANT_DIV_PROBE_DWELL_TIME]) {
7040 ant_div_usrcfg = ANT_DIV_SET_PROBE_DWELL_TIME(
7041 nla_get_u32(tb[ANT_DIV_PROBE_DWELL_TIME]));
7042 hdd_debug("ant div set probe dewll time: %x",
7043 ant_div_usrcfg);
Jeff Johnson1b780e42017-10-31 14:11:45 -07007044 ret_val = wma_cli_set_command((int)adapter->session_id,
lifeng907edd62017-05-12 10:10:36 +08007045 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
7046 ant_div_usrcfg, PDEV_CMD);
7047 if (ret_val) {
7048 hdd_err("Failed to set ant div probe dewll time");
7049 return ret_val;
7050 }
7051 }
7052
7053 if (tb[ANT_DIV_MGMT_SNR_WEIGHT] ||
7054 tb[ANT_DIV_DATA_SNR_WEIGHT] ||
7055 tb[ANT_DIV_ACK_SNR_WEIGHT]) {
7056
7057 if (!tb[ANT_DIV_MGMT_SNR_WEIGHT] ||
7058 !tb[ANT_DIV_DATA_SNR_WEIGHT] ||
7059 !tb[ANT_DIV_ACK_SNR_WEIGHT]) {
7060 hdd_err("Mgmt snr, data snr and ack snr weight are required");
7061 return -EINVAL;
7062 }
7063
7064 ant_div_usrcfg = ANT_DIV_SET_WEIGHT(
7065 nla_get_u32(tb[ANT_DIV_MGMT_SNR_WEIGHT]),
7066 nla_get_u32(tb[ANT_DIV_DATA_SNR_WEIGHT]),
7067 nla_get_u32(tb[ANT_DIV_ACK_SNR_WEIGHT]));
7068 hdd_debug("ant div set weight: %x", ant_div_usrcfg);
Jeff Johnson1b780e42017-10-31 14:11:45 -07007069 ret_val = wma_cli_set_command((int)adapter->session_id,
lifeng907edd62017-05-12 10:10:36 +08007070 (int)WMI_PDEV_PARAM_ANT_DIV_USRCFG,
7071 ant_div_usrcfg, PDEV_CMD);
7072 if (ret_val) {
7073 hdd_err("Failed to set ant div weight");
7074 return ret_val;
7075 }
7076 }
7077
Ajit Pal Singh747b6802017-05-24 15:42:03 +05307078 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL]) {
7079 u8 restrict_offchan = nla_get_u8(
7080 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL]);
7081
7082 hdd_debug("Restrict offchannel:%d", restrict_offchan);
7083 if (restrict_offchan <= 1)
7084 ret_val =
7085 wlan_hdd_handle_restrict_offchan_config(adapter,
7086 restrict_offchan);
7087 else {
7088 ret_val = -EINVAL;
7089 hdd_err("Invalid RESTRICT_OFFCHAN setting");
7090 }
7091 }
lifeng66831662017-05-19 16:01:35 +08007092
7093 ret_val =
7094 wlan_hdd_cfg80211_wifi_set_reorder_timeout(hdd_ctx, tb);
7095 if (ret_val != 0)
7096 return ret_val;
7097
7098 ret_val =
7099 wlan_hdd_cfg80211_wifi_set_rx_blocksize(hdd_ctx, adapter, tb);
7100 if (ret_val != 0)
7101 return ret_val;
7102
lifengd217d192017-05-09 19:44:16 +08007103 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA]) {
7104 antdiv_enable = nla_get_u32(
7105 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA]);
7106 hdd_debug("antdiv_enable: %d", antdiv_enable);
Jeff Johnson1b780e42017-10-31 14:11:45 -07007107 ret_val = wma_cli_set_command((int)adapter->session_id,
lifengd217d192017-05-09 19:44:16 +08007108 (int)WMI_PDEV_PARAM_ENA_ANT_DIV,
7109 antdiv_enable, PDEV_CMD);
7110 if (ret_val) {
7111 hdd_err("Failed to set antdiv_enable");
7112 return ret_val;
7113 }
7114 }
7115
7116 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN]) {
7117 antdiv_chain = nla_get_u32(
7118 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN]);
7119 hdd_debug("antdiv_chain: %d", antdiv_chain);
Jeff Johnson1b780e42017-10-31 14:11:45 -07007120 ret_val = wma_cli_set_command((int)adapter->session_id,
lifengd217d192017-05-09 19:44:16 +08007121 (int)WMI_PDEV_PARAM_FORCE_CHAIN_ANT,
7122 antdiv_chain, PDEV_CMD);
7123 if (ret_val) {
7124 hdd_err("Failed to set antdiv_chain");
7125 return ret_val;
7126 }
7127 }
7128
7129 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST]) {
7130 antdiv_selftest = nla_get_u32(
7131 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST]);
7132 hdd_debug("antdiv_selftest: %d", antdiv_selftest);
Jeff Johnson1b780e42017-10-31 14:11:45 -07007133 ret_val = wma_cli_set_command((int)adapter->session_id,
lifengd217d192017-05-09 19:44:16 +08007134 (int)WMI_PDEV_PARAM_ANT_DIV_SELFTEST,
7135 antdiv_selftest, PDEV_CMD);
7136 if (ret_val) {
7137 hdd_err("Failed to set antdiv_selftest");
7138 return ret_val;
7139 }
7140 }
7141
7142 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL]) {
7143 antdiv_selftest_intvl = nla_get_u32(
7144 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL]);
7145 hdd_debug("antdiv_selftest_intvl: %d",
7146 antdiv_selftest_intvl);
Jeff Johnson1b780e42017-10-31 14:11:45 -07007147 ret_val = wma_cli_set_command((int)adapter->session_id,
lifengd217d192017-05-09 19:44:16 +08007148 (int)WMI_PDEV_PARAM_ANT_DIV_SELFTEST_INTVL,
7149 antdiv_selftest_intvl, PDEV_CMD);
7150 if (ret_val) {
7151 hdd_err("Failed to set antdiv_selftest_intvl");
7152 return ret_val;
7153 }
7154 }
7155
Nachiket Kukadeaaf8a712017-07-27 19:15:36 +05307156 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT]) {
7157 bmiss_bcnt = nla_get_u8(
7158 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT]);
7159 if (hdd_ctx->config->nRoamBmissFirstBcnt < bmiss_bcnt) {
7160 hdd_ctx->config->nRoamBmissFinalBcnt = bmiss_bcnt
7161 - hdd_ctx->config->nRoamBmissFirstBcnt;
7162 hdd_debug("Bmiss first cnt(%d), Bmiss final cnt(%d)",
7163 hdd_ctx->config->nRoamBmissFirstBcnt,
7164 hdd_ctx->config->nRoamBmissFinalBcnt);
7165 ret_val = sme_set_roam_bmiss_final_bcnt(hdd_ctx->hHal,
7166 0, hdd_ctx->config->nRoamBmissFinalBcnt);
7167
7168 if (ret_val) {
7169 hdd_err("Failed to set bmiss final Bcnt");
7170 return ret_val;
7171 }
7172
Jeff Johnson1b780e42017-10-31 14:11:45 -07007173 ret_val = sme_set_bmiss_bcnt(adapter->session_id,
Nachiket Kukadeaaf8a712017-07-27 19:15:36 +05307174 hdd_ctx->config->nRoamBmissFirstBcnt,
7175 hdd_ctx->config->nRoamBmissFinalBcnt);
7176 if (ret_val) {
7177 hdd_err("Failed to set bmiss Bcnt");
7178 return ret_val;
7179 }
7180 } else {
7181 hdd_err("Bcnt(%d) needs to exceed BmissFirstBcnt(%d)",
7182 bmiss_bcnt,
7183 hdd_ctx->config->nRoamBmissFirstBcnt);
7184 return -EINVAL;
7185 }
7186 }
Paul Zhang99fe8842017-12-08 14:43:46 +08007187
7188 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL]) {
7189 latency_level = nla_get_u16(
7190 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL]);
7191
7192 if ((latency_level >
7193 QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MAX) ||
7194 (latency_level ==
7195 QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_INVALID)) {
7196 hdd_err("Invalid Wlan latency level value");
7197 return -EINVAL;
7198 }
7199
7200 /* Mapping the latency value to the level which fw expected
7201 * 0 - normal, 1 - moderate, 2 - low, 3 - ultralow
7202 */
7203 latency_level = latency_level - 1;
7204 qdf_status = sme_set_wlm_latency_level(hdd_ctx->hHal,
7205 adapter->session_id,
7206 latency_level);
7207 if (qdf_status != QDF_STATUS_SUCCESS) {
7208 hdd_err("set Wlan latency level failed");
7209 ret_val = -EINVAL;
7210 }
7211 }
7212
Vignesh Viswanathan32761e42017-09-25 17:10:54 +05307213 if (adapter->device_mode == QDF_STA_MODE &&
7214 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_DISABLE_FILS]) {
7215 uint8_t disable_fils;
7216
7217 disable_fils = nla_get_u8(tb[
7218 QCA_WLAN_VENDOR_ATTR_CONFIG_DISABLE_FILS]);
7219 hdd_debug("Set disable_fils - %d", disable_fils);
7220
7221 qdf_status = sme_update_fils_setting(hdd_ctx->hHal,
7222 adapter->session_id,
7223 disable_fils);
7224 if (qdf_status != QDF_STATUS_SUCCESS) {
7225 hdd_err("set disable_fils failed");
7226 ret_val = -EINVAL;
7227 }
7228 }
Nachiket Kukadeaaf8a712017-07-27 19:15:36 +05307229
Abhishek Singh6454ad32017-12-20 10:42:21 +05307230 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE] &&
7231 hdd_ctx->config->force_rsne_override) {
7232 uint8_t force_rsne_override;
7233
7234 force_rsne_override =
7235 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE]);
7236 if (force_rsne_override > 1) {
7237 hdd_err("Invalid test_mode %d", force_rsne_override);
7238 ret_val = -EINVAL;
7239 }
7240
7241 hdd_ctx->force_rsne_override = force_rsne_override;
7242 hdd_debug("force_rsne_override - %d",
7243 hdd_ctx->force_rsne_override);
7244 }
7245
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007246 return ret_val;
7247}
7248
7249/**
7250 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
7251 * vendor command
7252 *
7253 * @wiphy: wiphy device pointer
7254 * @wdev: wireless device pointer
7255 * @data: Vendor command data buffer
7256 * @data_len: Buffer length
7257 *
7258 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
7259 *
7260 * Return: EOK or other error codes.
7261 */
7262static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
7263 struct wireless_dev *wdev,
7264 const void *data,
7265 int data_len)
7266{
7267 int ret;
7268
7269 cds_ssr_protect(__func__);
7270 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
7271 data, data_len);
7272 cds_ssr_unprotect(__func__);
7273
7274 return ret;
7275}
7276
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007277/**
7278 * __wlan_hdd_cfg80211_set_wifi_test_config() - Wifi test configuration
7279 * vendor command
7280 *
7281 * @wiphy: wiphy device pointer
7282 * @wdev: wireless device pointer
7283 * @data: Vendor command data buffer
7284 * @data_len: Buffer length
7285 *
7286 * Handles QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX
7287 *
7288 * Return: Error code.
7289 */
7290static int
7291__wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
7292 struct wireless_dev *wdev, const void *data, int data_len) {
7293
7294 struct net_device *dev = wdev->netdev;
7295 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7296 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
7297 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX + 1];
7298 int ret_val = 0;
7299 uint8_t cfg_val = 0;
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08007300 uint8_t set_val = 0;
Krunal Soni707eb782018-01-18 12:04:19 -08007301 tSmeConfigParams *sme_config;
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08007302 bool update_sme_cfg = false;
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08007303 uint8_t tid = 0, ac;
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007304 uint16_t buff_size = 0;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007305
Dustin Brownfdf17c12018-03-14 12:55:34 -07007306 hdd_enter_dev(dev);
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007307
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08007308 sme_config = qdf_mem_malloc(sizeof(*sme_config));
7309 if (!sme_config) {
7310 hdd_err("mem alloc failed for sme_config");
7311 return -ENOMEM;
7312 }
7313 sme_get_config_param(hdd_ctx->hHal, sme_config);
7314
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007315 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7316 hdd_err("Command not allowed in FTM mode");
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007317 ret_val = -EPERM;
7318 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007319 }
7320
7321 ret_val = wlan_hdd_validate_context(hdd_ctx);
7322 if (ret_val)
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007323 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007324
7325 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
7326 hdd_err("Driver Modules are closed, can not start logger");
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007327 ret_val = -EINVAL;
7328 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007329 }
7330
7331 if (wlan_cfg80211_nla_parse(tb,
7332 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX,
7333 data, data_len, wlan_hdd_wifi_test_config_policy)) {
7334 hdd_err("invalid attr");
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007335 ret_val = -EINVAL;
7336 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007337 }
7338
7339 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ]) {
7340 cfg_val = nla_get_u8(tb[
7341 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ]
7342 );
7343 hdd_debug("set addba accept req from peer value %d", cfg_val);
7344 ret_val = sme_set_addba_accept(hdd_ctx->hHal,
7345 adapter->session_id, cfg_val);
7346 if (ret_val)
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007347 goto send_err;
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007348 }
7349
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08007350 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS]) {
7351 cfg_val = nla_get_u8(tb[
7352 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS]);
7353 hdd_debug("set HE MCS value 0x%0X", cfg_val);
7354 ret_val = sme_update_he_mcs(hdd_ctx->hHal, adapter->session_id,
7355 cfg_val);
7356 if (ret_val)
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007357 goto send_err;
Kiran Kumar Lokere96246e52018-01-24 16:44:35 -08007358 }
7359
Krunal Soni707eb782018-01-18 12:04:19 -08007360 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE]) {
7361 cfg_val = nla_get_u8(tb[
7362 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE]);
Krunal Soni707eb782018-01-18 12:04:19 -08007363 if (!cfg_val) {
7364 sme_config->csrConfig.WMMSupportMode =
7365 hdd_to_csr_wmm_mode(HDD_WMM_USER_MODE_NO_QOS);
7366 hdd_debug("wmm is disabled");
7367 } else {
7368 sme_config->csrConfig.WMMSupportMode =
7369 hdd_to_csr_wmm_mode(hdd_ctx->config->WmmMode);
7370 hdd_debug("using wmm default value");
7371 }
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08007372 update_sme_cfg = true;
Krunal Soni707eb782018-01-18 12:04:19 -08007373 }
7374
Kiran Kumar Lokerea9345612018-02-08 14:28:24 -08007375 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ]) {
7376 cfg_val = nla_get_u8(tb[
7377 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ]);
7378 if (cfg_val) {
7379 /*Auto BA mode*/
7380 set_val = 0;
7381 hdd_debug("BA operating mode is set to auto");
7382 } else {
7383 /*Manual BA mode*/
7384 set_val = 1;
7385 hdd_debug("BA operating mode is set to Manual");
7386 }
7387
7388 ret_val = wma_cli_set_command(adapter->session_id,
7389 WMI_VDEV_PARAM_BA_MODE, set_val, VDEV_CMD);
7390 }
7391
Kiran Kumar Lokere5cc2f0d2018-02-08 17:10:05 -08007392 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION]) {
7393 cfg_val = nla_get_u8(tb[
7394 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION]
7395 );
7396 if (cfg_val > HE_FRAG_LEVEL1)
7397 set_val = HE_FRAG_LEVEL1;
7398 else
7399 set_val = cfg_val;
7400
7401 hdd_debug("set HE fragmention to %d", set_val);
7402 ret_val = sme_update_he_frag_supp(hdd_ctx->hHal,
7403 adapter->session_id, set_val);
7404 }
7405
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08007406 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE]) {
7407 cfg_val = nla_get_u8(tb[
7408 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE]);
7409 sme_config->csrConfig.wep_tkip_in_he = cfg_val;
7410 hdd_debug("Set WEP/TKIP allow in HE %d", cfg_val);
7411
7412 update_sme_cfg = true;
7413 }
7414
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007415 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION]) {
7416 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID]) {
7417 tid = nla_get_u8(tb[
7418 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID]);
7419 } else {
7420 hdd_err("TID is not set for ADD/DEL BA cfg");
7421 ret_val = -EINVAL;
7422 goto send_err;
7423 }
7424 cfg_val = nla_get_u8(tb[
7425 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION]);
7426 if (cfg_val == QCA_WLAN_ADD_BA) {
7427 if (tb[
7428 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE])
7429 buff_size = nla_get_u8(tb[
7430 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]);
7431 ret_val = sme_send_addba_req(hdd_ctx->hHal,
7432 adapter->session_id, tid, buff_size);
7433 } else if (cfg_val == QCA_WLAN_DELETE_BA) {
7434 } else {
7435 hdd_err("Invalid BA session cfg");
7436 ret_val = -EINVAL;
7437 goto send_err;
7438 }
7439 } else if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]) {
7440 buff_size = nla_get_u8(tb[
7441 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]);
7442 hdd_debug("set buff size to %d for all tids", buff_size);
7443 ret_val = sme_set_ba_buff_size(hdd_ctx->hHal,
7444 adapter->session_id, buff_size);
7445 if (ret_val)
7446 goto send_err;
7447 if (buff_size > 64)
7448 /* Configure ADDBA req buffer size to 256 */
7449 set_val = 3;
7450 else
7451 /* Configure ADDBA req buffer size to 64 */
7452 set_val = 2;
7453 ret_val = wma_cli_set_command(adapter->session_id,
7454 WMI_VDEV_PARAM_BA_MODE, set_val, VDEV_CMD);
7455 }
7456
Kiran Kumar Lokere3324f632018-03-01 21:43:21 -08007457 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK]) {
7458 if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC]) {
7459 ac = nla_get_u8(tb[
7460 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC]);
7461 } else {
7462 hdd_err("AC is not set for NO ACK policy config");
7463 ret_val = -EINVAL;
7464 goto send_err;
7465 }
7466 cfg_val = nla_get_u8(tb[
7467 QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK]);
7468 hdd_debug("Set NO_ACK to %d for ac %d", cfg_val, ac);
7469 ret_val = sme_set_no_ack_policy(hdd_ctx->hHal,
7470 adapter->session_id, cfg_val, ac);
7471 }
7472
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08007473 if (update_sme_cfg)
7474 sme_update_config(hdd_ctx->hHal, sme_config);
7475
Kiran Kumar Lokerebc87bec2018-02-27 20:06:42 -08007476send_err:
Kiran Kumar Lokere722dccd2018-02-23 13:23:52 -08007477 qdf_mem_free(sme_config);
7478
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -08007479 return ret_val;
7480}
7481
7482/**
7483 * wlan_hdd_cfg80211_set_wifi_test_config() - Wifi test configuration
7484 * vendor command
7485 *
7486 * @wiphy: wiphy device pointer
7487 * @wdev: wireless device pointer
7488 * @data: Vendor command data buffer
7489 * @data_len: Buffer length
7490 *
7491 * Handles QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX
7492 *
7493 * Return: EOK or other error codes.
7494 */
7495static int wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
7496 struct wireless_dev *wdev, const void *data, int data_len)
7497{
7498 int ret;
7499
7500 cds_ssr_protect(__func__);
7501 ret = __wlan_hdd_cfg80211_set_wifi_test_config(wiphy, wdev,
7502 data, data_len);
7503 cds_ssr_unprotect(__func__);
7504
7505 return ret;
7506}
7507
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007508static const struct
7509nla_policy
7510qca_wlan_vendor_wifi_logger_start_policy
7511[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
7512 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
7513 = {.type = NLA_U32 },
7514 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
7515 = {.type = NLA_U32 },
7516 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
7517 = {.type = NLA_U32 },
7518};
7519
7520/**
7521 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
7522 * or disable the collection of packet statistics from the firmware
7523 * @wiphy: WIPHY structure pointer
7524 * @wdev: Wireless device structure pointer
7525 * @data: Pointer to the data received
7526 * @data_len: Length of the data received
7527 *
7528 * This function enables or disables the collection of packet statistics from
7529 * the firmware
7530 *
7531 * Return: 0 on success and errno on failure
7532 */
7533static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
7534 struct wireless_dev *wdev,
7535 const void *data,
7536 int data_len)
7537{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307538 QDF_STATUS status;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07007539 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007540 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
7541 struct sir_wifi_start_log start_log;
7542
Dustin Brownfdf17c12018-03-14 12:55:34 -07007543 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08007544
Anurag Chouhan6d760662016-02-20 16:05:43 +05307545 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007546 hdd_err("Command not allowed in FTM mode");
7547 return -EPERM;
7548 }
7549
7550 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05307551 if (status)
7552 return status;
7553
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05307554 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
7555 hdd_err("Driver Modules are closed, can not start logger");
7556 return -EINVAL;
7557 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007558
Dustin Brown4ea21db2018-01-05 14:13:17 -08007559 if (wlan_cfg80211_nla_parse(tb,
7560 QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
7561 data, data_len,
7562 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007563 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007564 return -EINVAL;
7565 }
7566
7567 /* Parse and fetch ring id */
7568 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007569 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007570 return -EINVAL;
7571 }
7572 start_log.ring_id = nla_get_u32(
7573 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007574 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007575
7576 /* Parse and fetch verbose level */
7577 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007578 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007579 return -EINVAL;
7580 }
7581 start_log.verbose_level = nla_get_u32(
7582 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007583 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007584
7585 /* Parse and fetch flag */
7586 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007587 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007588 return -EINVAL;
7589 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05307590 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007591 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007592
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307593 /* size is buff size which can be set using iwpriv command*/
7594 start_log.size = 0;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05307595 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05307596
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007597 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
7598
7599 if (start_log.ring_id == RING_ID_WAKELOCK) {
7600 /* Start/stop wakelock events */
7601 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
7602 cds_set_wakelock_logging(true);
7603 else
7604 cds_set_wakelock_logging(false);
7605 return 0;
7606 }
7607
7608 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307609 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007610 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007611 status);
7612 return -EINVAL;
7613 }
7614 return 0;
7615}
7616
7617/**
7618 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
7619 * or disable the collection of packet statistics from the firmware
7620 * @wiphy: WIPHY structure pointer
7621 * @wdev: Wireless device structure pointer
7622 * @data: Pointer to the data received
7623 * @data_len: Length of the data received
7624 *
7625 * This function is used to enable or disable the collection of packet
7626 * statistics from the firmware
7627 *
7628 * Return: 0 on success and errno on failure
7629 */
7630static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
7631 struct wireless_dev *wdev,
7632 const void *data,
7633 int data_len)
7634{
7635 int ret = 0;
7636
7637 cds_ssr_protect(__func__);
7638 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
7639 wdev, data, data_len);
7640 cds_ssr_unprotect(__func__);
7641
7642 return ret;
7643}
7644
7645static const struct
7646nla_policy
7647qca_wlan_vendor_wifi_logger_get_ring_data_policy
7648[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
7649 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
7650 = {.type = NLA_U32 },
7651};
7652
7653/**
7654 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
7655 * @wiphy: WIPHY structure pointer
7656 * @wdev: Wireless device structure pointer
7657 * @data: Pointer to the data received
7658 * @data_len: Length of the data received
7659 *
7660 * This function is used to flush or retrieve the per packet statistics from
7661 * the driver
7662 *
7663 * Return: 0 on success and errno on failure
7664 */
7665static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
7666 struct wireless_dev *wdev,
7667 const void *data,
7668 int data_len)
7669{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307670 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007671 uint32_t ring_id;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07007672 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007673 struct nlattr *tb
7674 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
7675
Dustin Brownfdf17c12018-03-14 12:55:34 -07007676 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08007677
Anurag Chouhan6d760662016-02-20 16:05:43 +05307678 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007679 hdd_err("Command not allowed in FTM mode");
7680 return -EPERM;
7681 }
7682
7683 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05307684 if (status)
7685 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007686
Dustin Brown4ea21db2018-01-05 14:13:17 -08007687 if (wlan_cfg80211_nla_parse(tb,
7688 QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
7689 data, data_len,
7690 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007691 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007692 return -EINVAL;
7693 }
7694
7695 /* Parse and fetch ring id */
7696 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007697 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007698 return -EINVAL;
7699 }
7700
7701 ring_id = nla_get_u32(
7702 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
7703
7704 if (ring_id == RING_ID_PER_PACKET_STATS) {
7705 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007706 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05307707 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
7708 /*
7709 * As part of DRIVER ring ID, flush both driver and fw logs.
7710 * For other Ring ID's driver doesn't have any rings to flush
7711 */
Dustin Brown5e89ef82018-03-14 11:50:23 -07007712 hdd_info("Bug report triggered by framework");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05307713
7714 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
7715 WLAN_LOG_INDICATOR_FRAMEWORK,
7716 WLAN_LOG_REASON_CODE_UNUSED,
7717 true, false);
7718 if (QDF_STATUS_SUCCESS != status) {
7719 hdd_err("Failed to trigger bug report");
7720 return -EINVAL;
7721 }
7722 } else {
7723 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
7724 WLAN_LOG_INDICATOR_FRAMEWORK,
Agrawal Ashishaff28982017-05-30 15:25:47 +05307725 WLAN_LOG_REASON_CODE_UNUSED,
7726 ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007727 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007728 return 0;
7729}
7730
7731/**
7732 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
7733 * @wiphy: WIPHY structure pointer
7734 * @wdev: Wireless device structure pointer
7735 * @data: Pointer to the data received
7736 * @data_len: Length of the data received
7737 *
7738 * This function is used to flush or retrieve the per packet statistics from
7739 * the driver
7740 *
7741 * Return: 0 on success and errno on failure
7742 */
7743static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
7744 struct wireless_dev *wdev,
7745 const void *data,
7746 int data_len)
7747{
7748 int ret = 0;
7749
7750 cds_ssr_protect(__func__);
7751 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
7752 wdev, data, data_len);
7753 cds_ssr_unprotect(__func__);
7754
7755 return ret;
7756}
7757
7758#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
7759/**
7760 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
7761 * @hdd_ctx: HDD context
7762 * @request_id: [input] request id
7763 * @pattern_id: [output] pattern id
7764 *
7765 * This function loops through request id to pattern id array
7766 * if the slot is available, store the request id and return pattern id
7767 * if entry exists, return the pattern id
7768 *
7769 * Return: 0 on success and errno on failure
7770 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07007771static int hdd_map_req_id_to_pattern_id(struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007772 uint32_t request_id,
7773 uint8_t *pattern_id)
7774{
7775 uint32_t i;
7776
7777 mutex_lock(&hdd_ctx->op_ctx.op_lock);
7778 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
7779 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
7780 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
7781 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
7782 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
7783 return 0;
7784 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
7785 request_id) {
7786 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
7787 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
7788 return 0;
7789 }
7790 }
7791 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
7792 return -EINVAL;
7793}
7794
7795/**
7796 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
7797 * @hdd_ctx: HDD context
7798 * @request_id: [input] request id
7799 * @pattern_id: [output] pattern id
7800 *
7801 * This function loops through request id to pattern id array
7802 * reset request id to 0 (slot available again) and
7803 * return pattern id
7804 *
7805 * Return: 0 on success and errno on failure
7806 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07007807static int hdd_unmap_req_id_to_pattern_id(struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007808 uint32_t request_id,
7809 uint8_t *pattern_id)
7810{
7811 uint32_t i;
7812
7813 mutex_lock(&hdd_ctx->op_ctx.op_lock);
7814 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
7815 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
7816 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
7817 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
7818 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
7819 return 0;
7820 }
7821 }
7822 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
7823 return -EINVAL;
7824}
7825
7826
7827/*
7828 * define short names for the global vendor params
7829 * used by __wlan_hdd_cfg80211_offloaded_packets()
7830 */
7831#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
7832#define PARAM_REQUEST_ID \
7833 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
7834#define PARAM_CONTROL \
7835 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
7836#define PARAM_IP_PACKET \
7837 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
7838#define PARAM_SRC_MAC_ADDR \
7839 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
7840#define PARAM_DST_MAC_ADDR \
7841 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
7842#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
7843
7844/**
7845 * wlan_hdd_add_tx_ptrn() - add tx pattern
7846 * @adapter: adapter pointer
7847 * @hdd_ctx: hdd context
7848 * @tb: nl attributes
7849 *
7850 * This function reads the NL attributes and forms a AddTxPtrn message
7851 * posts it to SME.
7852 *
7853 */
7854static int
Jeff Johnsone5006672017-08-29 14:39:02 -07007855wlan_hdd_add_tx_ptrn(struct hdd_adapter *adapter, struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007856 struct nlattr **tb)
7857{
7858 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307859 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007860 uint32_t request_id, ret, len;
7861 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05307862 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007863 uint16_t eth_type = htons(ETH_P_IP);
7864
7865 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07007866 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007867 return -ENOTSUPP;
7868 }
7869
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307870 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007871 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07007872 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007873 return -ENOMEM;
7874 }
7875
7876 /* Parse and fetch request Id */
7877 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007878 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007879 goto fail;
7880 }
7881
7882 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
7883 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07007884 hdd_err("request_id cannot be MAX");
SaidiReddy Yenuga466b3ce2017-05-02 18:50:25 +05307885 goto fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007886 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007887 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007888
7889 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007890 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007891 goto fail;
7892 }
7893 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007894 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007895 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07007896 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007897 goto fail;
7898 }
7899
7900 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007901 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007902 goto fail;
7903 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08007904 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05307905 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007906 hdd_debug("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08007907 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007908
Anurag Chouhanc5548422016-02-24 18:33:27 +05307909 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Jeff Johnson1e851a12017-10-28 14:36:12 -07007910 &adapter->mac_addr)) {
Srinivas Girigowda31896552015-11-18 22:59:52 -08007911 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007912 goto fail;
7913 }
7914
7915 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007916 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007917 goto fail;
7918 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05307919 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007920 hdd_debug("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007921 MAC_ADDR_ARRAY(dst_addr.bytes));
7922
7923 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007924 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007925 goto fail;
7926 }
7927 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007928 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007929
7930 if (add_req->ucPtrnSize < 0 ||
7931 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
7932 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007933 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007934 add_req->ucPtrnSize);
7935 goto fail;
7936 }
7937
7938 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307939 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05307940 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307941 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05307942 QDF_MAC_ADDR_SIZE);
7943 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307944 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007945 len += 2;
7946
7947 /*
7948 * This is the IP packet, add 14 bytes Ethernet (802.3) header
7949 * ------------------------------------------------------------
7950 * | 14 bytes Ethernet (802.3) header | IP header and payload |
7951 * ------------------------------------------------------------
7952 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307953 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007954 nla_data(tb[PARAM_IP_PACKET]),
7955 add_req->ucPtrnSize);
7956 add_req->ucPtrnSize += len;
7957
7958 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
7959 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007960 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007961 goto fail;
7962 }
7963 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007964 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007965
7966 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307967 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007968 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007969 goto fail;
7970 }
7971
Dustin Browne74003f2018-03-14 12:51:58 -07007972 hdd_exit();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307973 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007974 return 0;
7975
7976fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05307977 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007978 return -EINVAL;
7979}
7980
7981/**
7982 * wlan_hdd_del_tx_ptrn() - delete tx pattern
7983 * @adapter: adapter pointer
7984 * @hdd_ctx: hdd context
7985 * @tb: nl attributes
7986 *
7987 * This function reads the NL attributes and forms a DelTxPtrn message
7988 * posts it to SME.
7989 *
7990 */
7991static int
Jeff Johnsone5006672017-08-29 14:39:02 -07007992wlan_hdd_del_tx_ptrn(struct hdd_adapter *adapter, struct hdd_context *hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007993 struct nlattr **tb)
7994{
7995 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05307996 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007997 uint32_t request_id, ret;
7998 uint8_t pattern_id = 0;
7999
8000 /* Parse and fetch request Id */
8001 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07008002 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008003 return -EINVAL;
8004 }
8005 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
8006 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07008007 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008008 return -EINVAL;
8009 }
8010
8011 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
8012 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008013 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008014 return -EINVAL;
8015 }
8016
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308017 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008018 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07008019 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008020 return -ENOMEM;
8021 }
8022
Jeff Johnson1e851a12017-10-28 14:36:12 -07008023 qdf_copy_macaddr(&del_req->mac_address, &adapter->mac_addr);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008024 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008025 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008026 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008027 request_id, del_req->ucPtrnId);
8028
8029 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308030 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008031 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008032 goto fail;
8033 }
8034
Dustin Browne74003f2018-03-14 12:51:58 -07008035 hdd_exit();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308036 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008037 return 0;
8038
8039fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308040 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008041 return -EINVAL;
8042}
8043
8044
8045/**
8046 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
8047 * @wiphy: Pointer to wireless phy
8048 * @wdev: Pointer to wireless device
8049 * @data: Pointer to data
8050 * @data_len: Data length
8051 *
8052 * Return: 0 on success, negative errno on failure
8053 */
8054static int
8055__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
8056 struct wireless_dev *wdev,
8057 const void *data,
8058 int data_len)
8059{
8060 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07008061 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008062 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008063 struct nlattr *tb[PARAM_MAX + 1];
8064 uint8_t control;
8065 int ret;
8066 static const struct nla_policy policy[PARAM_MAX + 1] = {
8067 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
8068 [PARAM_CONTROL] = { .type = NLA_U32 },
8069 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05308070 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008071 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05308072 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008073 [PARAM_PERIOD] = { .type = NLA_U32 },
8074 };
8075
Dustin Brownfdf17c12018-03-14 12:55:34 -07008076 hdd_enter_dev(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008077
Anurag Chouhan6d760662016-02-20 16:05:43 +05308078 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008079 hdd_err("Command not allowed in FTM mode");
8080 return -EPERM;
8081 }
8082
8083 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308084 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008085 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008086
8087 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008088 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008089 return -ENOTSUPP;
8090 }
8091
Dustin Brown4ea21db2018-01-05 14:13:17 -08008092 if (wlan_cfg80211_nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008093 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008094 return -EINVAL;
8095 }
8096
8097 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07008098 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008099 return -EINVAL;
8100 }
8101 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008102 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008103
8104 if (control == WLAN_START_OFFLOADED_PACKETS)
8105 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08008106 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008107 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08008108
8109 hdd_err("Invalid control: %d", control);
Jeff Johnson68755312017-02-10 11:46:55 -08008110 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008111}
8112
8113/*
8114 * done with short names for the global vendor params
8115 * used by __wlan_hdd_cfg80211_offloaded_packets()
8116 */
8117#undef PARAM_MAX
8118#undef PARAM_REQUEST_ID
8119#undef PARAM_CONTROL
8120#undef PARAM_IP_PACKET
8121#undef PARAM_SRC_MAC_ADDR
8122#undef PARAM_DST_MAC_ADDR
8123#undef PARAM_PERIOD
8124
8125/**
8126 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
8127 * @wiphy: wiphy structure pointer
8128 * @wdev: Wireless device structure pointer
8129 * @data: Pointer to the data received
8130 * @data_len: Length of @data
8131 *
8132 * Return: 0 on success; errno on failure
8133 */
8134static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
8135 struct wireless_dev *wdev,
8136 const void *data,
8137 int data_len)
8138{
8139 int ret = 0;
8140
8141 cds_ssr_protect(__func__);
8142 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
8143 wdev, data, data_len);
8144 cds_ssr_unprotect(__func__);
8145
8146 return ret;
8147}
8148#endif
8149
8150/*
8151 * define short names for the global vendor params
8152 * used by __wlan_hdd_cfg80211_monitor_rssi()
8153 */
8154#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
8155#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
8156#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
8157#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
8158#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
8159
8160/**
8161 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
8162 * @wiphy: Pointer to wireless phy
8163 * @wdev: Pointer to wireless device
8164 * @data: Pointer to data
8165 * @data_len: Data length
8166 *
8167 * Return: 0 on success, negative errno on failure
8168 */
8169static int
8170__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
8171 struct wireless_dev *wdev,
8172 const void *data,
8173 int data_len)
8174{
8175 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07008176 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008177 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008178 struct nlattr *tb[PARAM_MAX + 1];
8179 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308180 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008181 int ret;
8182 uint32_t control;
8183 static const struct nla_policy policy[PARAM_MAX + 1] = {
8184 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
8185 [PARAM_CONTROL] = { .type = NLA_U32 },
8186 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
8187 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
8188 };
8189
Dustin Brownfdf17c12018-03-14 12:55:34 -07008190 hdd_enter_dev(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008191
Jeff Johnson1b780e42017-10-31 14:11:45 -07008192 if (wlan_hdd_validate_session_id(adapter->session_id)) {
8193 hdd_err("invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05308194 return -EINVAL;
8195 }
8196
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008197 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05308198 if (ret)
8199 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008200
8201 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07008202 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008203 return -ENOTSUPP;
8204 }
8205
Dustin Brown4ea21db2018-01-05 14:13:17 -08008206 if (wlan_cfg80211_nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008207 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008208 return -EINVAL;
8209 }
8210
8211 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07008212 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008213 return -EINVAL;
8214 }
8215
8216 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07008217 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008218 return -EINVAL;
8219 }
8220
8221 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
Jeff Johnson1b780e42017-10-31 14:11:45 -07008222 req.session_id = adapter->session_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008223 control = nla_get_u32(tb[PARAM_CONTROL]);
8224
8225 if (control == QCA_WLAN_RSSI_MONITORING_START) {
8226 req.control = true;
8227 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07008228 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008229 return -EINVAL;
8230 }
8231
8232 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07008233 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008234 return -EINVAL;
8235 }
8236
8237 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
8238 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
8239
8240 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008241 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008242 req.min_rssi, req.max_rssi);
8243 return -EINVAL;
8244 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008245 hdd_debug("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008246 req.min_rssi, req.max_rssi);
8247
8248 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
8249 req.control = false;
8250 else {
Jeff Johnson77848112016-06-29 14:52:06 -07008251 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008252 return -EINVAL;
8253 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008254 hdd_debug("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008255 req.request_id, req.session_id, req.control);
8256
8257 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308258 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008259 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008260 return -EINVAL;
8261 }
8262
8263 return 0;
8264}
8265
8266/*
8267 * done with short names for the global vendor params
8268 * used by __wlan_hdd_cfg80211_monitor_rssi()
8269 */
8270#undef PARAM_MAX
8271#undef PARAM_CONTROL
8272#undef PARAM_REQUEST_ID
8273#undef PARAM_MAX_RSSI
8274#undef PARAM_MIN_RSSI
8275
8276/**
8277 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
8278 * @wiphy: wiphy structure pointer
8279 * @wdev: Wireless device structure pointer
8280 * @data: Pointer to the data received
8281 * @data_len: Length of @data
8282 *
8283 * Return: 0 on success; errno on failure
8284 */
8285static int
8286wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
8287 const void *data, int data_len)
8288{
8289 int ret;
8290
8291 cds_ssr_protect(__func__);
8292 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
8293 cds_ssr_unprotect(__func__);
8294
8295 return ret;
8296}
8297
8298/**
8299 * hdd_rssi_threshold_breached() - rssi breached NL event
8300 * @hddctx: HDD context
8301 * @data: rssi breached event data
8302 *
8303 * This function reads the rssi breached event %data and fill in the skb with
8304 * NL attributes and send up the NL event.
8305 *
8306 * Return: none
8307 */
8308void hdd_rssi_threshold_breached(void *hddctx,
8309 struct rssi_breach_event *data)
8310{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008311 struct hdd_context *hdd_ctx = hddctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008312 struct sk_buff *skb;
8313
Dustin Brown491d54b2018-03-14 12:39:11 -07008314 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008315
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05308316 if (wlan_hdd_validate_context(hdd_ctx))
8317 return;
8318 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07008319 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008320 return;
8321 }
8322
8323 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
8324 NULL,
8325 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
8326 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
8327 GFP_KERNEL);
8328
8329 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07008330 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008331 return;
8332 }
8333
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008334 hdd_debug("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008335 data->request_id, data->curr_rssi);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008336 hdd_debug("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008337 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
8338
8339 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
8340 data->request_id) ||
8341 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
8342 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
8343 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
8344 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008345 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008346 goto fail;
8347 }
8348
8349 cfg80211_vendor_event(skb, GFP_KERNEL);
8350 return;
8351
8352fail:
8353 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008354}
8355
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308356static const struct nla_policy
8357ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
8358 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
8359};
8360
8361/**
8362 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
8363 * @wiphy: Pointer to wireless phy
8364 * @wdev: Pointer to wireless device
8365 * @data: Pointer to data
8366 * @data_len: Length of @data
8367 *
8368 * Return: 0 on success, negative errno on failure
8369 */
8370static int
8371__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
8372 struct wireless_dev *wdev,
8373 const void *data, int data_len)
8374{
8375 int status;
8376 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
Jeff Johnsonb8944722017-09-03 09:03:19 -07008377 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07008378 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07008379 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308380
Dustin Brownfdf17c12018-03-14 12:55:34 -07008381 hdd_enter_dev(wdev->netdev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308382
Jeff Johnsonb8944722017-09-03 09:03:19 -07008383 status = wlan_hdd_validate_context(hdd_ctx);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308384 if (0 != status)
8385 return status;
Jeff Johnsonb8944722017-09-03 09:03:19 -07008386 if (!hdd_ctx->config->fhostNSOffload) {
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308387 hdd_err("ND Offload not supported");
8388 return -EINVAL;
8389 }
8390
Mukul Sharma495df602017-09-25 14:52:18 +05308391 if (!hdd_ctx->config->active_mode_offload) {
8392 hdd_warn("Active mode offload is disabled");
8393 return -EINVAL;
8394 }
8395
Dustin Brown4ea21db2018-01-05 14:13:17 -08008396 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
8397 (struct nlattr *)data, data_len,
8398 ns_offload_set_policy)) {
8399 hdd_err("nla_parse failed");
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308400 return -EINVAL;
8401 }
8402
8403 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
8404 hdd_err("ND Offload flag attribute not present");
8405 return -EINVAL;
8406 }
8407
Jeff Johnsonb8944722017-09-03 09:03:19 -07008408 hdd_ctx->ns_offload_enable =
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308409 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
8410
Nachiket Kukadedbffab82017-04-25 19:26:02 +05308411 if (QDF_IBSS_MODE == adapter->device_mode) {
8412 hdd_debug("NS Offload is not supported in IBSS mode");
8413 return -EINVAL;
8414 }
8415
Dustin Brownd8279d22016-09-07 14:52:57 -07008416 /* update ns offload in case it is already enabled/disabled */
Jeff Johnsonb8944722017-09-03 09:03:19 -07008417 if (hdd_ctx->ns_offload_enable)
Mukul Sharma3ba26b82017-01-12 21:59:41 +05308418 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
8419 else
8420 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07008421
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308422 return 0;
8423}
8424
8425/**
8426 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
8427 * @wiphy: pointer to wireless wiphy structure.
8428 * @wdev: pointer to wireless_dev structure.
8429 * @data: Pointer to the data to be passed via vendor interface
8430 * @data_len:Length of the data to be passed
8431 *
8432 * Return: Return the Success or Failure code.
8433 */
8434static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
8435 struct wireless_dev *wdev,
8436 const void *data, int data_len)
8437{
8438 int ret;
8439
8440 cds_ssr_protect(__func__);
8441 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
8442 cds_ssr_unprotect(__func__);
8443
8444 return ret;
8445}
8446
Jeff Johnsondd7bd3e2017-06-05 13:25:24 -07008447static const struct nla_policy get_preferred_freq_list_policy
8448 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1] = {
8449 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE] = {
8450 .type = NLA_U32},
8451};
8452
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008453/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
8454 * @wiphy: Pointer to wireless phy
8455 * @wdev: Pointer to wireless device
8456 * @data: Pointer to data
8457 * @data_len: Data length
8458 *
8459 * This function return the preferred frequency list generated by the policy
8460 * manager.
8461 *
8462 * Return: success or failure code
8463 */
8464static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
8465 struct wireless_dev
8466 *wdev, const void *data,
8467 int data_len)
8468{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008469 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008470 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308471 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308472 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008473 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308474 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008475 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008476 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
8477 struct sk_buff *reply_skb;
8478
Dustin Brownfdf17c12018-03-14 12:55:34 -07008479 hdd_enter_dev(wdev->netdev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08008480
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008481 ret = wlan_hdd_validate_context(hdd_ctx);
8482 if (ret)
8483 return -EINVAL;
8484
Dustin Brown4ea21db2018-01-05 14:13:17 -08008485 if (wlan_cfg80211_nla_parse(tb,
8486 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
8487 data, data_len,
8488 get_preferred_freq_list_policy)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008489 hdd_err("Invalid ATTR");
8490 return -EINVAL;
8491 }
8492
8493 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
8494 hdd_err("attr interface type failed");
8495 return -EINVAL;
8496 }
8497
8498 intf_mode = nla_get_u32(tb
8499 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
8500
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008501 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008502 hdd_err("Invalid interface type");
8503 return -EINVAL;
8504 }
8505
8506 hdd_debug("Userspace requested pref freq list");
8507
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008508 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc,
8509 intf_mode, pcl, &pcl_len,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05308510 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308511 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008512 hdd_err("Get pcl failed");
8513 return -EINVAL;
8514 }
8515
8516 /* convert channel number to frequency */
8517 for (i = 0; i < pcl_len; i++) {
8518 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
8519 freq_list[i] =
8520 ieee80211_channel_to_frequency(pcl[i],
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -07008521 HDD_NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008522 else
8523 freq_list[i] =
8524 ieee80211_channel_to_frequency(pcl[i],
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -07008525 HDD_NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008526 }
8527
8528 /* send the freq_list back to supplicant */
8529 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
8530 sizeof(u32) *
8531 pcl_len +
8532 NLMSG_HDRLEN);
8533
8534 if (!reply_skb) {
8535 hdd_err("Allocate reply_skb failed");
8536 return -EINVAL;
8537 }
8538
8539 if (nla_put_u32(reply_skb,
8540 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
8541 intf_mode) ||
8542 nla_put(reply_skb,
8543 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
8544 sizeof(uint32_t) * pcl_len,
8545 freq_list)) {
8546 hdd_err("nla put fail");
8547 kfree_skb(reply_skb);
8548 return -EINVAL;
8549 }
8550
8551 return cfg80211_vendor_cmd_reply(reply_skb);
8552}
8553
8554/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
8555 * @wiphy: Pointer to wireless phy
8556 * @wdev: Pointer to wireless device
8557 * @data: Pointer to data
8558 * @data_len: Data length
8559 *
8560 * This function return the preferred frequency list generated by the policy
8561 * manager.
8562 *
8563 * Return: success or failure code
8564 */
8565static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
8566 struct wireless_dev
8567 *wdev, const void *data,
8568 int data_len)
8569{
8570 int ret = 0;
8571
8572 cds_ssr_protect(__func__);
8573 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
8574 data, data_len);
8575 cds_ssr_unprotect(__func__);
8576
8577 return ret;
8578}
8579
Jeff Johnsone5f33ba2017-06-05 14:48:48 -07008580static const struct nla_policy set_probable_oper_channel_policy
8581 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX + 1] = {
8582 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE] = {
8583 .type = NLA_U32},
8584 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ] = {
8585 .type = NLA_U32},
8586};
8587
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008588/**
8589 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
8590 * @wiphy: Pointer to wireless phy
8591 * @wdev: Pointer to wireless device
8592 * @data: Pointer to data
8593 * @data_len: Data length
8594 *
8595 * Return: 0 on success, negative errno on failure
8596 */
8597static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
8598 struct wireless_dev *wdev,
8599 const void *data,
8600 int data_len)
8601{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05308602 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07008603 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008604 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008605 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008606 enum policy_mgr_con_mode intf_mode;
Jeff Johnsone5f33ba2017-06-05 14:48:48 -07008607 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX + 1];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008608 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008609
Dustin Brownfdf17c12018-03-14 12:55:34 -07008610 hdd_enter_dev(ndev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08008611
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008612 ret = wlan_hdd_validate_context(hdd_ctx);
8613 if (ret)
8614 return ret;
8615
Dustin Brown4ea21db2018-01-05 14:13:17 -08008616 if (wlan_cfg80211_nla_parse(tb,
8617 QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
8618 data, data_len,
8619 set_probable_oper_channel_policy)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008620 hdd_err("Invalid ATTR");
8621 return -EINVAL;
8622 }
8623
8624 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
8625 hdd_err("attr interface type failed");
8626 return -EINVAL;
8627 }
8628
8629 intf_mode = nla_get_u32(tb
8630 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
8631
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008632 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008633 hdd_err("Invalid interface type");
8634 return -EINVAL;
8635 }
8636
8637 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
8638 hdd_err("attr probable freq failed");
8639 return -EINVAL;
8640 }
8641
8642 channel_hint = cds_freq_to_chan(nla_get_u32(tb
8643 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
8644
8645 /* check pcl table */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008646 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc, intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008647 channel_hint, HW_MODE_20_MHZ)) {
8648 hdd_err("Set channel hint failed due to concurrency check");
8649 return -EINVAL;
8650 }
8651
Krunal Soni09e55032016-06-07 10:06:55 -07008652 if (0 != wlan_hdd_check_remain_on_channel(adapter))
8653 hdd_warn("Remain On Channel Pending");
8654
Krunal Sonied3bc8e2018-01-26 12:13:34 -08008655 if (wlan_hdd_change_hw_mode_for_given_chnl(adapter, channel_hint,
8656 POLICY_MGR_UPDATE_REASON_SET_OPER_CHAN)) {
8657 hdd_err("Failed to change hw mode");
Krunal Soni3091bcc2016-06-23 12:28:21 -07008658 return -EINVAL;
8659 }
8660
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008661 return 0;
8662}
8663
8664/**
8665 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
8666 * @wiphy: Pointer to wireless phy
8667 * @wdev: Pointer to wireless device
8668 * @data: Pointer to data
8669 * @data_len: Data length
8670 *
8671 * Return: 0 on success, negative errno on failure
8672 */
8673static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
8674 struct wireless_dev *wdev,
8675 const void *data,
8676 int data_len)
8677{
8678 int ret = 0;
8679
8680 cds_ssr_protect(__func__);
8681 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
8682 data, data_len);
8683 cds_ssr_unprotect(__func__);
8684
8685 return ret;
8686}
8687
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308688static const struct
8689nla_policy
8690qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
Ashish Kumar Dhanotiya81e2acc2017-06-21 12:30:32 +05308691 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {
8692 .type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308693};
8694
8695/**
8696 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
8697 * @wiphy: WIPHY structure pointer
8698 * @wdev: Wireless device structure pointer
8699 * @data: Pointer to the data received
8700 * @data_len: Length of the data received
8701 *
8702 * This function is used to get link properties like nss, rate flags and
8703 * operating frequency for the active connection with the given peer.
8704 *
8705 * Return: 0 on success and errno on failure
8706 */
8707static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
8708 struct wireless_dev *wdev,
8709 const void *data,
8710 int data_len)
8711{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008712 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308713 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07008714 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson40dae4e2017-08-29 14:00:25 -07008715 struct hdd_station_ctx *hdd_sta_ctx;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308716 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05308717 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308718 uint32_t sta_id;
8719 struct sk_buff *reply_skb;
8720 uint32_t rate_flags = 0;
8721 uint8_t nss;
8722 uint8_t final_rate_flags = 0;
8723 uint32_t freq;
8724
Dustin Brownfdf17c12018-03-14 12:55:34 -07008725 hdd_enter_dev(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308726
Anurag Chouhan6d760662016-02-20 16:05:43 +05308727 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308728 hdd_err("Command not allowed in FTM mode");
8729 return -EPERM;
8730 }
8731
8732 if (0 != wlan_hdd_validate_context(hdd_ctx))
8733 return -EINVAL;
8734
Dustin Brown4ea21db2018-01-05 14:13:17 -08008735 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data,
8736 data_len, qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008737 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308738 return -EINVAL;
8739 }
8740
8741 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07008742 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308743 adapter->device_mode);
8744 return -EINVAL;
8745 }
8746
Ashish Kumar Dhanotiya81e2acc2017-06-21 12:30:32 +05308747 if (nla_len(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) < QDF_MAC_ADDR_SIZE) {
8748 hdd_err("Attribute peerMac is invalid for mode=%d",
8749 adapter->device_mode);
8750 return -EINVAL;
8751 }
8752
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308753 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05308754 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008755 hdd_debug("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308756 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
8757
Krunal Sonib4326f22016-03-10 13:05:51 -08008758 if (adapter->device_mode == QDF_STA_MODE ||
8759 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308760 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
8761 if ((hdd_sta_ctx->conn_info.connState !=
8762 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308763 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05308764 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008765 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308766 MAC_ADDR_ARRAY(peer_mac));
8767 return -EINVAL;
8768 }
8769
8770 nss = hdd_sta_ctx->conn_info.nss;
8771 freq = cds_chan_to_freq(
8772 hdd_sta_ctx->conn_info.operationChannel);
8773 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08008774 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
8775 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308776
8777 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07008778 if (adapter->sta_info[sta_id].in_use &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05308779 !qdf_is_macaddr_broadcast(
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07008780 &adapter->sta_info[sta_id].sta_mac) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308781 !qdf_mem_cmp(
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07008782 &adapter->sta_info[sta_id].sta_mac.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05308783 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308784 break;
8785 }
8786
8787 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07008788 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308789 MAC_ADDR_ARRAY(peer_mac));
8790 return -EINVAL;
8791 }
8792
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07008793 nss = adapter->sta_info[sta_id].nss;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308794 freq = cds_chan_to_freq(
Jeff Johnson01206862017-10-27 20:55:59 -07008795 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operating_channel);
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -07008796 rate_flags = adapter->sta_info[sta_id].rate_flags;
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308797 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07008798 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308799 MAC_ADDR_ARRAY(peer_mac));
8800 return -EINVAL;
8801 }
8802
8803 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
8804 if (rate_flags & eHAL_TX_RATE_VHT80) {
8805 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08008806#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308807 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08008808#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308809 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
8810 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08008811#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308812 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08008813#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308814 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
8815 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
8816 } else if (rate_flags &
8817 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
8818 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08008819#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308820 if (rate_flags & eHAL_TX_RATE_HT40)
8821 final_rate_flags |=
8822 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08008823#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308824 }
8825
8826 if (rate_flags & eHAL_TX_RATE_SGI) {
8827 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
8828 final_rate_flags |= RATE_INFO_FLAGS_MCS;
8829 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
8830 }
8831 }
8832
8833 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
8834 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
8835
8836 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07008837 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308838 return -EINVAL;
8839 }
8840
8841 if (nla_put_u8(reply_skb,
8842 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
8843 nss) ||
8844 nla_put_u8(reply_skb,
8845 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
8846 final_rate_flags) ||
8847 nla_put_u32(reply_skb,
8848 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
8849 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008850 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308851 kfree_skb(reply_skb);
8852 return -EINVAL;
8853 }
8854
8855 return cfg80211_vendor_cmd_reply(reply_skb);
8856}
8857
8858/**
8859 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
8860 * properties.
8861 * @wiphy: WIPHY structure pointer
8862 * @wdev: Wireless device structure pointer
8863 * @data: Pointer to the data received
8864 * @data_len: Length of the data received
8865 *
8866 * This function is used to get link properties like nss, rate flags and
8867 * operating frequency for the active connection with the given peer.
8868 *
8869 * Return: 0 on success and errno on failure
8870 */
8871static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
8872 struct wireless_dev *wdev,
8873 const void *data,
8874 int data_len)
8875{
8876 int ret = 0;
8877
8878 cds_ssr_protect(__func__);
8879 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
8880 wdev, data, data_len);
8881 cds_ssr_unprotect(__func__);
8882
8883 return ret;
8884}
8885
Peng Xu278d0122015-09-24 16:34:17 -07008886static const struct
8887nla_policy
8888qca_wlan_vendor_ota_test_policy
8889[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
8890 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
8891};
8892
8893/**
8894 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
8895 * @wiphy: Pointer to wireless phy
8896 * @wdev: Pointer to wireless device
8897 * @data: Pointer to data
8898 * @data_len: Data length
8899 *
8900 * Return: 0 on success, negative errno on failure
8901 */
8902static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
8903 struct wireless_dev *wdev,
8904 const void *data,
8905 int data_len)
8906{
8907 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07008908 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Peng Xu278d0122015-09-24 16:34:17 -07008909 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07008910 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Peng Xu278d0122015-09-24 16:34:17 -07008911 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
8912 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308913 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07008914 uint32_t current_roam_state;
8915
Dustin Brownfdf17c12018-03-14 12:55:34 -07008916 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08008917
Anurag Chouhan6d760662016-02-20 16:05:43 +05308918 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07008919 hdd_err("Command not allowed in FTM mode");
8920 return -EPERM;
8921 }
8922
8923 if (0 != wlan_hdd_validate_context(hdd_ctx))
8924 return -EINVAL;
8925
Dustin Brown4ea21db2018-01-05 14:13:17 -08008926 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
8927 data, data_len,
8928 qca_wlan_vendor_ota_test_policy)) {
Peng Xu278d0122015-09-24 16:34:17 -07008929 hdd_err("invalid attr");
8930 return -EINVAL;
8931 }
8932
8933 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
8934 hdd_err("attr ota test failed");
8935 return -EINVAL;
8936 }
8937
8938 ota_enable = nla_get_u8(
8939 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
8940
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008941 hdd_debug(" OTA test enable = %d", ota_enable);
Peng Xu278d0122015-09-24 16:34:17 -07008942 if (ota_enable != 1) {
8943 hdd_err("Invalid value, only enable test mode is supported!");
8944 return -EINVAL;
8945 }
8946
8947 current_roam_state =
Jeff Johnson1b780e42017-10-31 14:11:45 -07008948 sme_get_current_roam_state(hal, adapter->session_id);
8949 status = sme_stop_roaming(hal, adapter->session_id,
Peng Xu278d0122015-09-24 16:34:17 -07008950 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308951 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07008952 hdd_err("Enable/Disable roaming failed");
8953 return -EINVAL;
8954 }
8955
Jeff Johnson1b780e42017-10-31 14:11:45 -07008956 status = sme_ps_enable_disable(hal, adapter->session_id,
Peng Xu278d0122015-09-24 16:34:17 -07008957 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308958 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07008959 hdd_err("Enable/Disable power save failed");
8960 /* restore previous roaming setting */
8961 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
8962 current_roam_state == eCSR_ROAMING_STATE_JOINED)
Jeff Johnson1b780e42017-10-31 14:11:45 -07008963 status = sme_start_roaming(hal, adapter->session_id,
Peng Xu278d0122015-09-24 16:34:17 -07008964 eCsrHddIssued);
8965 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
8966 current_roam_state == eCSR_ROAMING_STATE_IDLE)
Jeff Johnson1b780e42017-10-31 14:11:45 -07008967 status = sme_stop_roaming(hal, adapter->session_id,
Peng Xu278d0122015-09-24 16:34:17 -07008968 eCsrHddIssued);
8969
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308970 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07008971 hdd_err("Restoring roaming state failed");
8972
8973 return -EINVAL;
8974 }
8975
8976
8977 return 0;
8978}
8979
8980/**
8981 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
8982 * @wiphy: Pointer to wireless phy
8983 * @wdev: Pointer to wireless device
8984 * @data: Pointer to data
8985 * @data_len: Data length
8986 *
8987 * Return: 0 on success, negative errno on failure
8988 */
8989static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
8990 struct wireless_dev *wdev,
8991 const void *data,
8992 int data_len)
8993{
8994 int ret = 0;
8995
8996 cds_ssr_protect(__func__);
8997 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
8998 cds_ssr_unprotect(__func__);
8999
9000 return ret;
9001}
9002
Dustin Brown8f3b0562017-06-06 11:38:45 -07009003static const struct nla_policy
9004txpower_scale_policy[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1] = {
9005 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE] = { .type = NLA_U8 },
9006};
9007
Peng Xu4d67c8f2015-10-16 16:02:26 -07009008/**
9009 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
9010 * @wiphy: Pointer to wireless phy
9011 * @wdev: Pointer to wireless device
9012 * @data: Pointer to data
9013 * @data_len: Data length
9014 *
9015 * Return: 0 on success, negative errno on failure
9016 */
9017static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
9018 struct wireless_dev *wdev,
9019 const void *data,
9020 int data_len)
9021{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009022 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Peng Xu4d67c8f2015-10-16 16:02:26 -07009023 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07009024 struct hdd_adapter *adapter;
Peng Xu62c8c432016-05-09 15:23:02 -07009025 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07009026 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
9027 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07009028 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07009029
Dustin Brownfdf17c12018-03-14 12:55:34 -07009030 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08009031
Peng Xu4d67c8f2015-10-16 16:02:26 -07009032 ret = wlan_hdd_validate_context(hdd_ctx);
9033 if (ret)
9034 return ret;
9035
9036 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9037
Dustin Brown4ea21db2018-01-05 14:13:17 -08009038 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
9039 data, data_len, txpower_scale_policy)) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07009040 hdd_err("Invalid ATTR");
9041 return -EINVAL;
9042 }
9043
9044 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
9045 hdd_err("attr tx power scale failed");
9046 return -EINVAL;
9047 }
9048
9049 scale_value = nla_get_u8(tb
9050 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
9051
9052 if (scale_value > MAX_TXPOWER_SCALE) {
9053 hdd_err("Invalid tx power scale level");
9054 return -EINVAL;
9055 }
9056
Jeff Johnson1b780e42017-10-31 14:11:45 -07009057 status = wma_set_tx_power_scale(adapter->session_id, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07009058
Peng Xu62c8c432016-05-09 15:23:02 -07009059 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07009060 hdd_err("Set tx power scale failed");
9061 return -EINVAL;
9062 }
9063
9064 return 0;
9065}
9066
9067/**
9068 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
9069 * @wiphy: Pointer to wireless phy
9070 * @wdev: Pointer to wireless device
9071 * @data: Pointer to data
9072 * @data_len: Data length
9073 *
9074 * Return: 0 on success, negative errno on failure
9075 */
9076static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
9077 struct wireless_dev *wdev,
9078 const void *data,
9079 int data_len)
9080{
Peng Xu62c8c432016-05-09 15:23:02 -07009081 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07009082
9083 cds_ssr_protect(__func__);
9084 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
9085 data, data_len);
9086 cds_ssr_unprotect(__func__);
9087
9088 return ret;
9089}
9090
Dustin Brown498b11a2017-06-06 12:29:43 -07009091static const struct nla_policy txpower_scale_decr_db_policy
9092[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1] = {
9093 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB] = { .type = NLA_U8 },
9094};
9095
Peng Xu4d67c8f2015-10-16 16:02:26 -07009096/**
9097 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
9098 * @wiphy: Pointer to wireless phy
9099 * @wdev: Pointer to wireless device
9100 * @data: Pointer to data
9101 * @data_len: Data length
9102 *
9103 * Return: 0 on success, negative errno on failure
9104 */
9105static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
9106 struct wireless_dev *wdev,
9107 const void *data,
9108 int data_len)
9109{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009110 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Peng Xu4d67c8f2015-10-16 16:02:26 -07009111 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07009112 struct hdd_adapter *adapter;
Peng Xu62c8c432016-05-09 15:23:02 -07009113 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07009114 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
9115 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07009116 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07009117
Dustin Brownfdf17c12018-03-14 12:55:34 -07009118 hdd_enter_dev(dev);
Jeff Johnson1f61b612016-02-12 16:28:33 -08009119
Peng Xu4d67c8f2015-10-16 16:02:26 -07009120 ret = wlan_hdd_validate_context(hdd_ctx);
9121 if (ret)
9122 return ret;
9123
9124 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9125
Dustin Brown4ea21db2018-01-05 14:13:17 -08009126 if (wlan_cfg80211_nla_parse(tb,
9127 QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
9128 data, data_len,
9129 txpower_scale_decr_db_policy)) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07009130 hdd_err("Invalid ATTR");
9131 return -EINVAL;
9132 }
9133
9134 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
9135 hdd_err("attr tx power decrease db value failed");
9136 return -EINVAL;
9137 }
9138
9139 scale_value = nla_get_u8(tb
9140 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
9141
Jeff Johnson1b780e42017-10-31 14:11:45 -07009142 status = wma_set_tx_power_scale_decr_db(adapter->session_id,
Peng Xu62c8c432016-05-09 15:23:02 -07009143 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07009144
Peng Xu62c8c432016-05-09 15:23:02 -07009145 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07009146 hdd_err("Set tx power decrease db failed");
9147 return -EINVAL;
9148 }
9149
9150 return 0;
9151}
9152
9153/**
9154 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
9155 * @wiphy: Pointer to wireless phy
9156 * @wdev: Pointer to wireless device
9157 * @data: Pointer to data
9158 * @data_len: Data length
9159 *
9160 * Return: 0 on success, negative errno on failure
9161 */
9162static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
9163 struct wireless_dev *wdev,
9164 const void *data,
9165 int data_len)
9166{
Peng Xu62c8c432016-05-09 15:23:02 -07009167 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07009168
9169 cds_ssr_protect(__func__);
9170 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
9171 data, data_len);
9172 cds_ssr_unprotect(__func__);
9173
9174 return ret;
9175}
Peng Xu8fdaa492016-06-22 10:20:47 -07009176
9177/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309178 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
9179 * @wiphy: Pointer to wireless phy
9180 * @wdev: Pointer to wireless device
9181 * @data: Pointer to data
9182 * @data_len: Data length
9183 *
9184 * Processes the conditional channel switch request and invokes the helper
9185 * APIs to process the channel switch request.
9186 *
9187 * Return: 0 on success, negative errno on failure
9188 */
9189static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
9190 struct wireless_dev *wdev,
9191 const void *data,
9192 int data_len)
9193{
9194 int ret;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009195 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309196 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07009197 struct hdd_adapter *adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309198 struct nlattr
9199 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
9200 uint32_t freq_len, i;
9201 uint32_t *freq;
SaidiReddy Yenugac0c34cf2017-02-13 17:44:40 +05309202 uint8_t chans[QDF_MAX_NUM_CHAN] = {0};
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309203
Dustin Brownfdf17c12018-03-14 12:55:34 -07009204 hdd_enter_dev(dev);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309205
9206 ret = wlan_hdd_validate_context(hdd_ctx);
9207 if (ret)
9208 return ret;
9209
9210 if (!hdd_ctx->config->enableDFSMasterCap) {
9211 hdd_err("DFS master capability is not present in the driver");
9212 return -EINVAL;
9213 }
9214
9215 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9216 hdd_err("Command not allowed in FTM mode");
9217 return -EPERM;
9218 }
9219
9220 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9221 if (adapter->device_mode != QDF_SAP_MODE) {
9222 hdd_err("Invalid device mode %d", adapter->device_mode);
9223 return -EINVAL;
9224 }
9225
Rajeev Kumar1c40f072017-06-05 15:24:05 -07009226 /*
9227 * audit note: it is ok to pass a NULL policy here since only
9228 * one attribute is parsed which is array of frequencies and
9229 * it is explicitly validated for both under read and over read
9230 */
Dustin Brown4ea21db2018-01-05 14:13:17 -08009231 if (wlan_cfg80211_nla_parse(tb,
9232 QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
9233 data, data_len, NULL)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309234 hdd_err("Invalid ATTR");
9235 return -EINVAL;
9236 }
9237
9238 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
9239 hdd_err("Frequency list is missing");
9240 return -EINVAL;
9241 }
9242
9243 freq_len = nla_len(
9244 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
9245 sizeof(uint32_t);
9246
9247 if (freq_len > QDF_MAX_NUM_CHAN) {
9248 hdd_err("insufficient space to hold channels");
9249 return -ENOMEM;
9250 }
9251
9252 hdd_debug("freq_len=%d", freq_len);
9253
9254 freq = nla_data(
9255 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
9256
9257
9258 for (i = 0; i < freq_len; i++) {
9259 if (freq[i] == 0)
9260 chans[i] = 0;
9261 else
9262 chans[i] = ieee80211_frequency_to_channel(freq[i]);
9263
9264 hdd_debug("freq[%d]=%d", i, freq[i]);
9265 }
9266
9267 /*
9268 * The input frequency list from user space is designed to be a
9269 * priority based frequency list. This is only to accommodate any
9270 * future request. But, current requirement is only to perform CAC
9271 * on a single channel. So, the first entry from the list is picked.
9272 *
9273 * If channel is zero, any channel in the available outdoor regulatory
9274 * domain will be selected.
9275 */
9276 ret = wlan_hdd_request_pre_cac(chans[0]);
9277 if (ret) {
9278 hdd_err("pre cac request failed with reason:%d", ret);
9279 return ret;
9280 }
9281
9282 return 0;
9283}
9284
Rajeev Kumar67f5b872017-06-06 13:26:57 -07009285/* P2P listen offload device types parameters length in bytes */
9286#define P2P_LO_MAX_REQ_DEV_TYPE_COUNT (10)
9287#define P2P_LO_WPS_DEV_TYPE_LEN (8)
9288#define P2P_LO_DEV_TYPE_MAX_LEN \
9289 (P2P_LO_MAX_REQ_DEV_TYPE_COUNT * P2P_LO_WPS_DEV_TYPE_LEN)
9290
9291static const struct nla_policy
9292p2p_listen_offload_policy[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1] = {
9293 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] = { .type = NLA_U32 },
9294 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] = { .type = NLA_U32 },
9295 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] = {
9296 .type = NLA_U32 },
9297 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] = { .type = NLA_U32 },
9298 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] = {
9299 .type = NLA_BINARY,
9300 .len = P2P_LO_DEV_TYPE_MAX_LEN },
9301 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE] = {
9302 .type = NLA_BINARY,
9303 .len = MAX_GENIE_LEN },
9304 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG] = {
9305 .type = NLA_U32 },
9306 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] = { .type = NLA_U32 },
9307 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON] = {
9308 .type = NLA_U8 },
9309};
9310
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309311/**
Peng Xu8fdaa492016-06-22 10:20:47 -07009312 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
9313 * @wiphy: Pointer to wireless phy
9314 * @wdev: Pointer to wireless device
9315 * @data: Pointer to data
9316 * @data_len: Data length
9317 *
9318 * This function is to process the p2p listen offload start vendor
9319 * command. It parses the input parameters and invoke WMA API to
9320 * send the command to firmware.
9321 *
9322 * Return: 0 on success, negative errno on failure
9323 */
9324static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
9325 struct wireless_dev *wdev,
9326 const void *data,
9327 int data_len)
9328{
9329 int ret;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009330 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Peng Xu8fdaa492016-06-22 10:20:47 -07009331 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -07009332 struct hdd_adapter *adapter;
Peng Xu8fdaa492016-06-22 10:20:47 -07009333 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
9334 struct sir_p2p_lo_start params;
Peng Xu8fdaa492016-06-22 10:20:47 -07009335
Dustin Brownfdf17c12018-03-14 12:55:34 -07009336 hdd_enter_dev(dev);
Peng Xu8fdaa492016-06-22 10:20:47 -07009337
9338 ret = wlan_hdd_validate_context(hdd_ctx);
9339 if (ret)
9340 return ret;
9341
9342 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9343 hdd_err("Command not allowed in FTM mode");
9344 return -EPERM;
9345 }
9346
9347 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9348 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
9349 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
9350 (adapter->device_mode != QDF_P2P_GO_MODE)) {
9351 hdd_err("Invalid device mode %d", adapter->device_mode);
9352 return -EINVAL;
9353 }
9354
Dustin Brown4ea21db2018-01-05 14:13:17 -08009355 if (wlan_cfg80211_nla_parse(tb,
9356 QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
9357 data, data_len,
9358 p2p_listen_offload_policy)) {
Peng Xu8fdaa492016-06-22 10:20:47 -07009359 hdd_err("Invalid ATTR");
9360 return -EINVAL;
9361 }
9362
9363 memset(&params, 0, sizeof(params));
9364
9365 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
9366 params.ctl_flags = 1; /* set to default value */
9367 else
9368 params.ctl_flags = nla_get_u32(tb
9369 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
9370
9371 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
9372 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
9373 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
9374 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
9375 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
9376 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
9377 hdd_err("Attribute parsing failed");
9378 return -EINVAL;
9379 }
9380
Jeff Johnson1b780e42017-10-31 14:11:45 -07009381 params.vdev_id = adapter->session_id;
Peng Xu8fdaa492016-06-22 10:20:47 -07009382 params.freq = nla_get_u32(tb
9383 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
9384 if ((params.freq != 2412) && (params.freq != 2437) &&
9385 (params.freq != 2462)) {
9386 hdd_err("Invalid listening channel: %d", params.freq);
9387 return -EINVAL;
9388 }
9389
9390 params.period = nla_get_u32(tb
9391 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
9392 if (!((params.period > 0) && (params.period < UINT_MAX))) {
9393 hdd_err("Invalid period: %d", params.period);
9394 return -EINVAL;
9395 }
9396
9397 params.interval = nla_get_u32(tb
9398 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
9399 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
9400 hdd_err("Invalid interval: %d", params.interval);
9401 return -EINVAL;
9402 }
9403
9404 params.count = nla_get_u32(tb
9405 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08009406 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07009407 hdd_err("Invalid count: %d", params.count);
9408 return -EINVAL;
9409 }
9410
9411 params.device_types = nla_data(tb
9412 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
9413 if (params.device_types == NULL) {
9414 hdd_err("Invalid device types");
9415 return -EINVAL;
9416 }
9417
9418 params.dev_types_len = nla_len(tb
9419 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
Rajeev Kumar67f5b872017-06-06 13:26:57 -07009420 /* device type length has to be multiple of P2P_LO_WPS_DEV_TYPE_LEN */
9421 if (0 != (params.dev_types_len % P2P_LO_WPS_DEV_TYPE_LEN)) {
Peng Xu8fdaa492016-06-22 10:20:47 -07009422 hdd_err("Invalid device type length: %d", params.dev_types_len);
9423 return -EINVAL;
9424 }
9425
9426 params.probe_resp_tmplt = nla_data(tb
9427 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
9428 if (params.probe_resp_tmplt == NULL) {
9429 hdd_err("Invalid probe response template");
9430 return -EINVAL;
9431 }
9432
Rajeev Kumar67f5b872017-06-06 13:26:57 -07009433 /*
9434 * IEs minimum length should be 2 bytes: 1 byte for element id
9435 * and 1 byte for element id length.
9436 */
Peng Xu8fdaa492016-06-22 10:20:47 -07009437 params.probe_resp_len = nla_len(tb
9438 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
Rajeev Kumar67f5b872017-06-06 13:26:57 -07009439 if (params.probe_resp_len < MIN_GENIE_LEN) {
Peng Xu8fdaa492016-06-22 10:20:47 -07009440 hdd_err("Invalid probe resp template length: %d",
9441 params.probe_resp_len);
9442 return -EINVAL;
9443 }
9444
9445 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
9446 params.freq, params.period, params.interval, params.count);
9447
Wu Gao9a704f42017-03-10 18:42:11 +08009448 return wlan_hdd_listen_offload_start(adapter, &params);
Peng Xu8fdaa492016-06-22 10:20:47 -07009449}
9450
9451
9452/**
9453 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
9454 * @wiphy: Pointer to wireless phy
9455 * @wdev: Pointer to wireless device
9456 * @data: Pointer to data
9457 * @data_len: Data length
9458 *
9459 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
9460 * to process p2p listen offload start vendor command.
9461 *
9462 * Return: 0 on success, negative errno on failure
9463 */
9464static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
9465 struct wireless_dev *wdev,
9466 const void *data,
9467 int data_len)
9468{
9469 int ret = 0;
9470
9471 cds_ssr_protect(__func__);
9472 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
9473 data, data_len);
9474 cds_ssr_unprotect(__func__);
9475
9476 return ret;
9477}
9478
9479/**
9480 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
9481 * @wiphy: Pointer to wireless phy
9482 * @wdev: Pointer to wireless device
9483 * @data: Pointer to data
9484 * @data_len: Data length
9485 *
9486 * This function is to process the p2p listen offload stop vendor
9487 * command. It invokes WMA API to send command to firmware.
9488 *
9489 * Return: 0 on success, negative errno on failure
9490 */
9491static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
9492 struct wireless_dev *wdev,
9493 const void *data,
9494 int data_len)
9495{
Jeff Johnsone5006672017-08-29 14:39:02 -07009496 struct hdd_adapter *adapter;
Peng Xu8fdaa492016-06-22 10:20:47 -07009497 struct net_device *dev = wdev->netdev;
9498
9499 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9500 hdd_err("Command not allowed in FTM mode");
9501 return -EPERM;
9502 }
9503
9504 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9505 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
9506 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
9507 (adapter->device_mode != QDF_P2P_GO_MODE)) {
9508 hdd_err("Invalid device mode");
9509 return -EINVAL;
9510 }
9511
Wu Gao9a704f42017-03-10 18:42:11 +08009512 return wlan_hdd_listen_offload_stop(adapter);
Peng Xu8fdaa492016-06-22 10:20:47 -07009513}
9514
9515/**
9516 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
9517 * @wiphy: Pointer to wireless phy
9518 * @wdev: Pointer to wireless device
9519 * @data: Pointer to data
9520 * @data_len: Data length
9521 *
9522 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
9523 * to process p2p listen offload stop vendor command.
9524 *
9525 * Return: 0 on success, negative errno on failure
9526 */
9527static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
9528 struct wireless_dev *wdev,
9529 const void *data,
9530 int data_len)
9531{
9532 int ret = 0;
9533
9534 cds_ssr_protect(__func__);
9535 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
9536 data, data_len);
9537 cds_ssr_unprotect(__func__);
9538
9539 return ret;
9540}
9541
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309542/**
9543 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
9544 * @wiphy: Pointer to wireless phy
9545 * @wdev: Pointer to wireless device
9546 * @data: Pointer to data
9547 * @data_len: Data length
9548 *
9549 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
9550 * to process the conditional channel switch request.
9551 *
9552 * Return: 0 on success, negative errno on failure
9553 */
9554static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
9555 struct wireless_dev *wdev,
9556 const void *data,
9557 int data_len)
9558{
9559 int ret;
9560
9561 cds_ssr_protect(__func__);
9562 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
9563 data, data_len);
9564 cds_ssr_unprotect(__func__);
9565
9566 return ret;
9567}
9568
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309569/*
9570 * define short names for the global vendor params
9571 * used by __wlan_hdd_cfg80211_bpf_offload()
9572 */
9573#define BPF_INVALID \
9574 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
9575#define BPF_SET_RESET \
9576 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
9577#define BPF_VERSION \
9578 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
9579#define BPF_FILTER_ID \
9580 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
9581#define BPF_PACKET_SIZE \
9582 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
9583#define BPF_CURRENT_OFFSET \
9584 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
9585#define BPF_PROGRAM \
9586 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
9587#define BPF_MAX \
9588 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07009589
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309590static const struct nla_policy
9591wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
9592 [BPF_SET_RESET] = {.type = NLA_U32},
9593 [BPF_VERSION] = {.type = NLA_U32},
9594 [BPF_FILTER_ID] = {.type = NLA_U32},
9595 [BPF_PACKET_SIZE] = {.type = NLA_U32},
9596 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
9597 [BPF_PROGRAM] = {.type = NLA_U8},
9598};
9599
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009600struct bpf_offload_priv {
9601 struct sir_bpf_get_offload bpf_get_offload;
9602};
9603
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309604/**
9605 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009606 * @context: opaque context originally passed to SME. HDD always passes
9607 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309608 * @bpf_get_offload: struct for get offload
9609 *
9610 * This function receives the response/data from the lower layer and
9611 * checks to see if the thread is still waiting then post the results to
9612 * upper layer, if the request has timed out then ignore.
9613 *
9614 * Return: None
9615 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009616static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08009617 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309618{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009619 struct hdd_request *request;
9620 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309621
Dustin Brown491d54b2018-03-14 12:39:11 -07009622 hdd_enter();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309623
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009624 request = hdd_request_get(context);
9625 if (!request) {
9626 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309627 return;
9628 }
9629
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009630 priv = hdd_request_priv(request);
9631 priv->bpf_get_offload = *data;
9632 hdd_request_complete(request);
9633 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309634}
9635
9636/**
9637 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
9638 * @hdd_context: hdd_context
9639 * @bpf_get_offload: struct for get offload
9640 *
9641 * Return: 0 on success, error number otherwise.
9642 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009643static int hdd_post_get_bpf_capabilities_rsp(struct hdd_context *hdd_ctx,
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309644 struct sir_bpf_get_offload *bpf_get_offload)
9645{
9646 struct sk_buff *skb;
9647 uint32_t nl_buf_len;
9648
Dustin Brown491d54b2018-03-14 12:39:11 -07009649 hdd_enter();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309650
9651 nl_buf_len = NLMSG_HDRLEN;
9652 nl_buf_len +=
9653 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
9654 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
9655
9656 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
9657 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07009658 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309659 return -ENOMEM;
9660 }
9661
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009662 hdd_debug("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309663 bpf_get_offload->bpf_version,
9664 bpf_get_offload->max_bytes_for_bpf_inst);
9665
9666 if (nla_put_u32(skb, BPF_PACKET_SIZE,
9667 bpf_get_offload->max_bytes_for_bpf_inst) ||
9668 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009669 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309670 goto nla_put_failure;
9671 }
9672
9673 cfg80211_vendor_cmd_reply(skb);
Dustin Browne74003f2018-03-14 12:51:58 -07009674 hdd_exit();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309675 return 0;
9676
9677nla_put_failure:
9678 kfree_skb(skb);
9679 return -EINVAL;
9680}
9681
9682/**
9683 * hdd_get_bpf_offload - Get BPF offload Capabilities
9684 * @hdd_ctx: Hdd context
9685 *
9686 * Return: 0 on success, errno on failure
9687 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009688static int hdd_get_bpf_offload(struct hdd_context *hdd_ctx)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309689{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309690 QDF_STATUS status;
9691 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009692 void *cookie;
9693 struct hdd_request *request;
9694 struct bpf_offload_priv *priv;
9695 static const struct hdd_request_params params = {
9696 .priv_size = sizeof(*priv),
9697 .timeout_ms = WLAN_WAIT_TIME_BPF,
9698 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309699
Dustin Brown491d54b2018-03-14 12:39:11 -07009700 hdd_enter();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309701
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009702 request = hdd_request_alloc(&params);
9703 if (!request) {
9704 hdd_err("Unable to allocate request");
9705 return -EINVAL;
9706 }
9707 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309708
Jeff Johnsona867e0c2017-01-26 13:43:51 -08009709 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
9710 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009711 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309712 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009713 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009714 ret = qdf_status_to_os_return(status);
9715 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309716 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009717 ret = hdd_request_wait_for_response(request);
9718 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07009719 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009720 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309721 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009722 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309723 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009724 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309725 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07009726 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309727
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009728cleanup:
9729 /*
9730 * either we never sent a request to SME, we sent a request to
9731 * SME and timed out, or we sent a request to SME, received a
9732 * response from SME, and posted the response to userspace.
9733 * regardless we are done with the request.
9734 */
9735 hdd_request_put(request);
Dustin Browne74003f2018-03-14 12:51:58 -07009736 hdd_exit();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08009737
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309738 return ret;
9739}
9740
9741/**
9742 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
9743 * @hdd_ctx: Hdd context
9744 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05309745 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309746 *
9747 * Return: 0 on success; errno on failure
9748 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009749static int hdd_set_reset_bpf_offload(struct hdd_context *hdd_ctx,
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309750 struct nlattr **tb,
Jeff Johnsone5006672017-08-29 14:39:02 -07009751 struct hdd_adapter *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309752{
9753 struct sir_bpf_set_offload *bpf_set_offload;
9754 QDF_STATUS status;
9755 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05309756 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309757
Dustin Brown491d54b2018-03-14 12:39:11 -07009758 hdd_enter();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309759
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05309760 if (adapter->device_mode == QDF_STA_MODE ||
9761 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
9762 if (!hdd_conn_is_connected(
9763 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
9764 hdd_err("Not in Connected state!");
9765 return -ENOTSUPP;
9766 }
9767 }
9768
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309769 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
9770 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07009771 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309772 return -ENOMEM;
9773 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309774
9775 /* Parse and fetch bpf packet size */
9776 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009777 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05309778 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309779 goto fail;
9780 }
9781 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
9782
9783 if (!bpf_set_offload->total_length) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009784 hdd_debug("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309785 goto post_sme;
9786 }
9787
9788 /* Parse and fetch bpf program */
9789 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009790 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05309791 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309792 goto fail;
9793 }
9794
9795 prog_len = nla_len(tb[BPF_PROGRAM]);
9796 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05309797
9798 if (bpf_set_offload->program == NULL) {
9799 hdd_err("qdf_mem_malloc failed for bpf offload program");
9800 ret = -ENOMEM;
9801 goto fail;
9802 }
9803
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309804 bpf_set_offload->current_length = prog_len;
9805 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Jeff Johnson1b780e42017-10-31 14:11:45 -07009806 bpf_set_offload->session_id = adapter->session_id;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309807
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009808 hdd_debug("BPF set instructions");
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08009809 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05309810 bpf_set_offload->program, prog_len);
9811
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309812 /* Parse and fetch filter Id */
9813 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009814 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05309815 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309816 goto fail;
9817 }
9818 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
9819
9820 /* Parse and fetch current offset */
9821 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009822 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05309823 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309824 goto fail;
9825 }
9826 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
9827
9828post_sme:
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009829 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 +05309830 bpf_set_offload->session_id,
9831 bpf_set_offload->version,
9832 bpf_set_offload->filter_id,
9833 bpf_set_offload->total_length,
9834 bpf_set_offload->current_length,
9835 bpf_set_offload->current_offset);
9836
9837 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
9838 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009839 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05309840 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309841 goto fail;
9842 }
Dustin Browne74003f2018-03-14 12:51:58 -07009843 hdd_exit();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309844
9845fail:
9846 if (bpf_set_offload->current_length)
9847 qdf_mem_free(bpf_set_offload->program);
9848 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05309849 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309850}
9851
9852/**
9853 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
9854 * @wiphy: wiphy structure pointer
9855 * @wdev: Wireless device structure pointer
9856 * @data: Pointer to the data received
9857 * @data_len: Length of @data
9858 *
9859 * Return: 0 on success; errno on failure
9860 */
9861static int
9862__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
9863 struct wireless_dev *wdev,
9864 const void *data, int data_len)
9865{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009866 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309867 struct net_device *dev = wdev->netdev;
Jeff Johnsonce2ba702017-10-02 13:30:24 -07009868 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309869 struct nlattr *tb[BPF_MAX + 1];
9870 int ret_val, packet_filter_subcmd;
9871
Dustin Brown491d54b2018-03-14 12:39:11 -07009872 hdd_enter();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309873
9874 ret_val = wlan_hdd_validate_context(hdd_ctx);
9875 if (ret_val)
9876 return ret_val;
9877
9878 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009879 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309880 return -EINVAL;
9881 }
9882
9883 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07009884 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309885 return -ENOTSUPP;
9886 }
9887
Dustin Brown4ea21db2018-01-05 14:13:17 -08009888 if (wlan_cfg80211_nla_parse(tb, BPF_MAX, data, data_len,
9889 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009890 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309891 return -EINVAL;
9892 }
9893
9894 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07009895 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309896 return -EINVAL;
9897 }
9898
9899 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
9900
9901 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
9902 return hdd_get_bpf_offload(hdd_ctx);
9903 else
9904 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Jeff Johnsonce2ba702017-10-02 13:30:24 -07009905 adapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309906}
9907
9908/**
9909 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
9910 * @wiphy: wiphy structure pointer
9911 * @wdev: Wireless device structure pointer
9912 * @data: Pointer to the data received
9913 * @data_len: Length of @data
9914 *
9915 * Return: 0 on success; errno on failure
9916 */
9917
9918static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
9919 struct wireless_dev *wdev,
9920 const void *data, int data_len)
9921{
9922 int ret;
9923
9924 cds_ssr_protect(__func__);
9925 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
9926 cds_ssr_unprotect(__func__);
9927
9928 return ret;
9929}
9930
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309931/**
9932 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
9933 * @pre_cac_adapter: AP adapter used for pre cac
9934 * @status: Status (true or false)
9935 * @handle: Global handle
9936 *
9937 * Sets the status of pre cac i.e., whether the pre cac is active or not
9938 *
9939 * Return: Zero on success, non-zero on failure
9940 */
Jeff Johnsone5006672017-08-29 14:39:02 -07009941static int wlan_hdd_set_pre_cac_status(struct hdd_adapter *pre_cac_adapter,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309942 bool status, tHalHandle handle)
9943{
9944 QDF_STATUS ret;
9945
9946 ret = wlan_sap_set_pre_cac_status(
9947 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
9948 if (QDF_IS_STATUS_ERROR(ret))
9949 return -EINVAL;
9950
9951 return 0;
9952}
9953
9954/**
9955 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
9956 * @ap_adapter: AP adapter
9957 * @chan_before_pre_cac: Channel
9958 *
9959 * Saves the channel which the AP was beaconing on before moving to the pre
9960 * cac channel. If radar is detected on the pre cac channel, this saved
9961 * channel will be used for AP operations.
9962 *
9963 * Return: Zero on success, non-zero on failure
9964 */
Jeff Johnsone5006672017-08-29 14:39:02 -07009965static int wlan_hdd_set_chan_before_pre_cac(struct hdd_adapter *ap_adapter,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309966 uint8_t chan_before_pre_cac)
9967{
9968 QDF_STATUS ret;
9969
9970 ret = wlan_sap_set_chan_before_pre_cac(
9971 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
9972 if (QDF_IS_STATUS_ERROR(ret))
9973 return -EINVAL;
9974
9975 return 0;
9976}
9977
Jeff Johnsone5006672017-08-29 14:39:02 -07009978int wlan_hdd_sap_get_valid_channellist(struct hdd_adapter *adapter,
Kapil Gupta94ca6f62016-12-11 18:43:12 +05309979 uint32_t *channel_count,
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05309980 uint8_t *channel_list,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -08009981 enum band_info band)
Kapil Gupta94ca6f62016-12-11 18:43:12 +05309982{
9983 tsap_Config_t *sap_config;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -07009984 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05309985 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
9986 uint32_t chan_count;
9987 uint8_t i;
9988 QDF_STATUS status;
bingsd79e6062018-01-30 15:40:16 +08009989 struct wlan_objmgr_pdev *pdev = hdd_ctx->hdd_pdev;
9990 uint8_t tmp_chan;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05309991
Jeff Johnsonb9424862017-10-30 08:49:35 -07009992 sap_config = &adapter->session.ap.sap_config;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05309993
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +05309994 status =
9995 policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
9996 tmp_chan_list,
9997 &chan_count);
9998 if (QDF_IS_STATUS_ERROR(status)) {
9999 hdd_err("Failed to get channel list");
10000 return -EINVAL;
10001 }
Kapil Guptac1224bf2017-06-22 21:22:40 +053010002
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +053010003 for (i = 0; i < chan_count; i++) {
bingsd79e6062018-01-30 15:40:16 +080010004 tmp_chan = tmp_chan_list[i];
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +053010005 if (*channel_count < QDF_MAX_NUM_CHAN) {
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080010006 if ((BAND_2G == band) &&
bingsd79e6062018-01-30 15:40:16 +080010007 (WLAN_REG_IS_24GHZ_CH(tmp_chan)) &&
10008 (!wlan_reg_is_disable_ch(pdev, tmp_chan))) {
10009 channel_list[*channel_count] = tmp_chan;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +053010010 *channel_count += 1;
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080010011 } else if ((BAND_5G == band) &&
bingsd79e6062018-01-30 15:40:16 +080010012 (WLAN_REG_IS_5GHZ_CH(tmp_chan)) &&
10013 (!wlan_reg_is_disable_ch(pdev, tmp_chan))) {
10014 channel_list[*channel_count] = tmp_chan;
Jayachandran Sreekumaran68c952c2017-04-24 12:42:03 +053010015 *channel_count += 1;
10016 }
10017 } else {
10018 break;
10019 }
10020 }
bingsd79e6062018-01-30 15:40:16 +080010021
Kapil Gupta94ca6f62016-12-11 18:43:12 +053010022 if (*channel_count == 0) {
10023 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010024 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +053010025 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010026
10027 return 0;
10028}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010029
10030/**
10031 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
10032 * @hdd_ctx: HDD context
10033 * @ap_adapter: AP adapter
10034 * @channel: Channel requested by userspace
10035 * @pre_cac_chan: Pointer to the pre CAC channel
10036 *
10037 * Validates the channel provided by userspace. If user provided channel 0,
10038 * a valid outdoor channel must be selected from the regulatory channel.
10039 *
10040 * Return: Zero on success and non zero value on error
10041 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010042static int wlan_hdd_validate_and_get_pre_cac_ch(struct hdd_context *hdd_ctx,
Jeff Johnsone5006672017-08-29 14:39:02 -070010043 struct hdd_adapter *ap_adapter,
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010044 uint8_t channel,
10045 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010046{
bingsd79e6062018-01-30 15:40:16 +080010047 uint32_t i;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010048 QDF_STATUS status;
bingsd79e6062018-01-30 15:40:16 +080010049 uint32_t weight_len = 0;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010050 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10051 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
10052 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
10053
10054 if (0 == channel) {
10055 /* Channel is not obtained from PCL because PCL may not have
10056 * the entire channel list. For example: if SAP is up on
10057 * channel 6 and PCL is queried for the next SAP interface,
10058 * if SCC is preferred, the PCL will contain only the channel
10059 * 6. But, we are in need of a DFS channel. So, going with the
10060 * first channel from the valid channel list.
10061 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080010062 status = policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
10063 channel_list, &len);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010064 if (QDF_IS_STATUS_ERROR(status)) {
10065 hdd_err("Failed to get channel list");
10066 return -EINVAL;
10067 }
Tushnim Bhattacharyyaabc58852017-07-26 13:14:52 -070010068 policy_mgr_update_with_safe_channel_list(hdd_ctx->hdd_psoc,
10069 channel_list, &len, pcl_weights, weight_len);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010070 for (i = 0; i < len; i++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010071 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
10072 channel_list[i])) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010073 *pre_cac_chan = channel_list[i];
10074 break;
10075 }
10076 }
10077 if (*pre_cac_chan == 0) {
10078 hdd_err("unable to find outdoor channel");
10079 return -EINVAL;
10080 }
10081 } else {
10082 /* Only when driver selects a channel, check is done for
10083 * unnsafe and NOL channels. When user provides a fixed channel
10084 * the user is expected to take care of this.
10085 */
10086 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010087 !wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010088 hdd_err("Invalid channel for pre cac:%d", channel);
10089 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010090 }
Jeff Johnson68755312017-02-10 11:46:55 -080010091 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010092 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010093 hdd_debug("selected pre cac channel:%d", *pre_cac_chan);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010094 return 0;
10095}
10096
10097/**
10098 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
10099 * @channel: Channel option provided by userspace
10100 *
10101 * Sets the driver to the required hardware mode and start an adapater for
10102 * pre CAC which will mimic an AP.
10103 *
10104 * Return: Zero on success, non-zero value on error
10105 */
10106int wlan_hdd_request_pre_cac(uint8_t channel)
10107{
Krunal Sonib37bb352016-12-20 14:12:21 -080010108 uint8_t pre_cac_chan = 0, *mac_addr;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010109 struct hdd_context *hdd_ctx;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010110 int ret;
Jeff Johnsone5006672017-08-29 14:39:02 -070010111 struct hdd_adapter *ap_adapter, *pre_cac_adapter;
Jeff Johnson87251032017-08-29 13:31:11 -070010112 struct hdd_ap_ctx *hdd_ap_ctx;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010113 QDF_STATUS status;
10114 struct wiphy *wiphy;
10115 struct net_device *dev;
10116 struct cfg80211_chan_def chandef;
10117 enum nl80211_channel_type channel_type;
10118 uint32_t freq;
10119 struct ieee80211_channel *chan;
10120 tHalHandle handle;
10121 bool val;
10122
10123 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10124 if (0 != wlan_hdd_validate_context(hdd_ctx))
10125 return -EINVAL;
10126
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080010127 if (policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) > 1) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010128 hdd_err("pre cac not allowed in concurrency");
10129 return -EINVAL;
10130 }
10131
10132 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
10133 if (!ap_adapter) {
10134 hdd_err("unable to get SAP adapter");
10135 return -EINVAL;
10136 }
10137
10138 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
10139 if (!handle) {
10140 hdd_err("Invalid handle");
10141 return -EINVAL;
10142 }
10143
10144 val = wlan_sap_is_pre_cac_active(handle);
10145 if (val) {
10146 hdd_err("pre cac is already in progress");
10147 return -EINVAL;
10148 }
10149
10150 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
10151 if (!hdd_ap_ctx) {
10152 hdd_err("SAP context is NULL");
10153 return -EINVAL;
10154 }
10155
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010156 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
Jeff Johnson01206862017-10-27 20:55:59 -070010157 hdd_ap_ctx->operating_channel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010158 hdd_err("SAP is already on DFS channel:%d",
Jeff Johnson01206862017-10-27 20:55:59 -070010159 hdd_ap_ctx->operating_channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010160 return -EINVAL;
10161 }
10162
Jeff Johnson01206862017-10-27 20:55:59 -070010163 if (!WLAN_REG_IS_24GHZ_CH(hdd_ap_ctx->operating_channel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010164 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
Jeff Johnson01206862017-10-27 20:55:59 -070010165 hdd_ap_ctx->operating_channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010166 return -EINVAL;
10167 }
10168
Krunal Sonib37bb352016-12-20 14:12:21 -080010169 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
10170 if (!mac_addr) {
10171 hdd_err("can't add virtual intf: Not getting valid mac addr");
10172 return -EINVAL;
10173 }
10174
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010175 hdd_debug("channel:%d", channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010176
10177 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
10178 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -080010179 if (ret != 0) {
10180 hdd_err("can't validate pre-cac channel");
10181 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010182 }
10183
10184 hdd_debug("starting pre cac SAP adapter");
10185
10186 /* Starting a SAP adapter:
10187 * Instead of opening an adapter, we could just do a SME open session
10188 * for AP type. But, start BSS would still need an adapter.
10189 * So, this option is not taken.
10190 *
10191 * hdd open adapter is going to register this precac interface with
10192 * user space. This interface though exposed to user space will be in
10193 * DOWN state. Consideration was done to avoid this registration to the
10194 * user space. But, as part of SAP operations multiple events are sent
10195 * to user space. Some of these events received from unregistered
10196 * interface was causing crashes. So, retaining the registration.
10197 *
10198 * So, this interface would remain registered and will remain in DOWN
10199 * state for the CAC duration. We will add notes in the feature
10200 * announcement to not use this temporary interface for any activity
10201 * from user space.
10202 */
10203 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -080010204 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010205 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +053010206 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -080010207 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010208 }
10209
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +053010210 /*
10211 * This interface is internally created by the driver. So, no interface
10212 * up comes for this interface from user space and hence starting
10213 * the adapter internally.
10214 */
10215 if (hdd_start_adapter(pre_cac_adapter)) {
10216 hdd_err("error starting the pre cac adapter");
10217 goto close_pre_cac_adapter;
10218 }
10219
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010220 hdd_debug("preparing for start ap/bss on the pre cac adapter");
10221
10222 wiphy = hdd_ctx->wiphy;
10223 dev = pre_cac_adapter->dev;
10224
10225 /* Since this is only a dummy interface lets us use the IEs from the
10226 * other active SAP interface. In regular scenarios, these IEs would
10227 * come from the user space entity
10228 */
Jeff Johnsonb9424862017-10-30 08:49:35 -070010229 pre_cac_adapter->session.ap.beacon = qdf_mem_malloc(
10230 sizeof(*ap_adapter->session.ap.beacon));
10231 if (!pre_cac_adapter->session.ap.beacon) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010232 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +053010233 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010234 }
Jeff Johnsonb9424862017-10-30 08:49:35 -070010235 qdf_mem_copy(pre_cac_adapter->session.ap.beacon,
10236 ap_adapter->session.ap.beacon,
10237 sizeof(*pre_cac_adapter->session.ap.beacon));
10238 pre_cac_adapter->session.ap.sap_config.ch_width_orig =
10239 ap_adapter->session.ap.sap_config.ch_width_orig;
10240 pre_cac_adapter->session.ap.sap_config.authType =
10241 ap_adapter->session.ap.sap_config.authType;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010242
10243 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
10244 * to operate on the same bandwidth as that of the 2.4GHz operations.
10245 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
10246 */
Jeff Johnsonb9424862017-10-30 08:49:35 -070010247 switch (ap_adapter->session.ap.sap_config.ch_width_orig) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010248 case CH_WIDTH_20MHZ:
10249 channel_type = NL80211_CHAN_HT20;
10250 break;
10251 case CH_WIDTH_40MHZ:
Jeff Johnsonb9424862017-10-30 08:49:35 -070010252 if (ap_adapter->session.ap.sap_config.sec_ch >
10253 ap_adapter->session.ap.sap_config.channel)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010254 channel_type = NL80211_CHAN_HT40PLUS;
10255 else
10256 channel_type = NL80211_CHAN_HT40MINUS;
10257 break;
10258 default:
10259 channel_type = NL80211_CHAN_NO_HT;
10260 break;
10261 }
10262
10263 freq = cds_chan_to_freq(pre_cac_chan);
Dustin Brown2eb1e452017-08-15 12:40:34 -070010264 chan = ieee80211_get_channel(wiphy, freq);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010265 if (!chan) {
10266 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +053010267 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010268 }
10269
10270 cfg80211_chandef_create(&chandef, chan, channel_type);
10271
10272 hdd_debug("orig width:%d channel_type:%d freq:%d",
Jeff Johnsonb9424862017-10-30 08:49:35 -070010273 ap_adapter->session.ap.sap_config.ch_width_orig,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010274 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -080010275 /*
10276 * Doing update after opening and starting pre-cac adapter will make
10277 * sure that driver won't do hardware mode change if there are any
10278 * initial hick-ups or issues in pre-cac adapter's configuration.
10279 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
10280 * connection update should result in DBS mode
10281 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080010282 status = policy_mgr_update_and_wait_for_connection_update(
Tushnim Bhattacharyya3b99f4b2018-03-26 14:19:24 -070010283 hdd_ctx->hdd_psoc,
10284 ap_adapter->session_id,
10285 pre_cac_chan,
10286 POLICY_MGR_UPDATE_REASON_PRE_CAC);
Krunal Sonib37bb352016-12-20 14:12:21 -080010287 if (QDF_IS_STATUS_ERROR(status)) {
10288 hdd_err("error in moving to DBS mode");
10289 goto stop_close_pre_cac_adapter;
10290 }
10291
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010292
10293 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
10294 if (0 != ret) {
10295 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +053010296 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010297 }
10298
10299 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
10300 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Mahesh Kumar Kalikot Veetilc637fc92017-09-27 16:06:21 -070010301 NL80211_HIDDEN_SSID_NOT_IN_USE, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010302 if (QDF_IS_STATUS_ERROR(status)) {
10303 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +053010304 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010305 }
10306
10307 /*
10308 * The pre cac status is set here. But, it would not be reset explicitly
10309 * anywhere, since after the pre cac success/failure, the pre cac
10310 * adapter itself would be removed.
10311 */
10312 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
10313 if (0 != ret) {
10314 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +053010315 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010316 }
10317
10318 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
Jeff Johnson01206862017-10-27 20:55:59 -070010319 hdd_ap_ctx->operating_channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010320 if (0 != ret) {
10321 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +053010322 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010323 }
10324
10325 ap_adapter->pre_cac_chan = pre_cac_chan;
10326
10327 return 0;
10328
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +053010329stop_close_pre_cac_adapter:
Dustin Browndb2a8be2017-12-20 11:49:56 -080010330 hdd_stop_adapter(hdd_ctx, pre_cac_adapter);
Jeff Johnsonb9424862017-10-30 08:49:35 -070010331 qdf_mem_free(pre_cac_adapter->session.ap.beacon);
10332 pre_cac_adapter->session.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +053010333close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010334 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -080010335release_intf_addr_and_return_failure:
10336 /*
10337 * Release the interface address as the adapter
10338 * failed to start, if you don't release then next
10339 * adapter which is trying to come wouldn't get valid
10340 * mac address. Remember we have limited pool of mac addresses
10341 */
10342 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010343 return -EINVAL;
10344}
10345
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010346static const struct nla_policy
10347wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
10348 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
Ganesh Kondabattini099e6e82017-06-28 12:24:20 +053010349 [QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST] = {
10350 .type = NLA_NESTED },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010351};
10352
Agrawal Ashish65634612016-08-18 13:24:32 +053010353static const struct nla_policy
10354wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
10355 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
10356 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
10357};
10358
Ganesh Kondabattinib1960e72017-09-01 09:09:50 +053010359static const struct nla_policy
10360wlan_hdd_set_limit_off_channel_param_policy
10361[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_MAX + 1] = {
10362 [QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS] = {.type = NLA_U8 },
10363 [QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_START] = {.type = NLA_U8 },
10364};
10365
Agrawal Ashish65634612016-08-18 13:24:32 +053010366/**
10367 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
10368 * @wiphy: Pointer to wireless phy
10369 * @wdev: Pointer to wireless device
10370 * @data: Pointer to data
10371 * @data_len: Length of @data
10372 *
10373 * This function parses the incoming NL vendor command data attributes and
10374 * updates the SAP context about channel_hint and DFS mode.
10375 * If channel_hint is set, SAP will choose that channel
10376 * as operating channel.
10377 *
10378 * If DFS mode is enabled, driver will include DFS channels
10379 * in ACS else driver will skip DFS channels.
10380 *
10381 * Return: 0 on success, negative errno on failure
10382 */
10383static int
10384__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
10385 struct wireless_dev *wdev,
10386 const void *data, int data_len)
10387{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010388 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashish65634612016-08-18 13:24:32 +053010389 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
10390 int ret;
10391 struct acs_dfs_policy *acs_policy;
10392 int mode = DFS_MODE_NONE;
10393 int channel_hint = 0;
10394
Dustin Brownfdf17c12018-03-14 12:55:34 -070010395 hdd_enter_dev(wdev->netdev);
Agrawal Ashish65634612016-08-18 13:24:32 +053010396
10397 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
10398 hdd_err("Command not allowed in FTM mode");
10399 return -EINVAL;
10400 }
10401
10402 ret = wlan_hdd_validate_context(hdd_ctx);
10403 if (0 != ret)
10404 return ret;
10405
Dustin Brown4ea21db2018-01-05 14:13:17 -080010406 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
10407 data, data_len,
10408 wlan_hdd_set_acs_dfs_config_policy)) {
Agrawal Ashish65634612016-08-18 13:24:32 +053010409 hdd_err("invalid attr");
10410 return -EINVAL;
10411 }
10412
10413 acs_policy = &hdd_ctx->acs_policy;
10414 /*
10415 * SCM sends this attribute to restrict SAP from choosing
10416 * DFS channels from ACS.
10417 */
10418 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
10419 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
10420
10421 if (!IS_DFS_MODE_VALID(mode)) {
10422 hdd_err("attr acs dfs mode is not valid");
10423 return -EINVAL;
10424 }
10425 acs_policy->acs_dfs_mode = mode;
10426
10427 /*
10428 * SCM sends this attribute to provide an active channel,
10429 * to skip redundant ACS between drivers, and save driver start up time
10430 */
10431 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
10432 channel_hint = nla_get_u8(
10433 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
10434
10435 if (!IS_CHANNEL_VALID(channel_hint)) {
10436 hdd_err("acs channel is not valid");
10437 return -EINVAL;
10438 }
10439 acs_policy->acs_channel = channel_hint;
10440
10441 return 0;
10442}
10443
10444/**
10445 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
10446 * @wiphy: wiphy structure pointer
10447 * @wdev: Wireless device structure pointer
10448 * @data: Pointer to the data received
10449 * @data_len: Length of @data
10450 *
10451 * This function parses the incoming NL vendor command data attributes and
10452 * updates the SAP context about channel_hint and DFS mode.
10453 *
10454 * Return: 0 on success; errno on failure
10455 */
10456static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
10457 struct wireless_dev *wdev,
10458 const void *data, int data_len)
10459{
10460 int ret;
10461
10462 cds_ssr_protect(__func__);
10463 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
10464 cds_ssr_unprotect(__func__);
10465
10466 return ret;
10467}
10468
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010469/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010470 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
10471 * @mode : cfg80211 dfs mode
10472 *
10473 * Return: return csr sta roam dfs mode else return NONE
10474 */
10475static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
10476 enum dfs_mode mode)
10477{
10478 switch (mode) {
10479 case DFS_MODE_ENABLE:
10480 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010481 case DFS_MODE_DISABLE:
10482 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010483 case DFS_MODE_DEPRIORITIZE:
10484 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010485 default:
10486 hdd_err("STA Roam policy dfs mode is NONE");
10487 return CSR_STA_ROAM_POLICY_NONE;
10488 }
10489}
10490
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010491/*
10492 * hdd_get_sap_operating_band: Get current operating channel
10493 * for sap.
10494 * @hdd_ctx: hdd context
10495 *
10496 * Return : Corresponding band for SAP operating channel
10497 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010498uint8_t hdd_get_sap_operating_band(struct hdd_context *hdd_ctx)
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010499{
Jeff Johnsone5006672017-08-29 14:39:02 -070010500 struct hdd_adapter *adapter;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010501 uint8_t operating_channel = 0;
10502 uint8_t sap_operating_band = 0;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070010503
Dustin Brown920397d2017-12-13 16:27:50 -080010504 hdd_for_each_adapter(hdd_ctx, adapter) {
10505 if (adapter->device_mode != QDF_SAP_MODE)
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010506 continue;
Dustin Brown920397d2017-12-13 16:27:50 -080010507
Jeff Johnsonb9424862017-10-30 08:49:35 -070010508 operating_channel = adapter->session.ap.operating_channel;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010509 if (IS_24G_CH(operating_channel))
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080010510 sap_operating_band = BAND_2G;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010511 else if (IS_5G_CH(operating_channel))
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080010512 sap_operating_band = BAND_5G;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010513 else
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080010514 sap_operating_band = BAND_ALL;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010515 }
Dustin Brown920397d2017-12-13 16:27:50 -080010516
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010517 return sap_operating_band;
10518}
10519
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010520static const struct nla_policy
10521wlan_hdd_set_sta_roam_config_policy[
10522QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
10523 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
10524 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
10525};
10526
10527/**
10528 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
10529 * for station connection or roaming.
10530 * @wiphy: Pointer to wireless phy
10531 * @wdev: Pointer to wireless device
10532 * @data: Pointer to data
10533 * @data_len: Length of @data
10534 *
10535 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
10536 * channels needs to be skipped in scanning or not.
10537 * If dfs_mode is disabled, driver will not scan DFS channels.
10538 * If skip_unsafe_channels is set, driver will skip unsafe channels
10539 * in Scanning.
10540 *
10541 * Return: 0 on success, negative errno on failure
10542 */
10543static int
10544__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
10545 struct wireless_dev *wdev,
10546 const void *data, int data_len)
10547{
10548 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -070010549 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010550 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010551 struct nlattr *tb[
10552 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
10553 int ret;
10554 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
10555 enum dfs_mode mode = DFS_MODE_NONE;
10556 bool skip_unsafe_channels = false;
10557 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010558 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010559
Dustin Brownfdf17c12018-03-14 12:55:34 -070010560 hdd_enter_dev(dev);
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010561
10562 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
10563 hdd_err("Command not allowed in FTM mode");
10564 return -EINVAL;
10565 }
10566
10567 ret = wlan_hdd_validate_context(hdd_ctx);
10568 if (0 != ret)
10569 return ret;
Dustin Brown4ea21db2018-01-05 14:13:17 -080010570 if (wlan_cfg80211_nla_parse(tb,
10571 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
10572 data, data_len,
10573 wlan_hdd_set_sta_roam_config_policy)) {
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010574 hdd_err("invalid attr");
10575 return -EINVAL;
10576 }
10577 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
10578 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
10579 if (!IS_DFS_MODE_VALID(mode)) {
10580 hdd_err("attr sta roam dfs mode policy is not valid");
10581 return -EINVAL;
10582 }
10583
10584 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
10585
10586 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
10587 skip_unsafe_channels = nla_get_u8(
10588 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010589 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010590 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Jeff Johnson1b780e42017-10-31 14:11:45 -070010591 skip_unsafe_channels, adapter->session_id,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +053010592 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010593
10594 if (!QDF_IS_STATUS_SUCCESS(status)) {
10595 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
10596 return -EINVAL;
10597 }
10598 return 0;
10599}
10600
10601/**
10602 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
10603 * connection and roaming for station.
10604 * @wiphy: wiphy structure pointer
10605 * @wdev: Wireless device structure pointer
10606 * @data: Pointer to the data received
10607 * @data_len: Length of @data
10608 *
10609 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
10610 * channels needs to be skipped in scanning or not.
10611 * If dfs_mode is disabled, driver will not scan DFS channels.
10612 * If skip_unsafe_channels is set, driver will skip unsafe channels
10613 * in Scanning.
10614 * Return: 0 on success; errno on failure
10615 */
10616static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
10617 struct wireless_dev *wdev,
10618 const void *data, int data_len)
10619{
10620 int ret;
10621
10622 cds_ssr_protect(__func__);
10623 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
10624 cds_ssr_unprotect(__func__);
10625
10626 return ret;
10627}
10628
Agrawal Ashish467dde42016-09-08 18:44:22 +053010629#ifdef FEATURE_WLAN_CH_AVOID
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010630
10631static int hdd_validate_avoid_freq_chanlist(
10632 struct hdd_context *hdd_ctx,
10633 struct ch_avoid_ind_type *channel_list)
10634{
10635 unsigned int range_idx, ch_idx;
10636 unsigned int unsafe_channel_index, unsafe_channel_count = 0;
10637 bool ch_found = false;
10638
10639 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
10640 (uint16_t)NUM_CHANNELS);
10641
10642 for (range_idx = 0; range_idx < channel_list->ch_avoid_range_cnt;
10643 range_idx++) {
10644 if ((channel_list->avoid_freq_range[range_idx].start_freq <
10645 CDS_24_GHZ_CHANNEL_1) ||
10646 (channel_list->avoid_freq_range[range_idx].end_freq >
10647 CDS_5_GHZ_CHANNEL_165) ||
10648 (channel_list->avoid_freq_range[range_idx].start_freq >
10649 channel_list->avoid_freq_range[range_idx].end_freq))
10650 continue;
10651
10652 for (ch_idx = channel_list->
10653 avoid_freq_range[range_idx].start_freq;
10654 ch_idx <= channel_list->
10655 avoid_freq_range[range_idx].end_freq;
10656 ch_idx++) {
10657 for (unsafe_channel_index = 0;
10658 unsafe_channel_index < unsafe_channel_count;
10659 unsafe_channel_index++) {
10660 if (ch_idx ==
10661 hdd_ctx->unsafe_channel_list[
10662 unsafe_channel_index]) {
Dustin Brown632af712018-03-14 15:03:55 -070010663 hdd_info("Duplicate channel %d",
10664 ch_idx);
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010665 ch_found = true;
10666 break;
10667 }
10668 }
10669 if (!ch_found) {
10670 hdd_ctx->unsafe_channel_list[
10671 unsafe_channel_count++] = ch_idx;
10672 }
10673 ch_found = false;
10674 }
10675 }
10676 return unsafe_channel_count;
10677}
10678
Agrawal Ashish467dde42016-09-08 18:44:22 +053010679/**
10680 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
10681 * is on unsafe channel.
10682 * @wiphy: wiphy structure pointer
10683 * @wdev: Wireless device structure pointer
10684 * @data: Pointer to the data received
10685 * @data_len: Length of @data
10686 *
10687 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
10688 * on any of unsafe channels.
10689 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
10690 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
10691 *
10692 * Return: 0 on success; errno on failure
10693 */
10694static int
10695__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
10696 struct wireless_dev *wdev,
10697 const void *data, int data_len)
10698{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010699 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashish467dde42016-09-08 18:44:22 +053010700 int ret;
Agrawal Ashish467dde42016-09-08 18:44:22 +053010701 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
Liangwei Dong6e1a2092017-08-30 16:29:06 +080010702 uint16_t *local_unsafe_list;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010703 uint16_t unsafe_channel_index, local_unsafe_list_count;
10704 struct ch_avoid_ind_type *channel_list;
10705 enum tQDF_GLOBAL_CON_MODE curr_mode;
Agrawal Ashish467dde42016-09-08 18:44:22 +053010706
Dustin Brownfdf17c12018-03-14 12:55:34 -070010707 hdd_enter_dev(wdev->netdev);
Agrawal Ashish467dde42016-09-08 18:44:22 +053010708
10709 if (!qdf_ctx) {
Jeff Johnson6867ec32017-09-29 20:30:20 -070010710 hdd_err("qdf_ctx is NULL");
Agrawal Ashish467dde42016-09-08 18:44:22 +053010711 return -EINVAL;
10712 }
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010713 curr_mode = hdd_get_conparam();
10714 if (QDF_GLOBAL_FTM_MODE == curr_mode ||
10715 QDF_GLOBAL_MONITOR_MODE == curr_mode) {
10716 hdd_err("Command not allowed in FTM/MONITOR mode");
Agrawal Ashish467dde42016-09-08 18:44:22 +053010717 return -EINVAL;
10718 }
10719
10720 ret = wlan_hdd_validate_context(hdd_ctx);
10721 if (0 != ret)
10722 return ret;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010723
10724 channel_list = (struct ch_avoid_ind_type *)data;
10725 if (!channel_list) {
Dustin Brown632af712018-03-14 15:03:55 -070010726 hdd_err("Avoid frequency channel list empty");
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010727 return -EINVAL;
10728 }
10729
Liangwei Dong6e1a2092017-08-30 16:29:06 +080010730 ret = hdd_clone_local_unsafe_chan(hdd_ctx,
10731 &local_unsafe_list,
10732 &local_unsafe_list_count);
10733 if (0 != ret) {
10734 hdd_err("failed to clone the cur unsafe chan list");
10735 return ret;
10736 }
10737
Agrawal Ashish467dde42016-09-08 18:44:22 +053010738 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
10739 &(hdd_ctx->unsafe_channel_count),
10740 sizeof(hdd_ctx->unsafe_channel_list));
10741
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010742 hdd_ctx->unsafe_channel_count = hdd_validate_avoid_freq_chanlist(
10743 hdd_ctx,
10744 channel_list);
10745
10746 pld_set_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
10747 hdd_ctx->unsafe_channel_count);
10748
Agrawal Ashish467dde42016-09-08 18:44:22 +053010749 for (unsafe_channel_index = 0;
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010750 unsafe_channel_index < hdd_ctx->unsafe_channel_count;
10751 unsafe_channel_index++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010752 hdd_debug("Channel %d is not safe",
Ashish Kumar Dhanotiya4be2a7b2018-02-09 20:08:21 +053010753 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
Agrawal Ashish467dde42016-09-08 18:44:22 +053010754 }
Liangwei Dong6e1a2092017-08-30 16:29:06 +080010755 if (hdd_local_unsafe_channel_updated(hdd_ctx, local_unsafe_list,
10756 local_unsafe_list_count))
10757 hdd_unsafe_channel_restart_sap(hdd_ctx);
10758 qdf_mem_free(local_unsafe_list);
10759
Agrawal Ashish467dde42016-09-08 18:44:22 +053010760 return 0;
10761}
10762
10763/**
10764 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
10765 * is on unsafe channel.
10766 * @wiphy: wiphy structure pointer
10767 * @wdev: Wireless device structure pointer
10768 * @data: Pointer to the data received
10769 * @data_len: Length of @data
10770 *
10771 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
10772 * on any of unsafe channels.
10773 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
10774 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
10775 *
10776 * Return: 0 on success; errno on failure
10777 */
10778static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
10779 struct wireless_dev *wdev,
10780 const void *data, int data_len)
10781{
10782 int ret;
10783
10784 cds_ssr_protect(__func__);
10785 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
10786 cds_ssr_unprotect(__func__);
10787
10788 return ret;
10789}
10790
10791#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010792/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010793 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
10794 * SAP is on unsafe channel.
10795 * @wiphy: wiphy structure pointer
10796 * @wdev: Wireless device structure pointer
10797 * @data: Pointer to the data received
10798 * @data_len: Length of @data
10799 *
10800 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
10801 * driver.
10802 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
10803 * will initiate restart of sap.
10804 *
10805 * Return: 0 on success; errno on failure
10806 */
10807static int
10808__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
10809 struct wireless_dev *wdev,
10810 const void *data, int data_len)
10811{
10812 struct net_device *ndev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -070010813 struct hdd_adapter *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070010814 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010815 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
10816 uint8_t config_channel = 0;
Jeff Johnson87251032017-08-29 13:31:11 -070010817 struct hdd_ap_ctx *ap_ctx;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010818 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +053010819 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010820
Dustin Brown491d54b2018-03-14 12:39:11 -070010821 hdd_enter();
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010822
10823 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010824 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010825 return -EINVAL;
10826 }
10827
10828 ret = wlan_hdd_validate_context(hdd_ctx);
10829 if (0 != ret)
10830 return -EINVAL;
10831
Dustin Brown4ea21db2018-01-05 14:13:17 -080010832 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
10833 data, data_len,
10834 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010835 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010836 return -EINVAL;
10837 }
10838
10839 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
10840 if (!test_bit(SOFTAP_BSS_STARTED,
10841 &hostapd_adapter->event_flags)) {
10842 hdd_err("SAP is not started yet. Restart sap will be invalid");
10843 return -EINVAL;
10844 }
10845
10846 config_channel =
10847 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
10848
10849 if (!((IS_24G_CH(config_channel)) ||
10850 (IS_5G_CH(config_channel)))) {
10851 hdd_err("Channel %d is not valid to restart SAP",
10852 config_channel);
10853 return -ENOTSUPP;
10854 }
10855
10856 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
Jeff Johnson91df29d2017-10-27 19:29:50 -070010857 ap_ctx->sap_config.channel = config_channel;
10858 ap_ctx->sap_config.ch_params.ch_width =
10859 ap_ctx->sap_config.ch_width_orig;
hqu73bccf22017-10-28 15:34:17 +080010860 ap_ctx->bss_stop_reason = BSS_STOP_DUE_TO_VENDOR_CONFIG_CHAN;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010861
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010862 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev,
Jeff Johnson91df29d2017-10-27 19:29:50 -070010863 ap_ctx->sap_config.channel,
10864 ap_ctx->sap_config.sec_ch,
10865 &ap_ctx->sap_config.ch_params);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010866
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080010867 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010868 }
10869
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +053010870 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
10871 uint32_t freq_len, i;
10872 uint32_t *freq;
10873 uint8_t chans[QDF_MAX_NUM_CHAN];
10874
10875 hdd_debug("setting mandatory freq/chan list");
10876
10877 freq_len = nla_len(
10878 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
10879 sizeof(uint32_t);
10880
10881 if (freq_len > QDF_MAX_NUM_CHAN) {
10882 hdd_err("insufficient space to hold channels");
10883 return -ENOMEM;
10884 }
10885
10886 freq = nla_data(
10887 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
10888
10889 hdd_debug("freq_len=%d", freq_len);
10890
10891 for (i = 0; i < freq_len; i++) {
10892 chans[i] = ieee80211_frequency_to_channel(freq[i]);
10893 hdd_debug("freq[%d]=%d", i, freq[i]);
10894 }
10895
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080010896 status = policy_mgr_set_sap_mandatory_channels(
10897 hdd_ctx->hdd_psoc, chans, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +053010898 if (QDF_IS_STATUS_ERROR(status))
10899 return -EINVAL;
10900 }
10901
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010902 return 0;
10903}
10904
10905/**
10906 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
10907 * @wiphy: wiphy structure pointer
10908 * @wdev: Wireless device structure pointer
10909 * @data: Pointer to the data received
10910 * @data_len: Length of @data
10911 *
10912 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
10913 * driver.
10914 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
10915 * will initiate restart of sap.
10916 *
10917 * Return: 0 on success; errno on failure
10918 */
10919static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
10920 struct wireless_dev *wdev,
10921 const void *data, int data_len)
10922{
10923 int ret;
10924
10925 cds_ssr_protect(__func__);
10926 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
10927 wdev, data, data_len);
10928 cds_ssr_unprotect(__func__);
10929
10930 return ret;
10931}
10932
Arun Khandavalli2476ef52016-04-26 20:19:43 +053010933#undef BPF_INVALID
10934#undef BPF_SET_RESET
10935#undef BPF_VERSION
10936#undef BPF_ID
10937#undef BPF_PACKET_SIZE
10938#undef BPF_CURRENT_OFFSET
10939#undef BPF_PROGRAM
10940#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010941
10942/**
10943 * define short names for the global vendor params
10944 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
10945 */
10946#define PARAM_TOTAL_CMD_EVENT_WAKE \
10947 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
10948#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
10949 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
10950#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
10951 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
10952#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
10953 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
10954#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
10955 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
10956#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
10957 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
10958#define PARAM_TOTAL_RX_DATA_WAKE \
10959 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
10960#define PARAM_RX_UNICAST_CNT \
10961 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
10962#define PARAM_RX_MULTICAST_CNT \
10963 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
10964#define PARAM_RX_BROADCAST_CNT \
10965 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
10966#define PARAM_ICMP_PKT \
10967 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
10968#define PARAM_ICMP6_PKT \
10969 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
10970#define PARAM_ICMP6_RA \
10971 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
10972#define PARAM_ICMP6_NA \
10973 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
10974#define PARAM_ICMP6_NS \
10975 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
10976#define PARAM_ICMP4_RX_MULTICAST_CNT \
10977 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
10978#define PARAM_ICMP6_RX_MULTICAST_CNT \
10979 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
10980#define PARAM_OTHER_RX_MULTICAST_CNT \
10981 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +053010982#define PARAM_RSSI_BREACH_CNT \
10983 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
10984#define PARAM_LOW_RSSI_CNT \
10985 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
10986#define PARAM_GSCAN_CNT \
10987 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
10988#define PARAM_PNO_COMPLETE_CNT \
10989 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
10990#define PARAM_PNO_MATCH_CNT \
10991 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
10992
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010993
10994
10995/**
10996 * hdd_send_wakelock_stats() - API to send wakelock stats
10997 * @ctx: context to be passed to callback
10998 * @data: data passed to callback
10999 *
11000 * This function is used to send wake lock stats to HAL layer
11001 *
11002 * Return: 0 on success, error number otherwise.
11003 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011004static uint32_t hdd_send_wakelock_stats(struct hdd_context *hdd_ctx,
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011005 const struct sir_wake_lock_stats *data)
11006{
11007 struct sk_buff *skb;
11008 uint32_t nl_buf_len;
11009 uint32_t total_rx_data_wake, rx_multicast_cnt;
11010 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +053011011 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011012
Dustin Brown491d54b2018-03-14 12:39:11 -070011013 hdd_enter();
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011014
11015 nl_buf_len = NLMSG_HDRLEN;
11016 nl_buf_len +=
11017 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
11018 (NLMSG_HDRLEN + sizeof(uint32_t));
11019
11020 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
11021
11022 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -070011023 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011024 return -ENOMEM;
11025 }
11026
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011027 hdd_debug("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011028 data->wow_ucast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011029 hdd_debug("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011030 data->wow_bcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011031 hdd_debug("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011032 data->wow_ipv4_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011033 hdd_debug("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011034 data->wow_ipv6_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011035 hdd_debug("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011036 data->wow_ipv6_mcast_ra_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011037 hdd_debug("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011038 data->wow_ipv6_mcast_ns_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011039 hdd_debug("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011040 data->wow_ipv6_mcast_na_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011041 hdd_debug("wow_icmpv4_count %d", data->wow_icmpv4_count);
11042 hdd_debug("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +053011043 data->wow_icmpv6_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011044 hdd_debug("wow_rssi_breach_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +053011045 data->wow_rssi_breach_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011046 hdd_debug("wow_low_rssi_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +053011047 data->wow_low_rssi_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011048 hdd_debug("wow_gscan_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +053011049 data->wow_gscan_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011050 hdd_debug("wow_pno_complete_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +053011051 data->wow_pno_complete_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011052 hdd_debug("wow_pno_match_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +053011053 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011054
11055 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +053011056 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011057
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +053011058 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +053011059 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +053011060
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011061 rx_multicast_cnt =
11062 data->wow_ipv4_mcast_wake_up_count +
11063 ipv6_rx_multicast_addr_cnt;
11064
11065 total_rx_data_wake =
11066 data->wow_ucast_wake_up_count +
11067 data->wow_bcast_wake_up_count +
11068 rx_multicast_cnt;
11069
11070 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
11071 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
11072 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
11073 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
11074 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
11075 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
11076 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
11077 total_rx_data_wake) ||
11078 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
11079 data->wow_ucast_wake_up_count) ||
11080 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
11081 rx_multicast_cnt) ||
11082 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
11083 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +053011084 nla_put_u32(skb, PARAM_ICMP_PKT,
11085 data->wow_icmpv4_count) ||
11086 nla_put_u32(skb, PARAM_ICMP6_PKT,
11087 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011088 nla_put_u32(skb, PARAM_ICMP6_RA,
11089 data->wow_ipv6_mcast_ra_stats) ||
11090 nla_put_u32(skb, PARAM_ICMP6_NA,
11091 data->wow_ipv6_mcast_na_stats) ||
11092 nla_put_u32(skb, PARAM_ICMP6_NS,
11093 data->wow_ipv6_mcast_ns_stats) ||
11094 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
11095 data->wow_ipv4_mcast_wake_up_count) ||
11096 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
11097 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +053011098 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
11099 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
11100 data->wow_rssi_breach_wake_up_count) ||
11101 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
11102 data->wow_low_rssi_wake_up_count) ||
11103 nla_put_u32(skb, PARAM_GSCAN_CNT,
11104 data->wow_gscan_wake_up_count) ||
11105 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
11106 data->wow_pno_complete_wake_up_count) ||
11107 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
11108 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -070011109 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011110 goto nla_put_failure;
11111 }
11112
11113 cfg80211_vendor_cmd_reply(skb);
11114
Dustin Browne74003f2018-03-14 12:51:58 -070011115 hdd_exit();
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011116 return 0;
11117
11118nla_put_failure:
11119 kfree_skb(skb);
11120 return -EINVAL;
11121}
11122
11123/**
11124 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
11125 * @wiphy: wiphy pointer
11126 * @wdev: pointer to struct wireless_dev
11127 * @data: pointer to incoming NL vendor data
11128 * @data_len: length of @data
11129 *
11130 * This function parses the incoming NL vendor command data attributes and
11131 * invokes the SME Api and blocks on a completion variable.
11132 * WMA copies required data and invokes callback
11133 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
11134 *
11135 * Return: 0 on success; error number otherwise.
11136 */
11137static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
11138 struct wireless_dev *wdev,
11139 const void *data,
11140 int data_len)
11141{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011142 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011143 int status, ret;
11144 struct sir_wake_lock_stats wake_lock_stats;
11145 QDF_STATUS qdf_status;
11146
Dustin Brown491d54b2018-03-14 12:39:11 -070011147 hdd_enter();
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011148
11149 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -070011150 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011151 return -EINVAL;
11152 }
11153
11154 status = wlan_hdd_validate_context(hdd_ctx);
11155 if (0 != status)
11156 return -EINVAL;
11157
11158 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
11159 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -070011160 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011161 return -EINVAL;
11162 }
11163
11164 ret = hdd_send_wakelock_stats(hdd_ctx,
11165 &wake_lock_stats);
11166 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -070011167 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011168
Dustin Browne74003f2018-03-14 12:51:58 -070011169 hdd_exit();
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011170 return ret;
11171}
11172
11173/**
11174 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
11175 * @wiphy: wiphy pointer
11176 * @wdev: pointer to struct wireless_dev
11177 * @data: pointer to incoming NL vendor data
11178 * @data_len: length of @data
11179 *
11180 * This function parses the incoming NL vendor command data attributes and
11181 * invokes the SME Api and blocks on a completion variable.
11182 * WMA copies required data and invokes callback
11183 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
11184 *
11185 * Return: 0 on success; error number otherwise.
11186 */
11187static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
11188 struct wireless_dev *wdev,
11189 const void *data, int data_len)
11190{
11191 int ret;
11192
11193 cds_ssr_protect(__func__);
11194 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
11195 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -070011196 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053011197
11198 return ret;
11199}
11200
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011201/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011202 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
11203 * @wiphy: wiphy structure pointer
11204 * @wdev: Wireless device structure pointer
11205 * @data: Pointer to the data received
11206 * @data_len: Length of @data
11207 *
11208 * This function reads wmi max bus size and fill in the skb with
11209 * NL attributes and send up the NL event.
11210 * Return: 0 on success; errno on failure
11211 */
11212static int
11213__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
11214 struct wireless_dev *wdev,
11215 const void *data, int data_len)
11216{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011217 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011218 int ret_val;
11219 struct sk_buff *skb;
11220 uint32_t nl_buf_len;
11221
Dustin Brown491d54b2018-03-14 12:39:11 -070011222 hdd_enter();
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011223
11224 ret_val = wlan_hdd_validate_context(hdd_ctx);
11225 if (ret_val)
11226 return ret_val;
11227
11228 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
11229 hdd_err("Command not allowed in FTM mode");
11230 return -EINVAL;
11231 }
11232
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011233 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011234
11235 nl_buf_len = NLMSG_HDRLEN;
11236 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
11237
11238 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
11239 if (!skb) {
11240 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
11241 return -ENOMEM;
11242 }
11243
11244 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
11245 hdd_ctx->wmi_max_len)) {
11246 hdd_err("nla put failure");
11247 goto nla_put_failure;
11248 }
11249
11250 cfg80211_vendor_cmd_reply(skb);
11251
Dustin Browne74003f2018-03-14 12:51:58 -070011252 hdd_exit();
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053011253
11254 return 0;
11255
11256nla_put_failure:
11257 kfree_skb(skb);
11258 return -EINVAL;
11259}
11260
11261/**
11262 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
11263 * @wiphy: wiphy structure pointer
11264 * @wdev: Wireless device structure pointer
11265 * @data: Pointer to the data received
11266 * @data_len: Length of @data
11267 *
11268 * Return: 0 on success; errno on failure
11269 */
11270static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
11271 struct wireless_dev *wdev,
11272 const void *data, int data_len)
11273{
11274 int ret;
11275
11276 cds_ssr_protect(__func__);
11277 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
11278 cds_ssr_unprotect(__func__);
11279
11280 return ret;
11281}
11282
11283/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011284 *__wlan_hdd_cfg80211_setband() - set band
11285 * @wiphy: Pointer to wireless phy
11286 * @wdev: Pointer to wireless device
11287 * @data: Pointer to data
11288 * @data_len: Length of @data
11289 *
11290 * Return: 0 on success, negative errno on failure
11291 */
11292static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
11293 struct wireless_dev *wdev,
11294 const void *data, int data_len)
11295{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011296 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -070011297 struct net_device *dev = wdev->netdev;
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011298 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
11299 int ret;
11300 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
11301 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
11302
Dustin Brown491d54b2018-03-14 12:39:11 -070011303 hdd_enter();
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011304
11305 ret = wlan_hdd_validate_context(hdd_ctx);
11306 if (ret)
11307 return ret;
11308
Dustin Brown4ea21db2018-01-05 14:13:17 -080011309 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX,
11310 data, data_len, policy)) {
Dustin Brownbacc48f2018-03-14 14:48:44 -070011311 hdd_err("Invalid ATTR");
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011312 return -EINVAL;
11313 }
11314
11315 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
Dustin Brownbacc48f2018-03-14 14:48:44 -070011316 hdd_err("attr SETBAND_VALUE failed");
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011317 return -EINVAL;
11318 }
11319
Kiran Kumar Lokereb1d412e2017-04-23 17:19:43 -070011320 ret = hdd_reg_set_band(dev,
11321 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011322
Dustin Browne74003f2018-03-14 12:51:58 -070011323 hdd_exit();
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011324 return ret;
11325}
11326
11327/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011328 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
11329 * @adapter: hdd adapter
11330 * @channel: channel number
11331 *
11332 * return: QDF status based on success or failure
11333 */
Jeff Johnsone5006672017-08-29 14:39:02 -070011334static QDF_STATUS wlan_hdd_validate_acs_channel(struct hdd_adapter *adapter,
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011335 int channel, int chan_bw)
11336{
11337 if (QDF_STATUS_SUCCESS !=
11338 wlan_hdd_validate_operation_channel(adapter, channel))
11339 return QDF_STATUS_E_FAILURE;
11340 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
11341 channel,
11342 PHY_SINGLE_CHANNEL_CENTERED))) {
Dustin Brown5e89ef82018-03-14 11:50:23 -070011343 hdd_info("channel %d is in nol", channel);
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011344 return -EINVAL;
11345 }
11346
11347 if ((wlansap_is_channel_leaking_in_nol(
11348 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
11349 channel, chan_bw))) {
Dustin Brown5e89ef82018-03-14 11:50:23 -070011350 hdd_info("channel %d is leaking in nol", channel);
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011351 return -EINVAL;
11352 }
11353
11354 return 0;
11355
11356}
11357
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011358static void hdd_update_acs_sap_config(struct hdd_context *hdd_ctx,
Kapil Gupta8878ad92017-02-13 11:56:04 +053011359 tsap_Config_t *sap_config,
11360 struct hdd_vendor_chan_info *channel_list)
11361{
11362 sap_config->channel = channel_list->pri_ch;
11363
11364 sap_config->ch_params.center_freq_seg0 =
11365 channel_list->vht_seg0_center_ch;
11366 sap_config->ch_params.center_freq_seg1 =
11367 channel_list->vht_seg1_center_ch;
11368
11369 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
11370 sap_config->ch_params.ch_width = channel_list->chan_width;
11371 if (sap_config->channel >= 36)
11372 sap_config->ch_width_orig =
11373 hdd_ctx->config->vhtChannelWidth;
11374 else
11375 sap_config->ch_width_orig =
11376 hdd_ctx->config->nChannelBondingMode24GHz ?
11377 eHT_CHANNEL_WIDTH_40MHZ :
11378 eHT_CHANNEL_WIDTH_20MHZ;
11379
11380 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
11381 sap_config->acs_cfg.ch_width = channel_list->chan_width;
11382 sap_config->acs_cfg.vht_seg0_center_ch =
11383 channel_list->vht_seg0_center_ch;
11384 sap_config->acs_cfg.vht_seg1_center_ch =
11385 channel_list->vht_seg1_center_ch;
11386 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
11387}
11388
Jeff Johnsone5006672017-08-29 14:39:02 -070011389static int hdd_update_acs_channel(struct hdd_adapter *adapter, uint8_t reason,
Kapil Gupta8878ad92017-02-13 11:56:04 +053011390 uint8_t channel_cnt,
11391 struct hdd_vendor_chan_info *channel_list)
11392{
11393 tsap_Config_t *sap_config;
Jeff Johnson87251032017-08-29 13:31:11 -070011394 struct hdd_ap_ctx *hdd_ap_ctx;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011395 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011396 QDF_STATUS status = QDF_STATUS_SUCCESS;
11397
Min Liuab6ed4f2018-01-09 13:13:57 +080011398 if (!channel_list) {
11399 hdd_err("channel_list is NULL");
11400 return -EINVAL;
11401 }
11402
Kapil Gupta8878ad92017-02-13 11:56:04 +053011403 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
Jeff Johnsonb9424862017-10-30 08:49:35 -070011404 sap_config = &adapter->session.ap.sap_config;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011405
11406 if (QDF_TIMER_STATE_RUNNING ==
Jeff Johnsonb9424862017-10-30 08:49:35 -070011407 qdf_mc_timer_get_current_state(&adapter->session.
Kapil Gupta8878ad92017-02-13 11:56:04 +053011408 ap.vendor_acs_timer)) {
Jeff Johnsonb9424862017-10-30 08:49:35 -070011409 qdf_mc_timer_stop(&adapter->session.ap.vendor_acs_timer);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011410 }
11411
Min Liuab6ed4f2018-01-09 13:13:57 +080011412 if (channel_list->pri_ch == 0) {
Kapil Gupta8878ad92017-02-13 11:56:04 +053011413 /* Check mode, set default channel */
11414 channel_list->pri_ch = 6;
11415 /*
11416 * sap_select_default_oper_chan(hdd_ctx->hHal,
11417 * sap_config->acs_cfg.hw_mode);
11418 */
11419 }
11420
11421 switch (reason) {
11422 /* SAP init case */
11423 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
11424 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
11425 /* Update Hostapd */
11426 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
11427 break;
11428
11429 /* DFS detected on current channel */
11430 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
11431 wlan_sap_update_next_channel(
11432 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
11433 channel_list->pri_ch,
11434 channel_list->chan_width);
11435 status = sme_update_new_channel_event(
11436 WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -070011437 adapter->session_id);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011438 break;
11439
11440 /* LTE coex event on current channel */
11441 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
11442 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
11443 sap_config->acs_cfg.ch_width = channel_list->chan_width;
Jeff Johnson91df29d2017-10-27 19:29:50 -070011444 hdd_ap_ctx->sap_config.ch_width_orig =
Kapil Gupta8878ad92017-02-13 11:56:04 +053011445 channel_list->chan_width;
Min Liu2fef5792018-01-19 17:59:42 +080011446 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch,
11447 true);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011448 break;
11449
11450 default:
11451 hdd_info("invalid reason for timer invoke");
11452 }
Dustin Browne74003f2018-03-14 12:51:58 -070011453 hdd_exit();
Min Liuab6ed4f2018-01-09 13:13:57 +080011454 return qdf_status_to_os_return(status);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011455}
11456
11457/**
11458 * Define short name for vendor channel set config
11459 */
11460#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
Kapil Gupta8878ad92017-02-13 11:56:04 +053011461#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
11462#define SET_CHAN_PRIMARY_CHANNEL \
11463 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
11464#define SET_CHAN_SECONDARY_CHANNEL \
11465 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
11466#define SET_CHAN_SEG0_CENTER_CHANNEL \
11467 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
11468#define SET_CHAN_SEG1_CENTER_CHANNEL \
11469 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
11470#define SET_CHAN_CHANNEL_WIDTH \
11471 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
11472#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
Kapil Gupta63e75282017-05-18 20:55:10 +053011473#define SET_EXT_ACS_BAND QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_BAND
Kapil Gupta8878ad92017-02-13 11:56:04 +053011474
11475/**
11476 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
11477 * @channel_list: pointer to hdd_vendor_chan_info
11478 * @reason: channel change reason
11479 * @channel_cnt: channel count
11480 * @data: data
11481 * @data_len: data len
11482 *
11483 * Return: 0 on success, negative errno on failure
11484 */
11485static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
11486 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
11487 const void *data, int data_len)
11488{
11489 int rem, i = 0;
11490 struct nlattr *tb[SET_CHAN_MAX + 1];
11491 struct nlattr *tb2[SET_CHAN_MAX + 1];
11492 struct nlattr *curr_attr;
11493 struct hdd_vendor_chan_info *channel_list;
11494
Dustin Brown4ea21db2018-01-05 14:13:17 -080011495 if (wlan_cfg80211_nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
Kapil Gupta8878ad92017-02-13 11:56:04 +053011496 hdd_err("Invalid ATTR");
11497 return -EINVAL;
11498 }
11499
11500 if (tb[SET_CHAN_REASON])
11501 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
11502
Kapil Gupta63e75282017-05-18 20:55:10 +053011503 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem)
11504 i++;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011505
Kapil Gupta63e75282017-05-18 20:55:10 +053011506 *channel_cnt = i;
11507
11508 if (i == 0)
11509 hdd_err("incorrect channel count");
Kapil Gupta8878ad92017-02-13 11:56:04 +053011510
11511 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
11512 (*channel_cnt));
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011513 if (NULL == channel_list) {
11514 hdd_err("Could not allocate for channel_list");
11515 return -ENOMEM;
11516 }
Kapil Gupta8878ad92017-02-13 11:56:04 +053011517
Kapil Gupta63e75282017-05-18 20:55:10 +053011518 i = 0;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011519 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
Dustin Brown4ea21db2018-01-05 14:13:17 -080011520 if (wlan_cfg80211_nla_parse(tb2, SET_CHAN_MAX,
11521 nla_data(curr_attr),
11522 nla_len(curr_attr), NULL)) {
11523 hdd_err("nla_parse failed");
Kapil Gupta8878ad92017-02-13 11:56:04 +053011524 return -EINVAL;
11525 }
Kapil Gupta63e75282017-05-18 20:55:10 +053011526 if (tb2[SET_EXT_ACS_BAND]) {
11527 channel_list[i].band =
11528 nla_get_u8(tb2[SET_EXT_ACS_BAND]);
11529 }
Kapil Gupta8878ad92017-02-13 11:56:04 +053011530 /* Parse and Fetch allowed SSID list*/
11531 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
11532 channel_list[i].pri_ch =
11533 nla_get_u8(
11534 tb2[SET_CHAN_PRIMARY_CHANNEL]);
11535 }
11536 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
11537 channel_list[i].ht_sec_ch =
11538 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
11539 }
11540 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
11541 channel_list[i].vht_seg0_center_ch =
11542 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
11543 }
11544 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
11545 channel_list[i].vht_seg1_center_ch =
11546 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
11547 }
11548 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
11549 channel_list[i].chan_width =
11550 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
11551 }
Kapil Gupta63e75282017-05-18 20:55:10 +053011552 hdd_debug("index %d pri %d sec %d seg0 %d seg1 %d width %d",
Kapil Gupta8878ad92017-02-13 11:56:04 +053011553 i, channel_list[i].pri_ch,
11554 channel_list[i].ht_sec_ch,
11555 channel_list[i].vht_seg0_center_ch,
11556 channel_list[i].vht_seg1_center_ch,
11557 channel_list[i].chan_width);
11558 i++;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011559 }
11560 *chan_list_ptr = channel_list;
11561
11562 return 0;
11563}
11564
11565/**
11566 * Undef short names for vendor set channel configuration
11567 */
11568#undef SET_CHAN_REASON
11569#undef SET_CHAN_CHANNEL_COUNT
11570#undef SET_CHAN_CHAN_LIST
11571#undef SET_CHAN_PRIMARY_CHANNEL
11572#undef SET_CHAN_SECONDARY_CHANNEL
11573#undef SET_CHAN_SEG0_CENTER_CHANNEL
11574#undef SET_CHAN_SEG1_CENTER_CHANNEL
11575#undef SET_CHAN_CHANNEL_WIDTH
11576#undef SET_CHAN_MAX
11577
11578/**
11579 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
11580 * @wiphy: Pointer to wireless phy
11581 * @wdev: Pointer to wireless device
11582 * @data: Pointer to data
11583 * @data_len: Length of @data
11584 *
11585 * Return: 0 on success, negative errno on failure
11586 */
11587static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
11588 struct wireless_dev *wdev,
11589 const void *data, int data_len)
11590{
11591 int ret_val;
11592 QDF_STATUS qdf_status;
11593 uint8_t channel_cnt = 0, reason = -1;
11594 struct hdd_vendor_chan_info *channel_list = NULL;
Jeff Johnsone5006672017-08-29 14:39:02 -070011595 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070011596 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011597 struct hdd_vendor_chan_info *channel_list_ptr;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011598
Dustin Brown491d54b2018-03-14 12:39:11 -070011599 hdd_enter();
Kapil Gupta8878ad92017-02-13 11:56:04 +053011600
11601 ret_val = wlan_hdd_validate_context(hdd_ctx);
11602 if (ret_val)
11603 return ret_val;
11604
11605 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
11606 hdd_err("Command not allowed in FTM mode");
11607 return -EINVAL;
11608 }
11609
11610 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
11611 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
11612 else {
11613 hdd_err("already timeout happened for acs");
11614 return -EINVAL;
11615 }
11616
11617 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
11618 &channel_cnt, data, data_len);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011619 channel_list_ptr = channel_list;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011620 if (ret_val)
11621 return ret_val;
11622
11623 /* Validate channel to be set */
11624 while (channel_cnt && channel_list) {
11625 qdf_status = wlan_hdd_validate_acs_channel(adapter,
11626 channel_list->pri_ch,
11627 channel_list->chan_width);
11628 if (qdf_status == QDF_STATUS_SUCCESS)
11629 break;
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011630 else if (channel_cnt == 1) {
11631 hdd_err("invalid channel %d received from app",
11632 channel_list->pri_ch);
11633 channel_list->pri_ch = 0;
11634 break;
11635 }
11636
Kapil Gupta8878ad92017-02-13 11:56:04 +053011637 channel_cnt--;
11638 channel_list++;
11639 }
Min Liuab6ed4f2018-01-09 13:13:57 +080011640
Kapil Gupta8878ad92017-02-13 11:56:04 +053011641 if ((channel_cnt <= 0) || !channel_list) {
Jeff Johnson36e74c42017-09-18 08:15:42 -070011642 hdd_err("no available channel/chanlist %d/%pK", channel_cnt,
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011643 channel_list);
11644 qdf_mem_free(channel_list_ptr);
Kapil Gupta8878ad92017-02-13 11:56:04 +053011645 return -EINVAL;
11646 }
11647
Min Liuab6ed4f2018-01-09 13:13:57 +080011648 hdd_debug("received primary channel as %d", channel_list->pri_ch);
11649
11650 ret_val = hdd_update_acs_channel(adapter, reason,
Kapil Gupta8878ad92017-02-13 11:56:04 +053011651 channel_cnt, channel_list);
Nachiket Kukadec3f92f72017-08-07 17:04:50 +053011652 qdf_mem_free(channel_list_ptr);
Min Liuab6ed4f2018-01-09 13:13:57 +080011653 return ret_val;
Kapil Gupta8878ad92017-02-13 11:56:04 +053011654}
11655
11656/**
11657 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
11658 * @wiphy: Pointer to wireless phy
11659 * @wdev: Pointer to wireless device
11660 * @data: Pointer to data
11661 * @data_len: Length of @data
11662 *
11663 * Return: 0 on success, negative errno on failure
11664 */
11665static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
11666 struct wireless_dev *wdev,
11667 const void *data, int data_len)
11668{
11669 int ret;
11670
11671 cds_ssr_protect(__func__);
11672 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
11673 data_len);
11674 cds_ssr_protect(__func__);
11675
11676 return ret;
11677}
Kapil Gupta94ca6f62016-12-11 18:43:12 +053011678
11679/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053011680 * wlan_hdd_cfg80211_setband() - Wrapper to setband
11681 * @wiphy: wiphy structure pointer
11682 * @wdev: Wireless device structure pointer
11683 * @data: Pointer to the data received
11684 * @data_len: Length of @data
11685 *
11686 * Return: 0 on success; errno on failure
11687 */
11688static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
11689 struct wireless_dev *wdev,
11690 const void *data, int data_len)
11691{
11692 int ret;
11693
11694 cds_ssr_protect(__func__);
11695 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
11696 cds_ssr_unprotect(__func__);
11697
11698 return ret;
11699}
11700
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011701/**
11702 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
11703 * @nl80211_value: Vendor command attribute value
11704 * @wmi_value: Pointer to return converted WMI return value
11705 *
11706 * Convert NL80211 vendor command value for SAR limit set to WMI value
11707 * Return: 0 on success, -1 on invalid value
11708 */
11709static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
11710 u32 *wmi_value)
11711{
11712 int ret = 0;
11713
11714 switch (nl80211_value) {
11715 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
11716 *wmi_value = WMI_SAR_FEATURE_OFF;
11717 break;
11718 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
11719 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
11720 break;
11721 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
11722 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
11723 break;
11724 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
11725 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
11726 break;
11727 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
11728 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
11729 break;
11730 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
11731 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
11732 break;
11733 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
11734 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
11735 break;
11736 default:
11737 ret = -1;
11738 }
11739 return ret;
11740}
11741
11742/**
11743 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
11744 * @nl80211_value: Vendor command attribute value
11745 * @wmi_value: Pointer to return converted WMI return value
11746 *
11747 * Convert NL80211 vendor command value for SAR BAND to WMI value
11748 * Return: 0 on success, -1 on invalid value
11749 */
11750static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
11751{
11752 int ret = 0;
11753
11754 switch (nl80211_value) {
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070011755 case HDD_NL80211_BAND_2GHZ:
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011756 *wmi_value = WMI_SAR_2G_ID;
11757 break;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070011758 case HDD_NL80211_BAND_5GHZ:
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011759 *wmi_value = WMI_SAR_5G_ID;
11760 break;
11761 default:
11762 ret = -1;
11763 }
11764 return ret;
11765}
11766
11767/**
11768 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
11769 * @nl80211_value: Vendor command attribute value
11770 * @wmi_value: Pointer to return converted WMI return value
11771 *
11772 * Convert NL80211 vendor command value for SAR Modulation to WMI value
11773 * Return: 0 on success, -1 on invalid value
11774 */
11775static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
11776 u32 *wmi_value)
11777{
11778 int ret = 0;
11779
11780 switch (nl80211_value) {
11781 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
11782 *wmi_value = WMI_SAR_MOD_CCK;
11783 break;
11784 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
11785 *wmi_value = WMI_SAR_MOD_OFDM;
11786 break;
11787 default:
11788 ret = -1;
11789 }
11790 return ret;
11791}
11792
Jeff Johnson8c83f132017-12-18 16:41:37 -080011793static u32 hdd_sar_wmi_to_nl_enable(uint32_t wmi_value)
11794{
11795 switch (wmi_value) {
11796 default:
11797 case WMI_SAR_FEATURE_OFF:
11798 return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE;
11799 case WMI_SAR_FEATURE_ON_SET_0:
11800 return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0;
11801 case WMI_SAR_FEATURE_ON_SET_1:
11802 return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1;
11803 case WMI_SAR_FEATURE_ON_SET_2:
11804 return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2;
11805 case WMI_SAR_FEATURE_ON_SET_3:
11806 return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3;
11807 case WMI_SAR_FEATURE_ON_SET_4:
11808 return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4;
11809 case WMI_SAR_FEATURE_ON_USER_DEFINED:
11810 return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER;
11811 }
11812}
11813
11814static u32 hdd_sar_wmi_to_nl_band(uint32_t wmi_value)
11815{
11816 switch (wmi_value) {
11817 default:
11818 case WMI_SAR_2G_ID:
11819 return HDD_NL80211_BAND_2GHZ;
11820 case WMI_SAR_5G_ID:
11821 return HDD_NL80211_BAND_5GHZ;
11822 }
11823}
11824
11825static u32 hdd_sar_wmi_to_nl_modulation(uint32_t wmi_value)
11826{
11827 switch (wmi_value) {
11828 default:
11829 case WMI_SAR_MOD_CCK:
11830 return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK;
11831 case WMI_SAR_MOD_OFDM:
11832 return QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM;
11833 }
11834}
11835
Jeff Johnsonb17a93c2017-06-02 12:26:55 -070011836static const struct nla_policy
11837sar_limits_policy[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1] = {
11838 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE] = {.type = NLA_U32},
11839 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS] = {.type = NLA_U32},
11840 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND] = {.type = NLA_U32},
11841 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN] = {.type = NLA_U32},
11842 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION] = {.type = NLA_U32},
11843 [QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT] = {.type = NLA_U32},
11844};
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080011845
Jeff Johnson8c83f132017-12-18 16:41:37 -080011846#define WLAN_WAIT_TIME_SAR 5000
11847
11848/**
11849 * hdd_sar_context - hdd sar context
11850 * @event: sar limit event
11851 */
11852struct hdd_sar_context {
11853 struct sar_limit_event event;
11854};
11855
11856/**
11857 * hdd_sar_cb () - sar response message handler
11858 * @cookie: hdd request cookie
11859 * @event: sar response event
11860 *
11861 * Return: none
11862 */
11863static void hdd_sar_cb(void *cookie,
11864 struct sar_limit_event *event)
11865{
11866 struct hdd_request *request;
11867 struct hdd_sar_context *context;
11868
Dustin Brown491d54b2018-03-14 12:39:11 -070011869 hdd_enter();
Jeff Johnson8c83f132017-12-18 16:41:37 -080011870
11871 if (!event) {
11872 hdd_err("response is NULL");
11873 return;
11874 }
11875
11876 request = hdd_request_get(cookie);
11877 if (!request) {
11878 hdd_debug("Obsolete request");
11879 return;
11880 }
11881
11882 context = hdd_request_priv(request);
11883 context->event = *event;
11884 hdd_request_complete(request);
11885 hdd_request_put(request);
11886
Dustin Browne74003f2018-03-14 12:51:58 -070011887 hdd_exit();
Jeff Johnson8c83f132017-12-18 16:41:37 -080011888}
11889
11890static uint32_t hdd_sar_get_response_len(const struct sar_limit_event *event)
11891{
11892 uint32_t len;
11893 uint32_t row_len;
11894
11895 len = NLMSG_HDRLEN;
11896 /* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE */
11897 len += NLA_HDRLEN + sizeof(u32);
11898 /* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS */
11899 len += NLA_HDRLEN + sizeof(u32);
11900
11901 /* nest */
11902 row_len = NLA_HDRLEN;
11903 /* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND */
11904 row_len += NLA_HDRLEN + sizeof(u32);
11905 /* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN */
11906 row_len += NLA_HDRLEN + sizeof(u32);
11907 /* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION */
11908 row_len += NLA_HDRLEN + sizeof(u32);
11909 /* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT */
11910 row_len += NLA_HDRLEN + sizeof(u32);
11911
11912 /* QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC */
11913 len += NLA_HDRLEN + (row_len * event->num_limit_rows);
11914
11915 return len;
11916}
11917
11918static int hdd_sar_fill_response(struct sk_buff *skb,
11919 const struct sar_limit_event *event)
11920{
11921 int errno;
11922 u32 value;
11923 u32 attr;
11924 struct nlattr *nla_spec_attr;
11925 struct nlattr *nla_row_attr;
11926 uint32_t row;
11927 const struct sar_limit_event_row *event_row;
11928
11929 attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE;
11930 value = hdd_sar_wmi_to_nl_enable(event->sar_enable);
11931 errno = nla_put_u32(skb, attr, value);
11932 if (errno)
11933 return errno;
11934
11935 attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS;
11936 value = event->num_limit_rows;
11937 errno = nla_put_u32(skb, attr, value);
11938 if (errno)
11939 return errno;
11940
11941 attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC;
11942 nla_spec_attr = nla_nest_start(skb, attr);
11943 if (!nla_spec_attr)
11944 return -EINVAL;
11945
11946 for (row = 0, event_row = event->sar_limit_row;
11947 row < event->num_limit_rows;
11948 row++, event_row++) {
11949 nla_row_attr = nla_nest_start(skb, attr);
11950 if (!nla_row_attr)
11951 return -EINVAL;
11952
11953 attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND;
11954 value = hdd_sar_wmi_to_nl_band(event_row->band_id);
11955 errno = nla_put_u32(skb, attr, value);
11956 if (errno)
11957 return errno;
11958
11959 attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN;
11960 value = event_row->chain_id;
11961 errno = nla_put_u32(skb, attr, value);
11962 if (errno)
11963 return errno;
11964
11965 attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION;
11966 value = hdd_sar_wmi_to_nl_modulation(event_row->mod_id);
11967 errno = nla_put_u32(skb, attr, value);
11968 if (errno)
11969 return errno;
11970
11971 attr = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT;
11972 value = event_row->limit_value;
11973 errno = nla_put_u32(skb, attr, value);
11974 if (errno)
11975 return errno;
11976
11977 nla_nest_end(skb, nla_row_attr);
11978 }
11979 nla_nest_end(skb, nla_spec_attr);
11980
11981 return 0;
11982}
11983
11984static int hdd_sar_send_response(struct wiphy *wiphy,
11985 const struct sar_limit_event *event)
11986{
11987 uint32_t len;
11988 struct sk_buff *skb;
11989 int errno;
11990
11991 len = hdd_sar_get_response_len(event);
11992 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, len);
11993 if (!skb) {
11994 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
11995 return -ENOMEM;
11996 }
11997
11998 errno = hdd_sar_fill_response(skb, event);
11999 if (errno) {
12000 kfree_skb(skb);
12001 return errno;
12002 }
12003
12004 return cfg80211_vendor_cmd_reply(skb);
12005}
12006
12007/**
12008 * __wlan_hdd_get_sar_power_limits() - Get SAR power limits
12009 * @wiphy: Pointer to wireless phy
12010 * @wdev: Pointer to wireless device
12011 * @data: Pointer to data
12012 * @data_len: Length of @data
12013 *
12014 * This function is used to retrieve Specific Absorption Rate limit specs.
12015 *
12016 * Return: 0 on success, negative errno on failure
12017 */
12018static int __wlan_hdd_get_sar_power_limits(struct wiphy *wiphy,
12019 struct wireless_dev *wdev,
12020 const void *data, int data_len)
12021{
12022 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
12023 struct hdd_request *request;
12024 struct hdd_sar_context *context;
12025 void *cookie;
12026 QDF_STATUS status;
12027 int ret;
12028 static const struct hdd_request_params params = {
12029 .priv_size = sizeof(*context),
12030 .timeout_ms = WLAN_WAIT_TIME_SAR,
12031 };
12032
Dustin Brown491d54b2018-03-14 12:39:11 -070012033 hdd_enter();
Jeff Johnson8c83f132017-12-18 16:41:37 -080012034
12035 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
12036 hdd_err("Command not allowed in FTM mode");
12037 return -EPERM;
12038 }
12039
12040 if (wlan_hdd_validate_context(hdd_ctx))
12041 return -EINVAL;
12042
12043 request = hdd_request_alloc(&params);
12044 if (!request) {
12045 hdd_err("Request allocation failure");
12046 return -ENOMEM;
12047 }
12048
12049 cookie = hdd_request_cookie(request);
12050
12051 status = sme_get_sar_power_limits(hdd_ctx->hHal, hdd_sar_cb, cookie);
12052 if (!QDF_IS_STATUS_SUCCESS(status)) {
12053 hdd_err("Unable to post sar message");
12054 ret = -EINVAL;
12055 goto cleanup;
12056 }
12057
12058 ret = hdd_request_wait_for_response(request);
12059 if (ret) {
12060 hdd_err("Target response timed out");
12061 goto cleanup;
12062 }
12063
12064 context = hdd_request_priv(request);
12065 ret = hdd_sar_send_response(wiphy, &context->event);
12066
12067cleanup:
12068 hdd_request_put(request);
12069
12070 return ret;
12071}
12072
12073/**
12074 * wlan_hdd_cfg80211_get_sar_power_limits() - Get SAR power limits
12075 * @wiphy: Pointer to wireless phy
12076 * @wdev: Pointer to wireless device
12077 * @data: Pointer to data
12078 * @data_len: Length of @data
12079 *
12080 * Wrapper function of __wlan_hdd_cfg80211_get_sar_power_limits()
12081 *
12082 * Return: 0 on success, negative errno on failure
12083 */
12084static int wlan_hdd_cfg80211_get_sar_power_limits(struct wiphy *wiphy,
12085 struct wireless_dev *wdev,
12086 const void *data,
12087 int data_len)
12088{
12089 int ret;
12090
12091 cds_ssr_protect(__func__);
12092 ret = __wlan_hdd_get_sar_power_limits(wiphy, wdev, data, data_len);
12093 cds_ssr_unprotect(__func__);
12094
12095 return ret;
12096}
12097
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012098/**
12099 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
12100 * @wiphy: Pointer to wireless phy
12101 * @wdev: Pointer to wireless device
12102 * @data: Pointer to data
12103 * @data_len: Length of @data
12104 *
12105 * This function is used to setup Specific Absorption Rate limit specs.
12106 *
12107 * Return: 0 on success, negative errno on failure
12108 */
12109static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
12110 struct wireless_dev *wdev,
12111 const void *data, int data_len)
12112{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070012113 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012114 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
12115 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
12116 *sar_spec_list;
12117 struct sar_limit_cmd_params sar_limit_cmd = {0};
12118 int ret = -EINVAL, i = 0, rem = 0;
12119
Dustin Brown491d54b2018-03-14 12:39:11 -070012120 hdd_enter();
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012121
12122 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
12123 hdd_err("Command not allowed in FTM mode");
12124 return -EPERM;
12125 }
12126
12127 if (wlan_hdd_validate_context(hdd_ctx))
12128 return -EINVAL;
12129
Dustin Brown4ea21db2018-01-05 14:13:17 -080012130 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
12131 data, data_len, sar_limits_policy)) {
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012132 hdd_err("Invalid SAR attributes");
12133 return -EINVAL;
12134 }
12135
12136 /* Vendor command manadates all SAR Specs in single call */
12137 sar_limit_cmd.commit_limits = 1;
12138 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
12139 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
12140 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
12141 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
12142 &sar_limit_cmd.sar_enable) < 0) {
12143 hdd_err("Invalid SAR Enable attr");
12144 goto fail;
12145 }
12146 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012147 hdd_debug("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012148
12149 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
12150 sar_limit_cmd.num_limit_rows = nla_get_u32(
12151 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012152 hdd_debug("attr sar num_limit_rows %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012153 sar_limit_cmd.num_limit_rows);
12154 }
12155 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
12156 hdd_err("SAR Spec list exceed supported size");
12157 goto fail;
12158 }
12159 if (sar_limit_cmd.num_limit_rows == 0)
12160 goto send_sar_limits;
12161 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
12162 struct sar_limit_cmd_row) *
12163 sar_limit_cmd.num_limit_rows);
12164 if (!sar_limit_cmd.sar_limit_row_list) {
12165 ret = -ENOMEM;
12166 goto fail;
12167 }
12168 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
12169 hdd_err("Invalid SAR SPECs list");
12170 goto fail;
12171 }
12172
12173 nla_for_each_nested(sar_spec_list,
12174 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
12175 if (i == sar_limit_cmd.num_limit_rows) {
12176 hdd_warn("SAR Cmd has excess SPECs in list");
12177 break;
12178 }
12179
Dustin Brown4ea21db2018-01-05 14:13:17 -080012180 if (wlan_cfg80211_nla_parse(sar_spec,
12181 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
12182 nla_data(sar_spec_list),
12183 nla_len(sar_spec_list),
12184 sar_limits_policy)) {
12185 hdd_err("nla_parse failed for SAR Spec list");
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012186 goto fail;
12187 }
12188 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
12189 if (sar_spec[
12190 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
12191 sar_limit_cmd.sar_limit_row_list[i].limit_value =
12192 nla_get_u32(sar_spec[
12193 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
12194 } else {
12195 hdd_err("SAR Spec does not have power limit value");
12196 goto fail;
12197 }
12198
12199 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
12200 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
12201 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
12202 &sar_limit_cmd.sar_limit_row_list[i].band_id)
12203 < 0) {
12204 hdd_err("Invalid SAR Band attr");
12205 goto fail;
12206 }
12207 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
12208 WMI_SAR_BAND_ID_VALID_MASK;
12209 }
12210 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
12211 sar_limit_cmd.sar_limit_row_list[i].chain_id =
12212 nla_get_u32(sar_spec[
12213 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
12214 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
12215 WMI_SAR_CHAIN_ID_VALID_MASK;
12216 }
12217 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
12218 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
12219 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
12220 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
12221 < 0) {
12222 hdd_err("Invalid SAR Modulation attr");
12223 goto fail;
12224 }
12225 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
12226 WMI_SAR_MOD_ID_VALID_MASK;
12227 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012228 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080012229 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
12230 sar_limit_cmd.sar_limit_row_list[i].chain_id,
12231 sar_limit_cmd.sar_limit_row_list[i].mod_id,
12232 sar_limit_cmd.sar_limit_row_list[i].limit_value,
12233 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
12234 i++;
12235 }
12236
12237 if (i < sar_limit_cmd.num_limit_rows) {
12238 hdd_warn("SAR Cmd has less SPECs in list");
12239 sar_limit_cmd.num_limit_rows = i;
12240 }
12241
12242send_sar_limits:
12243 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
12244 QDF_STATUS_SUCCESS)
12245 ret = 0;
12246fail:
12247 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
12248 return ret;
12249}
12250
12251/**
12252 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
12253 * @wiphy: Pointer to wireless phy
12254 * @wdev: Pointer to wireless device
12255 * @data: Pointer to data
12256 * @data_len: Length of @data
12257 *
12258 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
12259 *
12260 * Return: 0 on success, negative errno on failure
12261 */
12262static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
12263 struct wireless_dev *wdev,
12264 const void *data,
12265 int data_len)
12266{
12267 int ret;
12268
12269 cds_ssr_protect(__func__);
12270 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
12271 data_len);
12272 cds_ssr_unprotect(__func__);
12273
12274 return ret;
12275}
12276
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012277static const struct
12278nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
12279 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
12280 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
12281 .len = QDF_MAC_ADDR_SIZE},
12282};
12283
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +053012284void wlan_hdd_rso_cmd_status_cb(void *ctx, struct rso_cmd_status *rso_status)
12285{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070012286 struct hdd_context *hdd_ctx = (struct hdd_context *)ctx;
Jeff Johnsone5006672017-08-29 14:39:02 -070012287 struct hdd_adapter *adapter;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +053012288
12289 adapter = hdd_get_adapter_by_vdev(hdd_ctx, rso_status->vdev_id);
12290 if (!adapter) {
12291 hdd_err("adapter NULL");
12292 return;
12293 }
12294
12295 adapter->lfr_fw_status.is_disabled = rso_status->status;
12296 complete(&adapter->lfr_fw_status.disable_lfr_event);
12297}
12298
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012299/**
12300 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
12301 * @wiphy: Pointer to wireless phy
12302 * @wdev: Pointer to wireless device
12303 * @data: Pointer to data
12304 * @data_len: Length of @data
12305 *
12306 * This function is used to enable/disable roaming using vendor commands
12307 *
12308 * Return: 0 on success, negative errno on failure
12309 */
12310static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
12311 struct wireless_dev *wdev,
12312 const void *data, int data_len)
12313{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070012314 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012315 struct net_device *dev = wdev->netdev;
Jeff Johnsone5006672017-08-29 14:39:02 -070012316 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012317 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
Abhishek Singh1f217ec2017-12-22 11:48:27 +053012318 uint32_t is_fast_roam_enabled;
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012319 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +053012320 QDF_STATUS qdf_status;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +053012321 unsigned long rc;
Jeff Johnson40dae4e2017-08-29 14:00:25 -070012322 struct hdd_station_ctx *hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012323
Dustin Brownfdf17c12018-03-14 12:55:34 -070012324 hdd_enter_dev(dev);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012325
12326 ret = wlan_hdd_validate_context(hdd_ctx);
12327 if (0 != ret)
12328 return ret;
12329
12330 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
12331 hdd_err("Command not allowed in FTM mode");
12332 return -EINVAL;
12333 }
12334
Dustin Brown4ea21db2018-01-05 14:13:17 -080012335 ret = wlan_cfg80211_nla_parse(tb,
12336 QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
12337 qca_wlan_vendor_attr);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012338 if (ret) {
12339 hdd_err("Invalid ATTR");
12340 return -EINVAL;
12341 }
12342
12343 /* Parse and fetch Enable flag */
12344 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
12345 hdd_err("attr enable failed");
12346 return -EINVAL;
12347 }
12348
12349 is_fast_roam_enabled = nla_get_u32(
12350 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Abhishek Singh1f217ec2017-12-22 11:48:27 +053012351 hdd_debug("isFastRoamEnabled %d", is_fast_roam_enabled);
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012352
12353 /* Update roaming */
Jeff Johnson1b780e42017-10-31 14:11:45 -070012354 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->session_id,
Abhishek Singh1f217ec2017-12-22 11:48:27 +053012355 is_fast_roam_enabled);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +053012356 if (qdf_status != QDF_STATUS_SUCCESS)
12357 hdd_err("sme_config_fast_roaming failed with status=%d",
12358 qdf_status);
12359 ret = qdf_status_to_os_return(qdf_status);
12360
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +053012361 if (eConnectionState_Associated == hdd_sta_ctx->conn_info.connState &&
Abhishek Singh1f217ec2017-12-22 11:48:27 +053012362 QDF_IS_STATUS_SUCCESS(qdf_status) && !is_fast_roam_enabled) {
Selvaraj, Sridhar4c7411e2017-05-04 12:58:41 +053012363
12364 INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +053012365 /*
12366 * wait only for LFR disable in fw as LFR enable
12367 * is always success
12368 */
12369 rc = wait_for_completion_timeout(
12370 &adapter->lfr_fw_status.disable_lfr_event,
12371 msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
12372 if (!rc) {
12373 hdd_err("Timed out waiting for RSO CMD status");
12374 return -ETIMEDOUT;
12375 }
12376
12377 if (!adapter->lfr_fw_status.is_disabled) {
12378 hdd_err("Roam disable attempt in FW fails");
12379 return -EBUSY;
12380 }
12381 }
12382
Dustin Browne74003f2018-03-14 12:51:58 -070012383 hdd_exit();
Mukul Sharma69c44cd2016-09-12 18:33:57 +053012384 return ret;
12385}
12386
12387/**
12388 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
12389 * @wiphy: Pointer to wireless phy
12390 * @wdev: Pointer to wireless device
12391 * @data: Pointer to data
12392 * @data_len: Length of @data
12393 *
12394 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
12395 *
12396 * Return: 0 on success, negative errno on failure
12397 */
12398static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
12399 struct wireless_dev *wdev,
12400 const void *data, int data_len)
12401{
12402 int ret;
12403
12404 cds_ssr_protect(__func__);
12405 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
12406 cds_ssr_unprotect(__func__);
12407
12408 return ret;
12409}
12410
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012411/*
12412 * define short names for the global vendor params
12413 * used by wlan_hdd_cfg80211_setarp_stats_cmd()
12414 */
12415#define STATS_SET_INVALID \
12416 QCA_ATTR_NUD_STATS_SET_INVALID
12417#define STATS_SET_START \
12418 QCA_ATTR_NUD_STATS_SET_START
12419#define STATS_GW_IPV4 \
12420 QCA_ATTR_NUD_STATS_GW_IPV4
12421#define STATS_SET_DATA_PKT_INFO \
12422 QCA_ATTR_NUD_STATS_SET_DATA_PKT_INFO
12423#define STATS_SET_MAX \
12424 QCA_ATTR_NUD_STATS_SET_MAX
12425
12426const struct nla_policy
12427qca_wlan_vendor_set_nud_stats[STATS_SET_MAX + 1] = {
12428 [STATS_SET_START] = {.type = NLA_FLAG },
12429 [STATS_GW_IPV4] = {.type = NLA_U32 },
12430 [STATS_SET_DATA_PKT_INFO] = {.type = NLA_U32 },
12431};
12432
12433/* define short names for the global vendor params */
12434#define CONNECTIVITY_STATS_SET_INVALID \
12435 QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_INVALID
12436#define STATS_PKT_INFO_TYPE \
12437 QCA_ATTR_CONNECTIVITY_CHECK_STATS_STATS_PKT_INFO_TYPE
12438#define STATS_DNS_DOMAIN_NAME \
12439 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DNS_DOMAIN_NAME
12440#define STATS_SRC_PORT \
12441 QCA_ATTR_CONNECTIVITY_CHECK_STATS_SRC_PORT
12442#define STATS_DEST_PORT \
12443 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_PORT
12444#define STATS_DEST_IPV4 \
12445 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV4
12446#define STATS_DEST_IPV6 \
12447 QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV6
12448#define CONNECTIVITY_STATS_SET_MAX \
12449 QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_MAX
12450
12451const struct nla_policy
12452qca_wlan_vendor_set_connectivity_check_stats[CONNECTIVITY_STATS_SET_MAX + 1] = {
12453 [STATS_PKT_INFO_TYPE] = {.type = NLA_U32 },
12454 [STATS_DNS_DOMAIN_NAME] = {.type = NLA_BINARY,
12455 .len = DNS_DOMAIN_NAME_MAX_LEN },
12456 [STATS_SRC_PORT] = {.type = NLA_U32 },
12457 [STATS_DEST_PORT] = {.type = NLA_U32 },
12458 [STATS_DEST_IPV4] = {.type = NLA_U32 },
12459 [STATS_DEST_IPV6] = {.type = NLA_BINARY,
12460 .len = ICMPv6_ADDR_LEN },
12461};
12462
12463/**
12464 * hdd_dns_unmake_name_query() - Convert an uncompressed DNS name to a
12465 * NUL-terminated string
12466 * @name: DNS name
12467 *
12468 * Return: Produce a printable version of a DNS name.
12469 */
12470static inline uint8_t *hdd_dns_unmake_name_query(uint8_t *name)
12471{
12472 uint8_t *p;
12473 unsigned int len;
12474
12475 p = name;
12476 while ((len = *p)) {
12477 *(p++) = '.';
12478 p += len;
12479 }
12480
12481 return name + 1;
12482}
12483
12484/**
12485 * hdd_dns_make_name_query() - Convert a standard NUL-terminated string
12486 * to DNS name
12487 * @string: Name as a NUL-terminated string
12488 * @buf: Buffer in which to place DNS name
12489 *
12490 * DNS names consist of "<length>element" pairs.
12491 *
12492 * Return: Byte following constructed DNS name
12493 */
12494static uint8_t *hdd_dns_make_name_query(const uint8_t *string, uint8_t *buf)
12495{
12496 uint8_t *length_byte = buf++;
12497 uint8_t c;
12498
12499 while ((c = *(string++))) {
12500 if (c == '.') {
12501 *length_byte = buf - length_byte - 1;
12502 length_byte = buf;
12503 }
12504 *(buf++) = c;
12505 }
12506 *length_byte = buf - length_byte - 1;
12507 *(buf++) = '\0';
12508 return buf;
12509}
12510
12511/**
12512 * hdd_set_clear_connectivity_check_stats_info() - set/clear stats info
12513 * @adapter: Pointer to hdd adapter
12514 * @arp_stats_params: arp stats structure to be sent to FW
12515 * @tb: nl attribute
12516 * @is_set_stats: set/clear stats
12517 *
12518 *
12519 * Return: 0 on success, negative errno on failure
12520 */
12521static int hdd_set_clear_connectivity_check_stats_info(
12522 struct hdd_adapter *adapter,
12523 struct set_arp_stats_params *arp_stats_params,
12524 struct nlattr **tb, bool is_set_stats)
12525{
12526 struct nlattr *tb2[CONNECTIVITY_STATS_SET_MAX + 1];
12527 struct nlattr *curr_attr = NULL;
12528 int err = 0;
12529 uint32_t pkt_bitmap;
12530 int rem;
12531
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012532 /* Set NUD command for start tracking is received. */
12533 nla_for_each_nested(curr_attr,
12534 tb[STATS_SET_DATA_PKT_INFO],
12535 rem) {
12536
12537 if (wlan_cfg80211_nla_parse(tb2,
12538 CONNECTIVITY_STATS_SET_MAX,
12539 nla_data(curr_attr), nla_len(curr_attr),
12540 qca_wlan_vendor_set_connectivity_check_stats)) {
12541 hdd_err("nla_parse failed");
12542 err = -EINVAL;
12543 goto end;
12544 }
12545
12546 if (tb2[STATS_PKT_INFO_TYPE]) {
12547 pkt_bitmap = nla_get_u32(tb2[STATS_PKT_INFO_TYPE]);
12548 if (!pkt_bitmap) {
12549 hdd_err("pkt tracking bitmap is empty");
12550 err = -EINVAL;
12551 goto end;
12552 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012553
12554 if (is_set_stats) {
12555 arp_stats_params->pkt_type_bitmap = pkt_bitmap;
12556 arp_stats_params->flag = true;
12557 adapter->pkt_type_bitmap |=
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012558 arp_stats_params->pkt_type_bitmap;
12559
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012560 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_ARP) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012561 if (!tb[STATS_GW_IPV4]) {
12562 hdd_err("GW ipv4 address is not present");
12563 err = -EINVAL;
12564 goto end;
12565 }
12566 arp_stats_params->ip_addr =
12567 nla_get_u32(tb[STATS_GW_IPV4]);
12568 arp_stats_params->pkt_type =
12569 WLAN_NUD_STATS_ARP_PKT_TYPE;
12570 adapter->track_arp_ip =
12571 arp_stats_params->ip_addr;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012572 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012573
12574 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
12575 uint8_t *domain_name;
12576
12577 if (!tb2[STATS_DNS_DOMAIN_NAME]) {
12578 hdd_err("DNS domain id is not present");
12579 err = -EINVAL;
12580 goto end;
12581 }
12582 domain_name = nla_data(
12583 tb2[STATS_DNS_DOMAIN_NAME]);
12584 adapter->track_dns_domain_len =
12585 nla_len(tb2[
12586 STATS_DNS_DOMAIN_NAME]);
12587 hdd_dns_make_name_query(domain_name,
12588 adapter->dns_payload);
12589 /* DNStracking isn't supported in FW. */
12590 arp_stats_params->pkt_type_bitmap &=
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012591 ~CONNECTIVITY_CHECK_SET_DNS;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012592 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012593
12594 if (pkt_bitmap &
12595 CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
12596 if (!tb2[STATS_SRC_PORT] ||
12597 !tb2[STATS_DEST_PORT]) {
12598 hdd_err("Source/Dest port is not present");
12599 err = -EINVAL;
12600 goto end;
12601 }
12602 arp_stats_params->tcp_src_port =
12603 nla_get_u32(
12604 tb2[STATS_SRC_PORT]);
12605 arp_stats_params->tcp_dst_port =
12606 nla_get_u32(
12607 tb2[STATS_DEST_PORT]);
12608 adapter->track_src_port =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012609 arp_stats_params->tcp_src_port;
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012610 adapter->track_dest_port =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012611 arp_stats_params->tcp_dst_port;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012612 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012613
12614 if (pkt_bitmap &
12615 CONNECTIVITY_CHECK_SET_ICMPV4) {
12616 if (!tb2[STATS_DEST_IPV4]) {
12617 hdd_err("destination ipv4 address to track ping packets is not present");
12618 err = -EINVAL;
12619 goto end;
12620 }
12621 arp_stats_params->icmp_ipv4 =
12622 nla_get_u32(
12623 tb2[STATS_DEST_IPV4]);
12624 adapter->track_dest_ipv4 =
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012625 arp_stats_params->icmp_ipv4;
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012626 }
12627 } else {
12628 /* clear stats command received */
12629 arp_stats_params->pkt_type_bitmap = pkt_bitmap;
12630 arp_stats_params->flag = false;
12631 adapter->pkt_type_bitmap &=
12632 (~arp_stats_params->pkt_type_bitmap);
12633
12634 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_ARP) {
12635 arp_stats_params->pkt_type =
12636 WLAN_NUD_STATS_ARP_PKT_TYPE;
12637 qdf_mem_zero(&adapter->hdd_stats.
12638 hdd_arp_stats,
12639 sizeof(adapter->hdd_stats.
12640 hdd_arp_stats));
12641 adapter->track_arp_ip = 0;
12642 }
12643
12644 if (pkt_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
12645 /* DNStracking isn't supported in FW. */
12646 arp_stats_params->pkt_type_bitmap &=
12647 ~CONNECTIVITY_CHECK_SET_DNS;
12648 qdf_mem_zero(&adapter->hdd_stats.
12649 hdd_dns_stats,
12650 sizeof(adapter->hdd_stats.
12651 hdd_dns_stats));
12652 qdf_mem_zero(adapter->dns_payload,
12653 adapter->track_dns_domain_len);
12654 adapter->track_dns_domain_len = 0;
12655 }
12656
12657 if (pkt_bitmap &
12658 CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
12659 qdf_mem_zero(&adapter->hdd_stats.
12660 hdd_tcp_stats,
12661 sizeof(adapter->hdd_stats.
12662 hdd_tcp_stats));
12663 adapter->track_src_port = 0;
12664 adapter->track_dest_port = 0;
12665 }
12666
12667 if (pkt_bitmap &
12668 CONNECTIVITY_CHECK_SET_ICMPV4) {
12669 qdf_mem_zero(&adapter->hdd_stats.
12670 hdd_icmpv4_stats,
12671 sizeof(adapter->hdd_stats.
12672 hdd_icmpv4_stats));
12673 adapter->track_dest_ipv4 = 0;
12674 }
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012675 }
12676 } else {
12677 hdd_err("stats list empty");
12678 err = -EINVAL;
12679 goto end;
12680 }
12681 }
12682
12683end:
12684 return err;
12685}
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +053012686
12687void hdd_update_cca_info_cb(void *context, uint32_t congestion,
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012688 uint32_t vdev_id)
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +053012689{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070012690 struct hdd_context *hdd_ctx = (struct hdd_context *)context;
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +053012691 int status;
Jeff Johnsone5006672017-08-29 14:39:02 -070012692 struct hdd_adapter *adapter = NULL;
Jeff Johnson40dae4e2017-08-29 14:00:25 -070012693 struct hdd_station_ctx *hdd_sta_ctx;
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +053012694
12695 status = wlan_hdd_validate_context(hdd_ctx);
12696 if (status != 0)
12697 return;
12698
12699 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
12700 if (adapter == NULL) {
12701 hdd_err("vdev_id %d does not exist with host", vdev_id);
12702 return;
12703 }
12704
12705 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
12706 hdd_sta_ctx->conn_info.cca = congestion;
12707 hdd_info("congestion:%d", congestion);
12708}
12709
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012710static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
12711 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
12712 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
12713 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
12714 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
12715};
12716
12717/**
12718 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
12719 * @wiphy: Pointer to wireless phy
12720 * @wdev: Pointer to wireless device
12721 * @data: Pointer to data
12722 * @data_len: Length of @data
12723 *
12724 * Return: 0 on success, negative errno on failure
12725 */
12726static int
12727__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
12728 struct wireless_dev *wdev,
12729 const void *data,
12730 int data_len)
12731{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070012732 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012733 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
12734 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
12735 struct nlattr *apth;
12736 int rem;
12737 int ret = 1;
12738 int print_idx = -1;
12739 int module_id = -1;
12740 int bit_mask = -1;
12741 int status;
12742
Dustin Brown491d54b2018-03-14 12:39:11 -070012743 hdd_enter();
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012744
12745 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
12746 hdd_err("Command not allowed in FTM mode");
12747 return -EINVAL;
12748 }
12749
12750 ret = wlan_hdd_validate_context(hdd_ctx);
12751 if (ret != 0)
12752 return -EINVAL;
12753
12754 print_idx = qdf_get_pidx();
12755 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
12756 hdd_err("Invalid print controle object index");
12757 return -EINVAL;
12758 }
12759
Dustin Brown4ea21db2018-01-05 14:13:17 -080012760 if (wlan_cfg80211_nla_parse(tb1,
12761 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
12762 data, data_len,
12763 qca_wlan_vendor_set_trace_level_policy)) {
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012764 hdd_err("Invalid attr");
12765 return -EINVAL;
12766 }
12767
12768 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
12769 hdd_err("attr trace level param failed");
12770 return -EINVAL;
12771 }
12772
12773 nla_for_each_nested(apth,
12774 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
Dustin Brown4ea21db2018-01-05 14:13:17 -080012775 if (wlan_cfg80211_nla_parse(tb2,
12776 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
12777 nla_data(apth), nla_len(apth), NULL)) {
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012778 hdd_err("Invalid attr");
12779 return -EINVAL;
12780 }
12781
12782 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
12783 hdd_err("attr Module ID failed");
12784 return -EINVAL;
12785 }
12786 module_id = nla_get_u32
12787 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
12788
12789 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
12790 hdd_err("attr Verbose mask failed");
12791 return -EINVAL;
12792 }
12793 bit_mask = nla_get_u32
12794 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
12795
12796 status = hdd_qdf_trace_enable(module_id, bit_mask);
12797
12798 if (status != 0)
12799 hdd_err("can not set verbose mask %d for the category %d",
12800 bit_mask, module_id);
12801 }
12802
Dustin Browne74003f2018-03-14 12:51:58 -070012803 hdd_exit();
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012804 return ret;
12805}
12806
12807/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +053012808 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
12809 * @wiphy: Pointer to wireless phy
12810 * @wdev: Pointer to wireless device
12811 * @data: Pointer to data
12812 * @data_len: Length of @data
12813 *
12814 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
12815 *
12816 * Return: 0 on success, negative errno on failure
12817 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053012818
12819static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
12820 struct wireless_dev *wdev,
12821 const void *data,
12822 int data_len)
12823{
12824 int ret;
12825
12826 cds_ssr_protect(__func__);
12827 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
12828 cds_ssr_unprotect(__func__);
12829
12830 return ret;
12831}
12832
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012833/**
12834 * __wlan_hdd_cfg80211_set_nud_stats() - set arp stats command to firmware
12835 * @wiphy: pointer to wireless wiphy structure.
12836 * @wdev: pointer to wireless_dev structure.
12837 * @data: pointer to apfind configuration data.
12838 * @data_len: the length in byte of apfind data.
12839 *
12840 * This is called when wlan driver needs to send arp stats to
12841 * firmware.
12842 *
12843 * Return: An error code or 0 on success.
12844 */
12845static int __wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
12846 struct wireless_dev *wdev,
12847 const void *data, int data_len)
12848{
12849 struct nlattr *tb[STATS_SET_MAX + 1];
12850 struct net_device *dev = wdev->netdev;
12851 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
12852 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012853 struct set_arp_stats_params arp_stats_params = {0};
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012854 int err = 0;
12855
Dustin Brown491d54b2018-03-14 12:39:11 -070012856 hdd_enter();
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012857
Anurag Chouhan9fb2bd52018-01-04 12:25:48 +053012858 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
12859 hdd_err("Command not allowed in FTM mode");
12860 return -EINVAL;
12861 }
12862
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012863 err = wlan_hdd_validate_context(hdd_ctx);
12864 if (0 != err)
12865 return err;
12866
Dustin Brown4ea21db2018-01-05 14:13:17 -080012867 err = wlan_cfg80211_nla_parse(tb, STATS_SET_MAX, data, data_len,
12868 qca_wlan_vendor_set_nud_stats);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012869 if (err) {
Dustin Browna2868622018-03-20 11:38:14 -070012870 hdd_err("STATS_SET_START ATTR");
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012871 return err;
12872 }
12873
Yeshwanth Sriram Guntukad5aae7f2017-11-27 14:33:51 +053012874 if (adapter->session_id == HDD_SESSION_ID_INVALID) {
12875 hdd_err("Invalid session id");
12876 return -EINVAL;
12877 }
12878
Poddar, Siddarthdf076672018-02-26 14:21:45 +053012879 if (adapter->device_mode != QDF_STA_MODE) {
Dustin Browna2868622018-03-20 11:38:14 -070012880 hdd_err("STATS supported in only STA mode!");
Poddar, Siddarthdf076672018-02-26 14:21:45 +053012881 return -EINVAL;
12882 }
12883
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012884 if (tb[STATS_SET_START]) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012885 /* tracking is enabled for stats other than arp. */
12886 if (tb[STATS_SET_DATA_PKT_INFO]) {
12887 err = hdd_set_clear_connectivity_check_stats_info(
12888 adapter,
12889 &arp_stats_params, tb, true);
12890 if (err)
12891 return -EINVAL;
12892
12893 /*
12894 * if only tracking dns, then don't send
12895 * wmi command to FW.
12896 */
12897 if (!arp_stats_params.pkt_type_bitmap)
12898 return err;
12899 } else {
12900 if (!tb[STATS_GW_IPV4]) {
Dustin Browna2868622018-03-20 11:38:14 -070012901 hdd_err("STATS_SET_START CMD");
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012902 return -EINVAL;
12903 }
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012904
12905 arp_stats_params.pkt_type_bitmap =
12906 CONNECTIVITY_CHECK_SET_ARP;
12907 adapter->pkt_type_bitmap |=
12908 arp_stats_params.pkt_type_bitmap;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012909 arp_stats_params.flag = true;
12910 arp_stats_params.ip_addr =
12911 nla_get_u32(tb[STATS_GW_IPV4]);
12912 adapter->track_arp_ip = arp_stats_params.ip_addr;
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012913 arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012914 }
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012915 } else {
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012916 /* clear stats command received. */
12917 if (tb[STATS_SET_DATA_PKT_INFO]) {
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012918 err = hdd_set_clear_connectivity_check_stats_info(
12919 adapter,
12920 &arp_stats_params, tb, false);
12921 if (err)
12922 return -EINVAL;
12923
12924 /*
12925 * if only tracking dns, then don't send
12926 * wmi command to FW.
12927 */
12928 if (!arp_stats_params.pkt_type_bitmap)
12929 return err;
12930 } else {
Poddar, Siddarth9c2cd262018-01-18 19:03:39 +053012931 arp_stats_params.pkt_type_bitmap =
12932 CONNECTIVITY_CHECK_SET_ARP;
12933 adapter->pkt_type_bitmap &=
12934 (~arp_stats_params.pkt_type_bitmap);
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012935 arp_stats_params.flag = false;
12936 qdf_mem_zero(&adapter->hdd_stats.hdd_arp_stats,
12937 sizeof(adapter->hdd_stats.hdd_arp_stats));
12938 arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
12939 }
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012940 }
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053012941
Dustin Browna2868622018-03-20 11:38:14 -070012942 hdd_info("STATS_SET_START Received flag %d!", arp_stats_params.flag);
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012943
Jeff Johnson1b780e42017-10-31 14:11:45 -070012944 arp_stats_params.vdev_id = adapter->session_id;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012945
12946 if (QDF_STATUS_SUCCESS !=
12947 sme_set_nud_debug_stats(hdd_ctx->hHal, &arp_stats_params)) {
Dustin Browna2868622018-03-20 11:38:14 -070012948 hdd_err("STATS_SET_START CMD Failed!");
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012949 return -EINVAL;
12950 }
12951
Dustin Browne74003f2018-03-14 12:51:58 -070012952 hdd_exit();
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053012953
12954 return err;
12955}
12956
12957/**
12958 * wlan_hdd_cfg80211_set_nud_stats() - set arp stats command to firmware
12959 * @wiphy: pointer to wireless wiphy structure.
12960 * @wdev: pointer to wireless_dev structure.
12961 * @data: pointer to apfind configuration data.
12962 * @data_len: the length in byte of apfind data.
12963 *
12964 * This is called when wlan driver needs to send arp stats to
12965 * firmware.
12966 *
12967 * Return: An error code or 0 on success.
12968 */
12969static int wlan_hdd_cfg80211_set_nud_stats(struct wiphy *wiphy,
12970 struct wireless_dev *wdev,
12971 const void *data, int data_len)
12972{
12973 int ret;
12974
12975 cds_ssr_protect(__func__);
12976 ret = __wlan_hdd_cfg80211_set_nud_stats(wiphy, wdev, data, data_len);
12977 cds_ssr_unprotect(__func__);
12978
12979 return ret;
12980}
12981
12982#undef STATS_SET_INVALID
12983#undef STATS_SET_START
12984#undef STATS_GW_IPV4
12985#undef STATS_SET_MAX
12986
12987/*
12988 * define short names for the global vendor params
12989 * used by wlan_hdd_cfg80211_setarp_stats_cmd()
12990 */
12991#define STATS_GET_INVALID \
12992 QCA_ATTR_NUD_STATS_SET_INVALID
12993#define COUNT_FROM_NETDEV \
12994 QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
12995#define COUNT_TO_LOWER_MAC \
12996 QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
12997#define RX_COUNT_BY_LOWER_MAC \
12998 QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
12999#define COUNT_TX_SUCCESS \
13000 QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
13001#define RSP_RX_COUNT_BY_LOWER_MAC \
13002 QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
13003#define RSP_RX_COUNT_BY_UPPER_MAC \
13004 QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
13005#define RSP_COUNT_TO_NETDEV \
13006 QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
13007#define RSP_COUNT_OUT_OF_ORDER_DROP \
13008 QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
13009#define AP_LINK_ACTIVE \
13010 QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
13011#define AP_LINK_DAD \
13012 QCA_ATTR_NUD_STATS_IS_DAD
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013013#define DATA_PKT_STATS \
13014 QCA_ATTR_NUD_STATS_DATA_PKT_STATS
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013015#define STATS_GET_MAX \
13016 QCA_ATTR_NUD_STATS_GET_MAX
13017
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013018#define CHECK_STATS_INVALID \
13019 QCA_ATTR_CONNECTIVITY_CHECK_STATS_INVALID
13020#define CHECK_STATS_PKT_TYPE \
13021 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_TYPE
13022#define CHECK_STATS_PKT_DNS_DOMAIN_NAME \
13023 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DNS_DOMAIN_NAME
13024#define CHECK_STATS_PKT_SRC_PORT \
13025 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_SRC_PORT
13026#define CHECK_STATS_PKT_DEST_PORT \
13027 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_PORT
13028#define CHECK_STATS_PKT_DEST_IPV4 \
13029 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV4
13030#define CHECK_STATS_PKT_DEST_IPV6 \
13031 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV6
13032#define CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV \
13033 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV
13034#define CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC \
13035 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC
13036#define CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC \
13037 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC
13038#define CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS \
13039 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS
13040#define CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC \
13041 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC
13042#define CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC \
13043 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC
13044#define CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV \
13045 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV
13046#define CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP \
13047 QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP
13048#define CHECK_DATA_STATS_MAX \
13049 QCA_ATTR_CONNECTIVITY_CHECK_DATA_STATS_MAX
13050
13051
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013052const struct nla_policy
13053qca_wlan_vendor_get_nud_stats[STATS_GET_MAX + 1] = {
13054 [COUNT_FROM_NETDEV] = {.type = NLA_U16 },
13055 [COUNT_TO_LOWER_MAC] = {.type = NLA_U16 },
13056 [RX_COUNT_BY_LOWER_MAC] = {.type = NLA_U16 },
13057 [COUNT_TX_SUCCESS] = {.type = NLA_U16 },
13058 [RSP_RX_COUNT_BY_LOWER_MAC] = {.type = NLA_U16 },
13059 [RSP_RX_COUNT_BY_UPPER_MAC] = {.type = NLA_U16 },
13060 [RSP_COUNT_TO_NETDEV] = {.type = NLA_U16 },
13061 [RSP_COUNT_OUT_OF_ORDER_DROP] = {.type = NLA_U16 },
13062 [AP_LINK_ACTIVE] = {.type = NLA_FLAG },
13063 [AP_LINK_DAD] = {.type = NLA_FLAG },
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013064 [DATA_PKT_STATS] = {.type = NLA_U16 },
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013065};
13066
13067/**
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013068 * hdd_populate_dns_stats_info() - send dns stats info to network stack
13069 * @adapter: pointer to adapter context
13070 * @skb: pointer to skb
13071 *
13072 *
13073 * Return: An error code or 0 on success.
13074 */
13075static int hdd_populate_dns_stats_info(struct hdd_adapter *adapter,
13076 struct sk_buff *skb)
13077{
13078 uint8_t *dns_query;
13079
13080 dns_query = qdf_mem_malloc(adapter->track_dns_domain_len + 1);
13081 if (!dns_query) {
Dustin Browna2868622018-03-20 11:38:14 -070013082 hdd_err("mem alloc fail");
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013083 return -EINVAL;
13084 }
13085
13086 qdf_mem_copy(dns_query, adapter->dns_payload,
13087 adapter->track_dns_domain_len);
13088
13089 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
13090 CONNECTIVITY_CHECK_SET_DNS) ||
13091 nla_put(skb, CHECK_STATS_PKT_DNS_DOMAIN_NAME,
13092 adapter->track_dns_domain_len,
13093 hdd_dns_unmake_name_query(dns_query)) ||
13094 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
13095 adapter->hdd_stats.hdd_dns_stats.tx_dns_req_count) ||
13096 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
13097 adapter->hdd_stats.hdd_dns_stats.tx_host_fw_sent) ||
13098 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
13099 adapter->hdd_stats.hdd_dns_stats.tx_host_fw_sent) ||
13100 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
13101 adapter->hdd_stats.hdd_dns_stats.tx_ack_cnt) ||
13102 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
13103 adapter->hdd_stats.hdd_dns_stats.rx_dns_rsp_count) ||
13104 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
13105 adapter->hdd_stats.hdd_dns_stats.rx_delivered) ||
13106 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
13107 adapter->hdd_stats.hdd_dns_stats.rx_host_drop)) {
13108 hdd_err("nla put fail");
13109 qdf_mem_free(dns_query);
13110 kfree_skb(skb);
13111 return -EINVAL;
13112 }
13113 qdf_mem_free(dns_query);
13114 return 0;
13115}
13116
13117/**
13118 * hdd_populate_tcp_stats_info() - send tcp stats info to network stack
13119 * @adapter: pointer to adapter context
13120 * @skb: pointer to skb
13121 * @pkt_type: tcp pkt type
13122 *
13123 * Return: An error code or 0 on success.
13124 */
13125static int hdd_populate_tcp_stats_info(struct hdd_adapter *adapter,
13126 struct sk_buff *skb,
13127 uint8_t pkt_type)
13128{
13129 switch (pkt_type) {
13130 case CONNECTIVITY_CHECK_SET_TCP_SYN:
13131 /* Fill info for tcp syn packets (tx packet) */
13132 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
13133 CONNECTIVITY_CHECK_SET_TCP_SYN) ||
13134 nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
13135 adapter->track_src_port) ||
13136 nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
13137 adapter->track_dest_port) ||
13138 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
13139 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_syn_count) ||
13140 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
13141 adapter->hdd_stats.hdd_tcp_stats.
13142 tx_tcp_syn_host_fw_sent) ||
13143 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
13144 adapter->hdd_stats.hdd_tcp_stats.
13145 tx_tcp_syn_host_fw_sent) ||
13146 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
13147 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_syn_ack_cnt)) {
13148 hdd_err("nla put fail");
13149 kfree_skb(skb);
13150 return -EINVAL;
13151 }
13152 break;
13153 case CONNECTIVITY_CHECK_SET_TCP_SYN_ACK:
13154 /* Fill info for tcp syn-ack packets (rx packet) */
13155 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
13156 CONNECTIVITY_CHECK_SET_TCP_SYN_ACK) ||
13157 nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
13158 adapter->track_src_port) ||
13159 nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
13160 adapter->track_dest_port) ||
13161 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC,
13162 adapter->hdd_stats.hdd_tcp_stats.rx_fw_cnt) ||
13163 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
13164 adapter->hdd_stats.hdd_tcp_stats.
13165 rx_tcp_syn_ack_count) ||
13166 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
13167 adapter->hdd_stats.hdd_tcp_stats.rx_delivered) ||
13168 nla_put_u16(skb,
13169 CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
13170 adapter->hdd_stats.hdd_tcp_stats.rx_host_drop)) {
13171 hdd_err("nla put fail");
13172 kfree_skb(skb);
13173 return -EINVAL;
13174 }
13175 break;
13176 case CONNECTIVITY_CHECK_SET_TCP_ACK:
13177 /* Fill info for tcp ack packets (tx packet) */
13178 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
13179 CONNECTIVITY_CHECK_SET_TCP_ACK) ||
13180 nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
13181 adapter->track_src_port) ||
13182 nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
13183 adapter->track_dest_port) ||
13184 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
13185 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_ack_count) ||
13186 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
13187 adapter->hdd_stats.hdd_tcp_stats.
13188 tx_tcp_ack_host_fw_sent) ||
13189 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
13190 adapter->hdd_stats.hdd_tcp_stats.
13191 tx_tcp_ack_host_fw_sent) ||
13192 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
13193 adapter->hdd_stats.hdd_tcp_stats.tx_tcp_ack_ack_cnt)) {
13194 hdd_err("nla put fail");
13195 kfree_skb(skb);
13196 return -EINVAL;
13197 }
13198 break;
13199 default:
13200 break;
13201 }
13202 return 0;
13203}
13204
13205/**
13206 * hdd_populate_icmpv4_stats_info() - send icmpv4 stats info to network stack
13207 * @adapter: pointer to adapter context
13208 * @skb: pointer to skb
13209 *
13210 *
13211 * Return: An error code or 0 on success.
13212 */
13213static int hdd_populate_icmpv4_stats_info(struct hdd_adapter *adapter,
13214 struct sk_buff *skb)
13215{
13216 if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
13217 CONNECTIVITY_CHECK_SET_ICMPV4) ||
13218 nla_put_u32(skb, CHECK_STATS_PKT_DEST_IPV4,
13219 adapter->track_dest_ipv4) ||
13220 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
13221 adapter->hdd_stats.hdd_icmpv4_stats.tx_icmpv4_req_count) ||
13222 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
13223 adapter->hdd_stats.hdd_icmpv4_stats.tx_host_fw_sent) ||
13224 nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
13225 adapter->hdd_stats.hdd_icmpv4_stats.tx_host_fw_sent) ||
13226 nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
13227 adapter->hdd_stats.hdd_icmpv4_stats.tx_ack_cnt) ||
13228 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC,
13229 adapter->hdd_stats.hdd_icmpv4_stats.rx_fw_cnt) ||
13230 nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
13231 adapter->hdd_stats.hdd_icmpv4_stats.rx_icmpv4_rsp_count) ||
13232 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
13233 adapter->hdd_stats.hdd_icmpv4_stats.rx_delivered) ||
13234 nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
13235 adapter->hdd_stats.hdd_icmpv4_stats.rx_host_drop)) {
13236 hdd_err("nla put fail");
13237 kfree_skb(skb);
13238 return -EINVAL;
13239 }
13240 return 0;
13241}
13242
13243/**
13244 * hdd_populate_connectivity_check_stats_info() - send connectivity stats info
13245 * to network stack
13246 * @adapter: pointer to adapter context
13247 * @skb: pointer to skb
13248 *
13249 *
13250 * Return: An error code or 0 on success.
13251 */
13252
13253static int hdd_populate_connectivity_check_stats_info(
13254 struct hdd_adapter *adapter, struct sk_buff *skb)
13255{
13256 struct nlattr *connect_stats, *connect_info;
13257 uint32_t count = 0;
13258
13259 connect_stats = nla_nest_start(skb, DATA_PKT_STATS);
13260 if (connect_stats == NULL) {
13261 hdd_err("nla_nest_start failed");
13262 return -EINVAL;
13263 }
13264
13265 if (adapter->pkt_type_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
13266 connect_info = nla_nest_start(skb, count);
13267 if (connect_info == NULL) {
13268 hdd_err("nla_nest_start failed count %u", count);
13269 return -EINVAL;
13270 }
13271
13272 if (hdd_populate_dns_stats_info(adapter, skb))
13273 goto put_attr_fail;
13274 nla_nest_end(skb, connect_info);
13275 count++;
13276 }
13277
13278 if (adapter->pkt_type_bitmap & CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
13279 connect_info = nla_nest_start(skb, count);
13280 if (connect_info == NULL) {
13281 hdd_err("nla_nest_start failed count %u", count);
13282 return -EINVAL;
13283 }
13284 if (hdd_populate_tcp_stats_info(adapter, skb,
13285 CONNECTIVITY_CHECK_SET_TCP_SYN))
13286 goto put_attr_fail;
13287 nla_nest_end(skb, connect_info);
13288 count++;
13289
13290 connect_info = nla_nest_start(skb, count);
13291 if (connect_info == NULL) {
13292 hdd_err("nla_nest_start failed count %u", count);
13293 return -EINVAL;
13294 }
13295 if (hdd_populate_tcp_stats_info(adapter, skb,
13296 CONNECTIVITY_CHECK_SET_TCP_SYN_ACK))
13297 goto put_attr_fail;
13298 nla_nest_end(skb, connect_info);
13299 count++;
13300
13301 connect_info = nla_nest_start(skb, count);
13302 if (connect_info == NULL) {
13303 hdd_err("nla_nest_start failed count %u", count);
13304 return -EINVAL;
13305 }
13306 if (hdd_populate_tcp_stats_info(adapter, skb,
13307 CONNECTIVITY_CHECK_SET_TCP_ACK))
13308 goto put_attr_fail;
13309 nla_nest_end(skb, connect_info);
13310 count++;
13311 }
13312
13313 if (adapter->pkt_type_bitmap & CONNECTIVITY_CHECK_SET_ICMPV4) {
13314 connect_info = nla_nest_start(skb, count);
13315 if (connect_info == NULL) {
13316 hdd_err("nla_nest_start failed count %u", count);
13317 return -EINVAL;
13318 }
13319
13320 if (hdd_populate_icmpv4_stats_info(adapter, skb))
13321 goto put_attr_fail;
13322 nla_nest_end(skb, connect_info);
13323 count++;
13324 }
13325
13326 nla_nest_end(skb, connect_stats);
13327 return 0;
13328
13329put_attr_fail:
13330 hdd_err("QCA_WLAN_VENDOR_ATTR put fail. count %u", count);
13331 return -EINVAL;
13332}
13333
13334
13335/**
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013336 * __wlan_hdd_cfg80211_get_nud_stats() - get arp stats command to firmware
13337 * @wiphy: pointer to wireless wiphy structure.
13338 * @wdev: pointer to wireless_dev structure.
13339 * @data: pointer to apfind configuration data.
13340 * @data_len: the length in byte of apfind data.
13341 *
13342 * This is called when wlan driver needs to get arp stats to
13343 * firmware.
13344 *
13345 * Return: An error code or 0 on success.
13346 */
13347static int __wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
13348 struct wireless_dev *wdev,
13349 const void *data, int data_len)
13350{
13351 int err = 0;
13352 unsigned long rc;
13353 struct hdd_nud_stats_context *context;
13354 struct net_device *dev = wdev->netdev;
13355 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
13356 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
13357 struct get_arp_stats_params arp_stats_params;
Poddar, Siddarthdb568162017-07-27 18:16:38 +053013358 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013359 uint32_t pkt_type_bitmap;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013360 struct sk_buff *skb;
13361
Dustin Brown491d54b2018-03-14 12:39:11 -070013362 hdd_enter();
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013363
Anurag Chouhan9fb2bd52018-01-04 12:25:48 +053013364 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
13365 hdd_err("Command not allowed in FTM mode");
13366 return -EINVAL;
13367 }
13368
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013369 err = wlan_hdd_validate_context(hdd_ctx);
13370 if (0 != err)
13371 return err;
13372
Rajeev Kumar7f28e8a32017-08-23 15:41:30 -070013373 err = hdd_validate_adapter(adapter);
13374 if (err)
13375 return err;
13376
Poddar, Siddarthdf076672018-02-26 14:21:45 +053013377 if (adapter->device_mode != QDF_STA_MODE) {
Dustin Browna2868622018-03-20 11:38:14 -070013378 hdd_err("STATS supported in only STA mode!");
Poddar, Siddarthdf076672018-02-26 14:21:45 +053013379 return -EINVAL;
13380 }
13381
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013382 arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
Jeff Johnson1b780e42017-10-31 14:11:45 -070013383 arp_stats_params.vdev_id = adapter->session_id;
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013384
13385 spin_lock(&hdd_context_lock);
13386 context = &hdd_ctx->nud_stats_context;
13387 INIT_COMPLETION(context->response_event);
13388 spin_unlock(&hdd_context_lock);
13389
Poddar, Siddarth762c5472018-03-20 14:55:35 +053013390 pkt_type_bitmap = adapter->pkt_type_bitmap;
13391
13392 /* send NUD failure event only when ARP tracking is enabled. */
13393 if (hdd_ctx->config->enable_data_stall_det &&
13394 (pkt_type_bitmap & CONNECTIVITY_CHECK_SET_ARP))
Poddar, Siddarth37033032017-10-11 15:47:40 +053013395 cdp_post_data_stall_event(soc,
13396 DATA_STALL_LOG_INDICATOR_FRAMEWORK,
Poddar, Siddarthdb568162017-07-27 18:16:38 +053013397 DATA_STALL_LOG_NUD_FAILURE,
13398 0xFF, 0XFF,
13399 DATA_STALL_LOG_RECOVERY_TRIGGER_PDR);
13400
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013401 if (QDF_STATUS_SUCCESS !=
13402 sme_get_nud_debug_stats(hdd_ctx->hHal, &arp_stats_params)) {
Dustin Browna2868622018-03-20 11:38:14 -070013403 hdd_err("STATS_SET_START CMD Failed!");
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013404 return -EINVAL;
13405 }
13406
13407 rc = wait_for_completion_timeout(&context->response_event,
13408 msecs_to_jiffies(
13409 WLAN_WAIT_TIME_NUD_STATS));
13410 if (!rc) {
13411 hdd_err("Target response timed out request ");
13412 return -ETIMEDOUT;
13413 }
13414
13415 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
13416 WLAN_NUD_STATS_LEN);
13417 if (!skb) {
13418 hdd_err("%s: cfg80211_vendor_cmd_alloc_reply_skb failed",
13419 __func__);
13420 return -ENOMEM;
13421 }
13422
13423 if (nla_put_u16(skb, COUNT_FROM_NETDEV,
Sravan Kumar Kairamc1ae71c2017-02-24 12:27:27 +053013424 adapter->hdd_stats.hdd_arp_stats.tx_arp_req_count) ||
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013425 nla_put_u16(skb, COUNT_TO_LOWER_MAC,
13426 adapter->hdd_stats.hdd_arp_stats.tx_host_fw_sent) ||
13427 nla_put_u16(skb, RX_COUNT_BY_LOWER_MAC,
Sravan Kumar Kairamc1ae71c2017-02-24 12:27:27 +053013428 adapter->hdd_stats.hdd_arp_stats.tx_host_fw_sent) ||
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013429 nla_put_u16(skb, COUNT_TX_SUCCESS,
13430 adapter->hdd_stats.hdd_arp_stats.tx_ack_cnt) ||
13431 nla_put_u16(skb, RSP_RX_COUNT_BY_LOWER_MAC,
13432 adapter->hdd_stats.hdd_arp_stats.rx_fw_cnt) ||
13433 nla_put_u16(skb, RSP_RX_COUNT_BY_UPPER_MAC,
Sravan Kumar Kairamc1ae71c2017-02-24 12:27:27 +053013434 adapter->hdd_stats.hdd_arp_stats.rx_arp_rsp_count) ||
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013435 nla_put_u16(skb, RSP_COUNT_TO_NETDEV,
13436 adapter->hdd_stats.hdd_arp_stats.rx_delivered) ||
13437 nla_put_u16(skb, RSP_COUNT_OUT_OF_ORDER_DROP,
13438 adapter->hdd_stats.hdd_arp_stats.
13439 rx_host_drop_reorder)) {
13440 hdd_err("nla put fail");
13441 kfree_skb(skb);
13442 return -EINVAL;
13443 }
13444 if (adapter->con_status)
13445 nla_put_flag(skb, AP_LINK_ACTIVE);
13446 if (adapter->dad)
13447 nla_put_flag(skb, AP_LINK_DAD);
13448
Poddar, Siddarth31797fa2018-01-22 17:24:15 +053013449 /* ARP tracking is done above. */
13450 pkt_type_bitmap &= ~CONNECTIVITY_CHECK_SET_ARP;
13451
13452 if (pkt_type_bitmap) {
13453 if (hdd_populate_connectivity_check_stats_info(adapter, skb))
13454 return -EINVAL;
13455 }
13456
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053013457 cfg80211_vendor_cmd_reply(skb);
13458 return err;
13459}
13460
13461/**
13462 * wlan_hdd_cfg80211_get_nud_stats() - get arp stats command to firmware
13463 * @wiphy: pointer to wireless wiphy structure.
13464 * @wdev: pointer to wireless_dev structure.
13465 * @data: pointer to apfind configuration data.
13466 * @data_len: the length in byte of apfind data.
13467 *
13468 * This is called when wlan driver needs to get arp stats to
13469 * firmware.
13470 *
13471 * Return: An error code or 0 on success.
13472 */
13473static int wlan_hdd_cfg80211_get_nud_stats(struct wiphy *wiphy,
13474 struct wireless_dev *wdev,
13475 const void *data, int data_len)
13476{
13477 int ret;
13478
13479 cds_ssr_protect(__func__);
13480 ret = __wlan_hdd_cfg80211_get_nud_stats(wiphy, wdev, data, data_len);
13481 cds_ssr_unprotect(__func__);
13482
13483 return ret;
13484}
13485
13486#undef QCA_ATTR_NUD_STATS_SET_INVALID
13487#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
13488#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
13489#undef QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
13490#undef QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
13491#undef QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
13492#undef QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
13493#undef QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
13494#undef QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
13495#undef QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
13496#undef QCA_ATTR_NUD_STATS_GET_MAX
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053013497
13498void hdd_bt_activity_cb(void *context, uint32_t bt_activity)
13499{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070013500 struct hdd_context *hdd_ctx = (struct hdd_context *)context;
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053013501 int status;
13502
13503 status = wlan_hdd_validate_context(hdd_ctx);
13504 if (0 != status)
13505 return;
13506
13507 if (bt_activity == WLAN_COEX_EVENT_BT_A2DP_PROFILE_ADD)
13508 hdd_ctx->bt_a2dp_active = 1;
13509 else if (bt_activity == WLAN_COEX_EVENT_BT_A2DP_PROFILE_REMOVE)
13510 hdd_ctx->bt_a2dp_active = 0;
13511 else if (bt_activity == WLAN_COEX_EVENT_BT_VOICE_PROFILE_ADD)
13512 hdd_ctx->bt_vo_active = 1;
13513 else if (bt_activity == WLAN_COEX_EVENT_BT_VOICE_PROFILE_REMOVE)
13514 hdd_ctx->bt_vo_active = 0;
13515 else
13516 return;
13517
Yeshwanth Sriram Guntuka9b9eb432017-12-14 18:48:41 +053013518 ucfg_scan_set_bt_activity(hdd_ctx->hdd_psoc, hdd_ctx->bt_a2dp_active);
Srinivas Girigowda6598eea2017-07-06 19:26:19 -070013519 hdd_debug("a2dp_active: %d vo_active: %d", hdd_ctx->bt_a2dp_active,
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053013520 hdd_ctx->bt_vo_active);
13521}
13522
13523
13524/**
13525 * wlan_hdd_is_bt_in_progress() - check if bt activity is in progress
13526 * @hdd_ctx : HDD context
13527 *
13528 * Return: true if BT activity is in progress else false
13529 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070013530static inline bool wlan_hdd_is_bt_in_progress(struct hdd_context *hdd_ctx)
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053013531{
13532 if (hdd_ctx->bt_a2dp_active || hdd_ctx->bt_vo_active)
13533 return true;
13534
13535 return false;
13536}
13537
lifengd217d192017-05-09 19:44:16 +080013538struct chain_rssi_priv {
13539 struct chain_rssi_result chain_rssi;
13540};
13541
13542/**
13543 * hdd_get_chain_rssi_cb() - Callback function to get chain rssi
13544 * @context: opaque context originally passed to SME. HDD always passes
13545 * a cookie for the request context
13546 * @data: struct for get chain rssi
13547 *
13548 * This function receives the response/data from the lower layer and
13549 * checks to see if the thread is still waiting then post the results to
13550 * upper layer, if the request has timed out then ignore.
13551 *
13552 * Return: None
13553 */
13554static void hdd_get_chain_rssi_cb(void *context,
13555 struct chain_rssi_result *data)
13556{
13557 struct hdd_request *request;
13558 struct chain_rssi_priv *priv;
13559
Dustin Brown491d54b2018-03-14 12:39:11 -070013560 hdd_enter();
lifengd217d192017-05-09 19:44:16 +080013561
13562 request = hdd_request_get(context);
13563 if (!request) {
13564 hdd_err("Obsolete request");
13565 return;
13566 }
13567
13568 priv = hdd_request_priv(request);
13569 priv->chain_rssi = *data;
13570 hdd_request_complete(request);
13571 hdd_request_put(request);
13572}
13573
13574/**
13575 * hdd_post_get_chain_rssi_rsp - send rsp to user space
13576 * @hdd_ctx: pointer to hdd context
13577 * @result: chain rssi result
13578 *
13579 * Return: 0 for success, non-zero for failure
13580 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070013581static int hdd_post_get_chain_rssi_rsp(struct hdd_context *hdd_ctx,
lifengd217d192017-05-09 19:44:16 +080013582 struct chain_rssi_result *result)
13583{
13584 struct sk_buff *skb;
13585 int data_len = sizeof(result->chain_rssi);
13586
13587 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy,
13588 data_len + NLA_HDRLEN + NLMSG_HDRLEN);
13589
13590 if (!skb) {
13591 hdd_err("cfg80211_vendor_event_alloc failed");
13592 return -ENOMEM;
13593 }
13594
13595 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_CHAIN_RSSI, data_len,
13596 result->chain_rssi)) {
13597 hdd_err("put fail");
13598 goto nla_put_failure;
13599 }
13600
13601 cfg80211_vendor_cmd_reply(skb);
13602 return 0;
13603
13604nla_put_failure:
13605 kfree_skb(skb);
13606 return -EINVAL;
13607}
13608
13609/**
13610 * __wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
13611 * @wiphy: wiphy pointer
13612 * @wdev: pointer to struct wireless_dev
13613 * @data: pointer to incoming NL vendor data
13614 * @data_len: length of @data
13615 *
13616 * Return: 0 on success; error number otherwise.
13617 */
13618static int __wlan_hdd_cfg80211_get_chain_rssi(struct wiphy *wiphy,
13619 struct wireless_dev *wdev,
13620 const void *data,
13621 int data_len)
13622{
Jeff Johnsone5006672017-08-29 14:39:02 -070013623 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070013624 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
lifengd217d192017-05-09 19:44:16 +080013625 struct get_chain_rssi_req_params req_msg;
13626 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
13627 QDF_STATUS status;
13628 int retval;
13629 void *cookie;
13630 struct hdd_request *request;
13631 struct chain_rssi_priv *priv;
13632 static const struct hdd_request_params params = {
13633 .priv_size = sizeof(*priv),
13634 .timeout_ms = WLAN_WAIT_TIME_STATS,
13635 };
13636
Dustin Brown491d54b2018-03-14 12:39:11 -070013637 hdd_enter();
lifengd217d192017-05-09 19:44:16 +080013638
13639 retval = wlan_hdd_validate_context(hdd_ctx);
13640 if (0 != retval)
13641 return retval;
13642
Dustin Brown4ea21db2018-01-05 14:13:17 -080013643 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX,
13644 data, data_len, NULL)) {
lifengd217d192017-05-09 19:44:16 +080013645 hdd_err("Invalid ATTR");
13646 return -EINVAL;
13647 }
13648
13649 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
13650 hdd_err("attr mac addr failed");
13651 return -EINVAL;
13652 }
13653 if (nla_len(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) !=
13654 QDF_MAC_ADDR_SIZE) {
13655 hdd_err("incorrect mac size");
13656 return -EINVAL;
13657 }
13658 memcpy(&req_msg.peer_macaddr,
13659 nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
13660 QDF_MAC_ADDR_SIZE);
Jeff Johnson1b780e42017-10-31 14:11:45 -070013661 req_msg.session_id = adapter->session_id;
lifengd217d192017-05-09 19:44:16 +080013662
13663 request = hdd_request_alloc(&params);
13664 if (!request) {
13665 hdd_err("Request allocation failure");
13666 return -ENOMEM;
13667 }
13668 cookie = hdd_request_cookie(request);
13669
13670 status = sme_get_chain_rssi(hdd_ctx->hHal,
13671 &req_msg,
13672 hdd_get_chain_rssi_cb,
13673 cookie);
13674 if (QDF_STATUS_SUCCESS != status) {
13675 hdd_err("Unable to get chain rssi");
13676 retval = qdf_status_to_os_return(status);
13677 } else {
13678 retval = hdd_request_wait_for_response(request);
13679 if (retval) {
13680 hdd_err("Target response timed out");
13681 } else {
13682 priv = hdd_request_priv(request);
13683 retval = hdd_post_get_chain_rssi_rsp(hdd_ctx,
13684 &priv->chain_rssi);
13685 if (retval)
13686 hdd_err("Failed to post chain rssi");
13687 }
13688 }
13689 hdd_request_put(request);
13690
Dustin Browne74003f2018-03-14 12:51:58 -070013691 hdd_exit();
lifengd217d192017-05-09 19:44:16 +080013692 return retval;
13693}
13694
13695/**
13696 * wlan_hdd_cfg80211_get_chain_rssi() - get chain rssi
13697 * @wiphy: wiphy pointer
13698 * @wdev: pointer to struct wireless_dev
13699 * @data: pointer to incoming NL vendor data
13700 * @data_len: length of @data
13701 *
13702 * Return: 0 on success; error number otherwise.
13703 */
13704static int wlan_hdd_cfg80211_get_chain_rssi(struct wiphy *wiphy,
13705 struct wireless_dev *wdev,
13706 const void *data,
13707 int data_len)
13708{
13709 int ret;
13710
13711 cds_ssr_protect(__func__);
13712 ret = __wlan_hdd_cfg80211_get_chain_rssi(wiphy, wdev, data, data_len);
13713 cds_ssr_unprotect(__func__);
13714
13715 return ret;
13716}
Vidyullatha Kanchanapallybe0ebb32017-03-23 14:36:21 +053013717
Ganesh Kondabattinib1960e72017-09-01 09:09:50 +053013718/**
13719 * __wlan_hdd_cfg80211_set_limit_offchan_param() - set limit off-channel cmd
13720 * parameters
13721 * @wiphy: pointer to wireless wiphy structure.
13722 * @wdev: pointer to wireless_dev structure.
13723 * @data: pointer to limit off-channel command parameters.
13724 * @data_len: the length in byte of limit off-channel command parameters.
13725 *
13726 * This is called when application wants to limit the off channel time due to
13727 * active voip traffic.
13728 *
13729 * Return: An error code or 0 on success.
13730 */
13731static int __wlan_hdd_cfg80211_set_limit_offchan_param(struct wiphy *wiphy,
13732 struct wireless_dev *wdev, const void *data, int data_len)
13733{
13734 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_MAX + 1];
13735 struct net_device *dev = wdev->netdev;
13736 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
13737 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
13738 int ret = 0;
13739 uint8_t tos;
13740 uint8_t tos_status;
13741
Dustin Brown491d54b2018-03-14 12:39:11 -070013742 hdd_enter();
Ganesh Kondabattinib1960e72017-09-01 09:09:50 +053013743
13744 ret = wlan_hdd_validate_context(hdd_ctx);
13745 if (ret < 0)
13746 return ret;
13747
Dustin Brown4ea21db2018-01-05 14:13:17 -080013748 if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_MAX,
13749 data, data_len,
13750 wlan_hdd_set_limit_off_channel_param_policy)) {
Ganesh Kondabattinib1960e72017-09-01 09:09:50 +053013751 hdd_err("Invalid ATTR");
13752 return -EINVAL;
13753 }
13754
13755 if (!tb[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS]) {
13756 hdd_err("attr tos failed");
13757 goto fail;
13758 }
13759
13760 tos = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS]);
13761 hdd_debug("tos %d", tos);
13762
13763 if (!tb[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_START]) {
13764 hdd_err("attr tos active failed");
13765 goto fail;
13766 }
13767 tos_status = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_START]);
13768
13769 hdd_debug("tos status %d", tos_status);
13770 ret = hdd_set_limit_off_chan_for_tos(adapter, tos, tos_status);
13771
13772fail:
13773 return ret;
13774}
13775
13776/**
13777 * wlan_hdd_cfg80211_set_limit_offchan_param() - set limit off-channel cmd
13778 * parameters
13779 * @wiphy: pointer to wireless wiphy structure.
13780 * @wdev: pointer to wireless_dev structure.
13781 * @data: pointer to limit off-channel command parameters.
13782 * @data_len: the length in byte of limit off-channel command parameters.
13783 *
13784 * This is called when application wants to limit the off channel time due to
13785 * active voip traffic.
13786 *
13787 * Return: An error code or 0 on success.
13788 */
13789static int wlan_hdd_cfg80211_set_limit_offchan_param(struct wiphy *wiphy,
13790 struct wireless_dev *wdev,
13791 const void *data, int data_len)
13792
13793{
13794 int ret = 0;
13795
13796 cds_ssr_protect(__func__);
13797 ret = __wlan_hdd_cfg80211_set_limit_offchan_param(wiphy, wdev, data,
13798 data_len);
13799 cds_ssr_unprotect(__func__);
13800
13801 return ret;
13802}
13803
Vignesh Viswanathan9dd88d32017-11-22 14:22:03 +053013804/**
13805 * wlan_hdd_fill_btm_resp() - Fill bss candidate response buffer
13806 * @reply_skb : pointer to reply_skb
13807 * @info : bss candidate information
13808 * @index : attribute type index for nla_next_start()
13809 *
13810 * Return : 0 on success and errno on failure
13811 */
13812static int wlan_hdd_fill_btm_resp(struct sk_buff *reply_skb,
13813 struct bss_candidate_info *info,
13814 int index)
13815{
13816 struct nlattr *attr;
13817
13818 attr = nla_nest_start(reply_skb, index);
13819 if (!attr) {
13820 hdd_err("nla_nest_start failed");
13821 kfree_skb(reply_skb);
13822 return -EINVAL;
13823 }
13824
13825 if (nla_put(reply_skb,
13826 QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID,
13827 ETH_ALEN, info->bssid.bytes) ||
13828 nla_put_u32(reply_skb,
13829 QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_STATUS,
13830 info->status)) {
13831 hdd_err("nla_put failed");
13832 kfree_skb(reply_skb);
13833 return -EINVAL;
13834 }
13835
13836 nla_nest_end(reply_skb, attr);
13837
13838 return 0;
13839}
13840
13841/**
13842 * __wlan_hdd_cfg80211_fetch_bss_transition_status() - fetch bss transition
13843 * status
13844 * @wiphy : WIPHY structure pointer
13845 * @wdev : Wireless device structure pointer
13846 * @data : Pointer to the data received
13847 * @data_len : Length of the data received
13848 *
13849 * This fuction is used to fetch transition status for candidate bss. The
13850 * transition status is either accept or reason for reject.
13851 *
13852 * Return : 0 on success and errno on failure
13853 */
13854static int __wlan_hdd_cfg80211_fetch_bss_transition_status(struct wiphy *wiphy,
13855 struct wireless_dev *wdev,
13856 const void *data, int data_len)
13857{
13858 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
13859 struct nlattr *tb_msg[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_MAX + 1];
13860 uint8_t transition_reason;
13861 struct nlattr *attr;
13862 struct sk_buff *reply_skb;
13863 int rem, j;
13864 int ret;
13865 bool is_bt_in_progress;
13866 struct bss_candidate_info candidate_info[MAX_CANDIDATE_INFO];
13867 uint16_t nof_candidates, i = 0;
13868 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
13869 struct net_device *dev = wdev->netdev;
13870 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
13871 struct hdd_station_ctx *hdd_sta_ctx =
13872 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
13873 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
13874
13875 const struct nla_policy
13876 btm_params_policy[QCA_WLAN_VENDOR_ATTR_MAX + 1] = {
13877 [QCA_WLAN_VENDOR_ATTR_BTM_MBO_TRANSITION_REASON] = {
13878 .type = NLA_U8},
13879 [QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO] = {
13880 .type = NLA_NESTED},
13881 };
13882 const struct nla_policy
13883 btm_cand_list_policy[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_MAX + 1]
13884 = {[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID] = {
13885 .len = QDF_MAC_ADDR_SIZE},
13886 [QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_STATUS] = {
13887 .type = NLA_U32},
13888 };
13889
Dustin Brown491d54b2018-03-14 12:39:11 -070013890 hdd_enter();
Vignesh Viswanathan9dd88d32017-11-22 14:22:03 +053013891
13892 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
13893 hdd_err("Command not allowed in FTM mode");
13894 return -EINVAL;
13895 }
13896
13897 ret = wlan_hdd_validate_context(hdd_ctx);
13898 if (ret)
13899 return ret;
13900
13901 if (adapter->device_mode != QDF_STA_MODE ||
13902 hdd_sta_ctx->conn_info.connState != eConnectionState_Associated) {
13903 hdd_err("Command is either not invoked for STA mode (device mode: %d) or STA is not associated (Connection state: %d)",
13904 adapter->device_mode, hdd_sta_ctx->conn_info.connState);
13905 return -EINVAL;
13906 }
13907
Dustin Brown4ea21db2018-01-05 14:13:17 -080013908 ret = wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data,
13909 data_len, btm_params_policy);
Vignesh Viswanathan9dd88d32017-11-22 14:22:03 +053013910 if (ret) {
13911 hdd_err("Attribute parse failed");
13912 return -EINVAL;
13913 }
13914
13915 if (!tb[QCA_WLAN_VENDOR_ATTR_BTM_MBO_TRANSITION_REASON] ||
13916 !tb[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO]) {
13917 hdd_err("Missing attributes");
13918 return -EINVAL;
13919 }
13920
13921 transition_reason = nla_get_u8(
13922 tb[QCA_WLAN_VENDOR_ATTR_BTM_MBO_TRANSITION_REASON]);
13923
13924 nla_for_each_nested(attr,
13925 tb[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO],
13926 rem) {
Dustin Brown4ea21db2018-01-05 14:13:17 -080013927 ret = wlan_cfg80211_nla_parse_nested(tb_msg,
13928 QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_MAX,
13929 attr, btm_cand_list_policy);
Vignesh Viswanathan9dd88d32017-11-22 14:22:03 +053013930 if (ret) {
13931 hdd_err("Attribute parse failed");
13932 return -EINVAL;
13933 }
13934
13935 if (!tb_msg[QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID]) {
13936 hdd_err("Missing BSSID attribute");
13937 return -EINVAL;
13938 }
13939
13940 qdf_mem_copy((void *)candidate_info[i].bssid.bytes,
13941 nla_data(tb_msg[
13942 QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID]),
13943 QDF_MAC_ADDR_SIZE);
13944 i++;
13945 if (i == MAX_CANDIDATE_INFO)
13946 break;
13947 }
13948
13949 /*
13950 * Determine status for each candidate and fill in the status field.
13951 * Also arrange the candidates in the order of preference.
13952 */
13953 nof_candidates = i;
13954
13955 is_bt_in_progress = wlan_hdd_is_bt_in_progress(hdd_ctx);
13956
13957 ret = sme_get_bss_transition_status(hal, transition_reason,
13958 &hdd_sta_ctx->conn_info.bssId,
13959 candidate_info,
13960 nof_candidates,
13961 is_bt_in_progress);
13962 if (ret)
13963 return -EINVAL;
13964
13965 /* Prepare the reply and send it to userspace */
13966 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
13967 ((QDF_MAC_ADDR_SIZE + sizeof(uint32_t)) *
13968 nof_candidates) + NLMSG_HDRLEN);
13969 if (!reply_skb) {
13970 hdd_err("reply buffer alloc failed");
13971 return -ENOMEM;
13972 }
13973
13974 attr = nla_nest_start(reply_skb,
13975 QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO);
13976 if (!attr) {
13977 hdd_err("nla_nest_start failed");
13978 kfree_skb(reply_skb);
13979 return -EINVAL;
13980 }
13981
13982 /*
13983 * Order candidates as - accepted candidate list followed by rejected
13984 * candidate list
13985 */
13986 for (i = 0, j = 0; i < nof_candidates; i++) {
13987 /* copy accepted candidate list */
13988 if (candidate_info[i].status == QCA_STATUS_ACCEPT) {
13989 if (wlan_hdd_fill_btm_resp(reply_skb,
13990 &candidate_info[i], j))
13991 return -EINVAL;
13992 j++;
13993 }
13994 }
13995 for (i = 0; i < nof_candidates; i++) {
13996 /* copy rejected candidate list */
13997 if (candidate_info[i].status != QCA_STATUS_ACCEPT) {
13998 if (wlan_hdd_fill_btm_resp(reply_skb,
13999 &candidate_info[i], j))
14000 return -EINVAL;
14001 j++;
14002 }
14003 }
14004 nla_nest_end(reply_skb, attr);
14005
Dustin Browne74003f2018-03-14 12:51:58 -070014006 hdd_exit();
Vignesh Viswanathan9dd88d32017-11-22 14:22:03 +053014007
14008 return cfg80211_vendor_cmd_reply(reply_skb);
14009}
14010
14011/**
14012 * wlan_hdd_cfg80211_fetch_bss_transition_status() - fetch bss transition status
14013 * @wiphy : WIPHY structure pointer
14014 * @wdev : Wireless device structure pointer
14015 * @data : Pointer to the data received
14016 * @data_len : Length of the data received
14017 *
14018 * This fuction is used to fetch transition status for candidate bss. The
14019 * transition status is either accept or reason for reject.
14020 *
14021 * Return : 0 on success and errno on failure
14022 */
14023static int wlan_hdd_cfg80211_fetch_bss_transition_status(struct wiphy *wiphy,
14024 struct wireless_dev *wdev,
14025 const void *data, int data_len)
14026{
14027 int ret;
14028
14029 cds_ssr_protect(__func__);
14030 ret = __wlan_hdd_cfg80211_fetch_bss_transition_status(wiphy, wdev,
14031 data, data_len);
14032 cds_ssr_unprotect(__func__);
14033
14034 return ret;
14035}
14036
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053014037/**
14038 * wlan_hdd_fill_intf_info() - Fill skb buffer with interface info
14039 * @skb: Pointer to skb
14040 * @info: mac mode info
14041 * @index: attribute type index for nla_nest_start()
14042 *
14043 * Return : 0 on success and errno on failure
14044 */
14045static int wlan_hdd_fill_intf_info(struct sk_buff *skb,
14046 struct connection_info *info, int index)
14047{
14048 struct nlattr *attr;
14049 uint32_t freq;
14050 struct hdd_context *hdd_ctx;
14051 struct hdd_adapter *hdd_adapter;
14052
14053 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
14054 if (!hdd_ctx)
14055 goto error;
14056
14057 hdd_adapter = hdd_get_adapter_by_vdev(hdd_ctx, info->vdev_id);
14058 if (!hdd_adapter)
14059 goto error;
14060
14061 attr = nla_nest_start(skb, index);
14062 if (!attr)
14063 goto error;
14064
14065 freq = sme_chn_to_freq(info->channel);
14066
14067 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_IFINDEX,
14068 hdd_adapter->dev->ifindex) ||
14069 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_FREQ, freq))
14070 goto error;
14071
14072 nla_nest_end(skb, attr);
14073
14074 return 0;
14075error:
14076 hdd_err("Fill buffer with interface info failed");
14077 kfree_skb(skb);
14078 return -EINVAL;
14079}
14080
14081/**
14082 * wlan_hdd_fill_mac_info() - Fill skb buffer with mac info
14083 * @skb: Pointer to skb
14084 * @info: mac mode info
14085 * @mac_id: MAC id
14086 * @conn_count: number of current connections
14087 *
14088 * Return : 0 on success and errno on failure
14089 */
14090static int wlan_hdd_fill_mac_info(struct sk_buff *skb,
14091 struct connection_info *info, uint32_t mac_id,
14092 uint32_t conn_count)
14093{
14094 struct nlattr *attr, *intf_attr;
14095 uint32_t band = 0, i = 0, j = 0;
14096 bool present = false;
14097
14098 while (i < conn_count) {
14099 if (info[i].mac_id == mac_id) {
14100 present = true;
14101 if (info[i].channel <= SIR_11B_CHANNEL_END)
14102 band |= 1 << NL80211_BAND_2GHZ;
14103 else if (info[i].channel <= SIR_11A_CHANNEL_END)
14104 band |= 1 << NL80211_BAND_5GHZ;
14105 }
14106 i++;
14107 }
14108
14109 if (!present)
14110 return 0;
14111
14112 i = 0;
14113 attr = nla_nest_start(skb, mac_id);
14114 if (!attr)
14115 goto error;
14116
14117 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO_MAC_ID, mac_id) ||
14118 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO_BAND, band))
14119 goto error;
14120
14121 intf_attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO);
14122 if (!intf_attr)
14123 goto error;
14124
14125 while (i < conn_count) {
14126 if (info[i].mac_id == mac_id) {
14127 if (wlan_hdd_fill_intf_info(skb, &info[i], j))
14128 return -EINVAL;
14129 j++;
14130 }
14131 i++;
14132 }
14133
14134 nla_nest_end(skb, intf_attr);
14135
14136 nla_nest_end(skb, attr);
14137
14138 return 0;
14139error:
14140 hdd_err("Fill buffer with mac info failed");
14141 kfree_skb(skb);
14142 return -EINVAL;
14143}
14144
14145
14146int wlan_hdd_send_mode_change_event(void)
14147{
14148 int err;
14149 struct hdd_context *hdd_ctx;
14150 struct sk_buff *skb;
14151 struct nlattr *attr;
14152 struct connection_info info[MAX_NUMBER_OF_CONC_CONNECTIONS];
14153 uint32_t conn_count, mac_id;
14154
Dustin Brown491d54b2018-03-14 12:39:11 -070014155 hdd_enter();
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053014156 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
14157 if (!hdd_ctx) {
14158 hdd_err("HDD context is NULL");
14159 return -EINVAL;
14160 }
14161
14162 err = wlan_hdd_validate_context(hdd_ctx);
14163 if (0 != err)
14164 return err;
14165
14166 conn_count = policy_mgr_get_connection_info(hdd_ctx->hdd_psoc, info);
14167 if (!conn_count)
14168 return -EINVAL;
14169
14170 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy, NULL,
14171 (sizeof(uint32_t) * 4) *
14172 MAX_NUMBER_OF_CONC_CONNECTIONS + NLMSG_HDRLEN,
14173 QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO_INDEX,
14174 GFP_KERNEL);
14175 if (!skb) {
14176 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
14177 return -ENOMEM;
14178 }
14179
14180 attr = nla_nest_start(skb, QCA_WLAN_VENDOR_ATTR_MAC_INFO);
14181 if (!attr) {
14182 hdd_err("nla_nest_start failed");
14183 kfree_skb(skb);
14184 return -EINVAL;
14185 }
14186
14187 for (mac_id = 0; mac_id < MAX_MAC; mac_id++) {
14188 if (wlan_hdd_fill_mac_info(skb, info, mac_id, conn_count))
14189 return -EINVAL;
14190 }
14191
14192 nla_nest_end(skb, attr);
14193
14194 cfg80211_vendor_event(skb, GFP_KERNEL);
Dustin Browne74003f2018-03-14 12:51:58 -070014195 hdd_exit();
Yeshwanth Sriram Guntuka2d6204f2018-01-23 18:52:14 +053014196
14197 return err;
14198}
14199
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014200const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
14201 {
14202 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14203 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
14204 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +053014205 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014206 .doit = is_driver_dfs_capable
14207 },
14208
14209#ifdef WLAN_FEATURE_NAN
14210 {
14211 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14212 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
14213 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14214 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14215 .doit = wlan_hdd_cfg80211_nan_request
14216 },
14217#endif
14218
14219#ifdef WLAN_FEATURE_STATS_EXT
14220 {
14221 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14222 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
14223 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14224 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14225 .doit = wlan_hdd_cfg80211_stats_ext_request
14226 },
14227#endif
14228#ifdef FEATURE_WLAN_EXTSCAN
14229 {
14230 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14231 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
14232 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14233 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14234 .doit = wlan_hdd_cfg80211_extscan_start
14235 },
14236 {
14237 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14238 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
14239 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14240 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14241 .doit = wlan_hdd_cfg80211_extscan_stop
14242 },
14243 {
14244 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14245 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
Manjeet Singh3abd7302017-01-11 16:07:42 +053014246 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14247 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014248 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
14249 },
14250 {
14251 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14252 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
14253 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14254 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14255 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
14256 },
14257 {
14258 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14259 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
14260 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14261 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14262 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
14263 },
14264 {
14265 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14266 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
14267 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14268 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14269 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
14270 },
14271 {
14272 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14273 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
14274 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14275 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14276 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
14277 },
14278 {
14279 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14280 .info.subcmd =
14281 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
14282 .flags =
14283 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
14284 WIPHY_VENDOR_CMD_NEED_RUNNING,
14285 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
14286 },
14287 {
14288 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14289 .info.subcmd =
14290 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
14291 .flags =
14292 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
14293 WIPHY_VENDOR_CMD_NEED_RUNNING,
14294 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
14295 },
14296 {
14297 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14298 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
14299 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14300 WIPHY_VENDOR_CMD_NEED_NETDEV |
14301 WIPHY_VENDOR_CMD_NEED_RUNNING,
14302 .doit = wlan_hdd_cfg80211_set_epno_list
14303 },
14304#endif /* FEATURE_WLAN_EXTSCAN */
14305
14306#ifdef WLAN_FEATURE_LINK_LAYER_STATS
14307 {
14308 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14309 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
14310 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14311 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14312 .doit = wlan_hdd_cfg80211_ll_stats_clear
14313 },
14314
14315 {
14316 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14317 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
14318 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14319 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14320 .doit = wlan_hdd_cfg80211_ll_stats_set
14321 },
14322
14323 {
14324 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14325 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
14326 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14327 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14328 .doit = wlan_hdd_cfg80211_ll_stats_get
14329 },
14330#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
14331#ifdef FEATURE_WLAN_TDLS
14332 {
14333 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14334 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
14335 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14336 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14337 .doit = wlan_hdd_cfg80211_exttdls_enable
14338 },
14339 {
14340 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14341 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
14342 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14343 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
14344 .doit = wlan_hdd_cfg80211_exttdls_disable
14345 },
14346 {
14347 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14348 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
14349 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
14350 .doit = wlan_hdd_cfg80211_exttdls_get_status
14351 },
14352#endif
14353 {
14354 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14355 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
14356 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
14357 .doit = wlan_hdd_cfg80211_get_supported_features
14358 },
14359 {
14360 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14361 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053014362 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14363 WIPHY_VENDOR_CMD_NEED_NETDEV |
14364 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014365 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
14366 },
14367 {
14368 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14369 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
14370 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +053014371 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014372 },
14373 {
14374 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14375 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
14376 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053014377 WIPHY_VENDOR_CMD_NEED_NETDEV |
14378 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014379 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
14380 },
Manikandan Mohan80dea792016-04-28 16:36:48 -070014381 {
14382 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14383 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
14384 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053014385 WIPHY_VENDOR_CMD_NEED_NETDEV |
14386 WIPHY_VENDOR_CMD_NEED_RUNNING,
Manikandan Mohan80dea792016-04-28 16:36:48 -070014387 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
14388 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014389 {
14390 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +053014391 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
14392 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14393 WIPHY_VENDOR_CMD_NEED_NETDEV |
14394 WIPHY_VENDOR_CMD_NEED_RUNNING,
14395 .doit = hdd_cfg80211_get_station_cmd
14396 },
14397 {
14398 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014399 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
14400 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14401 WIPHY_VENDOR_CMD_NEED_NETDEV |
14402 WIPHY_VENDOR_CMD_NEED_RUNNING,
14403 .doit = wlan_hdd_cfg80211_do_acs
14404 },
14405
14406 {
14407 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14408 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
14409 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14410 WIPHY_VENDOR_CMD_NEED_NETDEV,
14411 .doit = wlan_hdd_cfg80211_get_features
14412 },
14413#ifdef WLAN_FEATURE_ROAM_OFFLOAD
14414 {
14415 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14416 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
14417 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14418 WIPHY_VENDOR_CMD_NEED_NETDEV |
14419 WIPHY_VENDOR_CMD_NEED_RUNNING,
14420 .doit = wlan_hdd_cfg80211_keymgmt_set_key
14421 },
14422#endif
14423#ifdef FEATURE_WLAN_EXTSCAN
14424 {
14425 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14426 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
14427 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14428 WIPHY_VENDOR_CMD_NEED_NETDEV |
14429 WIPHY_VENDOR_CMD_NEED_RUNNING,
14430 .doit = wlan_hdd_cfg80211_set_passpoint_list
14431 },
14432 {
14433 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14434 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
14435 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14436 WIPHY_VENDOR_CMD_NEED_NETDEV |
14437 WIPHY_VENDOR_CMD_NEED_RUNNING,
14438 .doit = wlan_hdd_cfg80211_reset_passpoint_list
14439 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014440#endif /* FEATURE_WLAN_EXTSCAN */
14441 {
14442 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14443 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
14444 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14445 WIPHY_VENDOR_CMD_NEED_NETDEV,
14446 .doit = wlan_hdd_cfg80211_get_wifi_info
14447 },
Paul Zhang3a210c52016-12-08 10:18:12 +080014448#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014449 {
14450 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14451 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
14452 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14453 WIPHY_VENDOR_CMD_NEED_NETDEV |
14454 WIPHY_VENDOR_CMD_NEED_RUNNING,
14455 .doit = wlan_hdd_cfg80211_wifi_configuration_set
14456 },
Paul Zhang3a210c52016-12-08 10:18:12 +080014457#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014458 {
14459 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Kiran Kumar Lokere08195ef2018-01-17 19:25:15 -080014460 .info.subcmd =
14461 QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION,
14462 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14463 WIPHY_VENDOR_CMD_NEED_NETDEV |
14464 WIPHY_VENDOR_CMD_NEED_RUNNING,
14465 .doit = wlan_hdd_cfg80211_set_wifi_test_config
14466 },
14467
14468 {
14469 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014470 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
14471 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053014472 WIPHY_VENDOR_CMD_NEED_NETDEV |
14473 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014474 .doit = wlan_hdd_cfg80211_set_ext_roam_params
14475 },
14476 {
14477 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14478 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
14479 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053014480 WIPHY_VENDOR_CMD_NEED_NETDEV |
14481 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014482 .doit = wlan_hdd_cfg80211_wifi_logger_start
14483 },
14484 {
14485 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14486 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
14487 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +053014488 WIPHY_VENDOR_CMD_NEED_NETDEV |
14489 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014490 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
14491 },
14492 {
14493 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14494 .info.subcmd =
14495 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
14496 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14497 WIPHY_VENDOR_CMD_NEED_NETDEV |
14498 WIPHY_VENDOR_CMD_NEED_RUNNING,
14499 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
14500 },
14501 {
14502 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14503 .info.subcmd =
14504 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
14505 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14506 WIPHY_VENDOR_CMD_NEED_NETDEV |
14507 WIPHY_VENDOR_CMD_NEED_RUNNING,
14508 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
14509 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070014510#ifdef WLAN_FEATURE_TSF
14511 {
14512 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14513 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
14514 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14515 WIPHY_VENDOR_CMD_NEED_NETDEV |
14516 WIPHY_VENDOR_CMD_NEED_RUNNING,
14517 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
14518 },
14519#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014520#ifdef FEATURE_WLAN_TDLS
14521 {
14522 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14523 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
14524 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14525 WIPHY_VENDOR_CMD_NEED_NETDEV |
14526 WIPHY_VENDOR_CMD_NEED_RUNNING,
14527 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
14528 },
14529#endif
14530#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
14531 {
14532 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14533 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
14534 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14535 WIPHY_VENDOR_CMD_NEED_NETDEV |
14536 WIPHY_VENDOR_CMD_NEED_RUNNING,
14537 .doit = wlan_hdd_cfg80211_offloaded_packets
14538 },
14539#endif
14540 {
14541 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14542 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
14543 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14544 WIPHY_VENDOR_CMD_NEED_NETDEV |
14545 WIPHY_VENDOR_CMD_NEED_RUNNING,
14546 .doit = wlan_hdd_cfg80211_monitor_rssi
14547 },
14548 {
14549 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +053014550 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
14551 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14552 WIPHY_VENDOR_CMD_NEED_NETDEV |
14553 WIPHY_VENDOR_CMD_NEED_RUNNING,
14554 .doit = wlan_hdd_cfg80211_set_ns_offload
14555 },
14556 {
14557 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014558 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
14559 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Sourav Mohapatra412ceb92018-03-07 18:41:16 +053014560 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014561 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
14562 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014563 {
14564 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14565 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
14566 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14567 WIPHY_VENDOR_CMD_NEED_NETDEV |
14568 WIPHY_VENDOR_CMD_NEED_RUNNING,
14569 .doit = wlan_hdd_cfg80211_vendor_scan
14570 },
14571
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014572 /* Vendor abort scan */
14573 {
14574 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14575 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
14576 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14577 WIPHY_VENDOR_CMD_NEED_NETDEV |
14578 WIPHY_VENDOR_CMD_NEED_RUNNING,
14579 .doit = wlan_hdd_vendor_abort_scan
14580 },
14581
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014582 /* OCB commands */
14583 {
14584 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14585 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
14586 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14587 WIPHY_VENDOR_CMD_NEED_NETDEV |
14588 WIPHY_VENDOR_CMD_NEED_RUNNING,
14589 .doit = wlan_hdd_cfg80211_ocb_set_config
14590 },
14591 {
14592 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14593 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
14594 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14595 WIPHY_VENDOR_CMD_NEED_NETDEV |
14596 WIPHY_VENDOR_CMD_NEED_RUNNING,
14597 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
14598 },
14599 {
14600 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14601 .info.subcmd =
14602 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
14603 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14604 WIPHY_VENDOR_CMD_NEED_NETDEV |
14605 WIPHY_VENDOR_CMD_NEED_RUNNING,
14606 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
14607 },
14608 {
14609 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14610 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
14611 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14612 WIPHY_VENDOR_CMD_NEED_NETDEV |
14613 WIPHY_VENDOR_CMD_NEED_RUNNING,
14614 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
14615 },
14616 {
14617 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14618 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
14619 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14620 WIPHY_VENDOR_CMD_NEED_NETDEV |
14621 WIPHY_VENDOR_CMD_NEED_RUNNING,
14622 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
14623 },
14624 {
14625 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14626 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
14627 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14628 WIPHY_VENDOR_CMD_NEED_NETDEV |
14629 WIPHY_VENDOR_CMD_NEED_RUNNING,
14630 .doit = wlan_hdd_cfg80211_dcc_get_stats
14631 },
14632 {
14633 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14634 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
14635 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14636 WIPHY_VENDOR_CMD_NEED_NETDEV |
14637 WIPHY_VENDOR_CMD_NEED_RUNNING,
14638 .doit = wlan_hdd_cfg80211_dcc_clear_stats
14639 },
14640 {
14641 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14642 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
14643 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14644 WIPHY_VENDOR_CMD_NEED_NETDEV |
14645 WIPHY_VENDOR_CMD_NEED_RUNNING,
14646 .doit = wlan_hdd_cfg80211_dcc_update_ndl
14647 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +053014648 {
14649 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14650 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
14651 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14652 WIPHY_VENDOR_CMD_NEED_NETDEV |
14653 WIPHY_VENDOR_CMD_NEED_RUNNING,
14654 .doit = wlan_hdd_cfg80211_get_link_properties
14655 },
Peng Xu278d0122015-09-24 16:34:17 -070014656 {
Peng Xud2220962016-07-11 17:59:17 -070014657 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -070014658 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
14659 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14660 WIPHY_VENDOR_CMD_NEED_NETDEV |
14661 WIPHY_VENDOR_CMD_NEED_RUNNING,
14662 .doit = wlan_hdd_cfg80211_set_ota_test
14663 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -080014664#ifdef FEATURE_LFR_SUBNET_DETECTION
14665 {
14666 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14667 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
14668 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14669 WIPHY_VENDOR_CMD_NEED_NETDEV |
14670 WIPHY_VENDOR_CMD_NEED_RUNNING,
14671 .doit = wlan_hdd_cfg80211_set_gateway_params
14672 },
14673#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -070014674 {
Peng Xud2220962016-07-11 17:59:17 -070014675 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -070014676 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
14677 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14678 WIPHY_VENDOR_CMD_NEED_NETDEV |
14679 WIPHY_VENDOR_CMD_NEED_RUNNING,
14680 .doit = wlan_hdd_cfg80211_txpower_scale
14681 },
14682 {
14683 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14684 .info.subcmd =
14685 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
14686 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14687 WIPHY_VENDOR_CMD_NEED_NETDEV |
14688 WIPHY_VENDOR_CMD_NEED_RUNNING,
14689 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
14690 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +053014691 {
14692 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14693 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
14694 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14695 WIPHY_VENDOR_CMD_NEED_NETDEV |
14696 WIPHY_VENDOR_CMD_NEED_RUNNING,
14697 .doit = wlan_hdd_cfg80211_bpf_offload
14698 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053014699 {
14700 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +053014701 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
14702 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14703 WIPHY_VENDOR_CMD_NEED_NETDEV |
14704 WIPHY_VENDOR_CMD_NEED_RUNNING,
14705 .doit = wlan_hdd_cfg80211_acs_dfs_mode
14706 },
14707 {
14708 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +053014709 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
14710 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14711 WIPHY_VENDOR_CMD_NEED_NETDEV |
14712 WIPHY_VENDOR_CMD_NEED_RUNNING,
14713 .doit = wlan_hdd_cfg80211_sta_roam_policy
14714 },
Agrawal Ashish467dde42016-09-08 18:44:22 +053014715#ifdef FEATURE_WLAN_CH_AVOID
14716 {
14717 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14718 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
14719 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14720 WIPHY_VENDOR_CMD_NEED_NETDEV |
14721 WIPHY_VENDOR_CMD_NEED_RUNNING,
14722 .doit = wlan_hdd_cfg80211_avoid_freq
14723 },
14724#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +053014725 {
14726 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053014727 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
14728 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14729 WIPHY_VENDOR_CMD_NEED_NETDEV |
14730 WIPHY_VENDOR_CMD_NEED_RUNNING,
14731 .doit = wlan_hdd_cfg80211_sap_configuration_set
14732 },
Peng Xu8fdaa492016-06-22 10:20:47 -070014733 {
Peng Xu4225c152016-07-14 21:18:14 -070014734 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -070014735 .info.subcmd =
14736 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
14737 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14738 WIPHY_VENDOR_CMD_NEED_NETDEV |
14739 WIPHY_VENDOR_CMD_NEED_RUNNING,
14740 .doit = wlan_hdd_cfg80211_p2p_lo_start
14741 },
14742 {
14743 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14744 .info.subcmd =
14745 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
14746 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14747 WIPHY_VENDOR_CMD_NEED_NETDEV |
14748 WIPHY_VENDOR_CMD_NEED_RUNNING,
14749 .doit = wlan_hdd_cfg80211_p2p_lo_stop
14750 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053014751 {
14752 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14753 .info.subcmd =
14754 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
14755 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14756 WIPHY_VENDOR_CMD_NEED_NETDEV |
14757 WIPHY_VENDOR_CMD_NEED_RUNNING,
14758 .doit = wlan_hdd_cfg80211_conditional_chan_switch
14759 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070014760#ifdef WLAN_FEATURE_NAN_DATAPATH
14761 {
14762 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14763 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
14764 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14765 WIPHY_VENDOR_CMD_NEED_NETDEV |
14766 WIPHY_VENDOR_CMD_NEED_RUNNING,
14767 .doit = wlan_hdd_cfg80211_process_ndp_cmd
14768 },
14769#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053014770 {
14771 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14772 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
14773 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14774 WIPHY_VENDOR_CMD_NEED_NETDEV |
14775 WIPHY_VENDOR_CMD_NEED_RUNNING,
14776 .doit = wlan_hdd_cfg80211_get_wakelock_stats
14777 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053014778 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053014779 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14780 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
14781 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14782 WIPHY_VENDOR_CMD_NEED_NETDEV |
14783 WIPHY_VENDOR_CMD_NEED_RUNNING,
14784 .doit = wlan_hdd_cfg80211_get_bus_size
14785 },
14786 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053014787 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14788 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
14789 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14790 WIPHY_VENDOR_CMD_NEED_NETDEV |
14791 WIPHY_VENDOR_CMD_NEED_RUNNING,
14792 .doit = wlan_hdd_cfg80211_update_vendor_channel
14793 },
14794 {
bingsd09dea32017-03-17 10:08:26 +080014795 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053014796 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
14797 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14798 WIPHY_VENDOR_CMD_NEED_NETDEV |
14799 WIPHY_VENDOR_CMD_NEED_RUNNING,
14800 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053014801 },
14802 {
14803 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14804 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
14805 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14806 WIPHY_VENDOR_CMD_NEED_NETDEV |
14807 WIPHY_VENDOR_CMD_NEED_RUNNING,
14808 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053014809 },
14810#ifdef WLAN_FEATURE_DISA
14811 {
14812 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14813 .info.subcmd =
14814 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
14815 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14816 WIPHY_VENDOR_CMD_NEED_NETDEV |
14817 WIPHY_VENDOR_CMD_NEED_RUNNING,
14818 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
14819 },
14820#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070014821#ifdef FEATURE_WLAN_TDLS
14822 {
14823 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14824 .info.subcmd =
14825 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
14826 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14827 WIPHY_VENDOR_CMD_NEED_NETDEV |
14828 WIPHY_VENDOR_CMD_NEED_RUNNING,
14829 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080014830 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070014831#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080014832 {
14833 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Jeff Johnson8c83f132017-12-18 16:41:37 -080014834 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS,
14835 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14836 WIPHY_VENDOR_CMD_NEED_RUNNING,
14837 .doit = wlan_hdd_cfg80211_get_sar_power_limits
14838 },
14839 {
14840 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080014841 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
14842 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14843 WIPHY_VENDOR_CMD_NEED_RUNNING,
14844 .doit = wlan_hdd_cfg80211_set_sar_power_limits
14845 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053014846 {
14847 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14848 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
14849 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14850 WIPHY_VENDOR_CMD_NEED_NETDEV |
14851 WIPHY_VENDOR_CMD_NEED_RUNNING,
14852 .doit = wlan_hdd_cfg80211_set_trace_level
14853 },
Zhang Qian4ead8f02017-03-27 14:21:47 +080014854 {
14855 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14856 .info.subcmd =
14857 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT,
14858 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14859 WIPHY_VENDOR_CMD_NEED_NETDEV |
14860 WIPHY_VENDOR_CMD_NEED_RUNNING,
14861 .doit = wlan_hdd_cfg80211_ll_stats_ext_set_param
14862 },
Anurag Chouhan3920c0f2017-09-11 17:10:56 +053014863 {
14864 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14865 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET,
14866 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14867 WIPHY_VENDOR_CMD_NEED_NETDEV |
14868 WIPHY_VENDOR_CMD_NEED_RUNNING,
14869 .doit = wlan_hdd_cfg80211_set_nud_stats
14870 },
14871 {
14872 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14873 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET,
14874 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14875 WIPHY_VENDOR_CMD_NEED_NETDEV |
14876 WIPHY_VENDOR_CMD_NEED_RUNNING,
14877 .doit = wlan_hdd_cfg80211_get_nud_stats
14878 },
Vignesh Viswanathan9dd88d32017-11-22 14:22:03 +053014879 {
14880 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14881 .info.subcmd =
14882 QCA_NL80211_VENDOR_SUBCMD_FETCH_BSS_TRANSITION_STATUS,
14883 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14884 WIPHY_VENDOR_CMD_NEED_NETDEV |
14885 WIPHY_VENDOR_CMD_NEED_RUNNING,
14886 .doit = wlan_hdd_cfg80211_fetch_bss_transition_status
14887 },
Sandeep Puligilla063a4342018-01-10 02:50:14 -080014888 FEATURE_SPECTRAL_SCAN_VENDOR_COMMANDS
Paul Zhang3a210c52016-12-08 10:18:12 +080014889#ifdef WLAN_UMAC_CONVERGENCE
14890 COMMON_VENDOR_COMMANDS
14891#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080014892 FEATURE_11AX_VENDOR_COMMANDS
lifengd217d192017-05-09 19:44:16 +080014893
14894 {
14895 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14896 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI,
14897 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14898 WIPHY_VENDOR_CMD_NEED_NETDEV |
14899 WIPHY_VENDOR_CMD_NEED_RUNNING,
14900 .doit = wlan_hdd_cfg80211_get_chain_rssi
14901 },
Ganesh Kondabattinib1960e72017-09-01 09:09:50 +053014902 {
14903 .info.vendor_id = QCA_NL80211_VENDOR_ID,
14904 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACTIVE_TOS,
14905 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
14906 WIPHY_VENDOR_CMD_NEED_NETDEV |
14907 WIPHY_VENDOR_CMD_NEED_RUNNING,
14908 .doit = wlan_hdd_cfg80211_set_limit_offchan_param
14909 },
14910
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014911};
14912
Dustin Brown52ba1ce2017-08-16 12:10:55 -070014913#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
14914static inline void
14915hdd_wiphy_set_max_sched_scans(struct wiphy *wiphy, uint8_t max_scans)
14916{
14917 if (max_scans == 0)
14918 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
14919 else
14920 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
14921}
14922#else
14923static inline void
14924hdd_wiphy_set_max_sched_scans(struct wiphy *wiphy, uint8_t max_scans)
14925{
14926 wiphy->max_sched_scan_reqs = max_scans;
14927}
14928#endif /* KERNEL_VERSION(4, 12, 0) */
14929
Padma, Santhosh Kumar4b302b62017-07-21 17:33:27 +053014930/**
14931 * wlan_hdd_cfg80211_add_connected_pno_support() - Set connected PNO support
14932 * @wiphy: Pointer to wireless phy
14933 *
14934 * This function is used to set connected PNO support to kernel
14935 *
14936 * Return: None
14937 */
14938#if defined(CFG80211_REPORT_BETTER_BSS_IN_SCHED_SCAN)
14939static void wlan_hdd_cfg80211_add_connected_pno_support(struct wiphy *wiphy)
14940{
14941 wiphy_ext_feature_set(wiphy,
14942 NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI);
14943}
14944#else
14945static void wlan_hdd_cfg80211_add_connected_pno_support(struct wiphy *wiphy)
14946{
14947}
14948#endif
14949
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053014950#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
14951 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
14952 defined(FEATURE_WLAN_SCAN_PNO)
14953/**
14954 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
14955 * @wiphy: pointer to wiphy
14956 * @config: pointer to config
14957 *
14958 * Return: None
14959 */
14960static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
14961 struct hdd_config *config)
14962{
14963 if (config->configPNOScanSupport) {
Dustin Brown52ba1ce2017-08-16 12:10:55 -070014964 hdd_wiphy_set_max_sched_scans(wiphy, 1);
Abhishek Singh0481d662017-04-11 18:20:11 +053014965 wiphy->max_sched_scan_ssids = SCAN_PNO_MAX_SUPP_NETWORKS;
14966 wiphy->max_match_sets = SCAN_PNO_MAX_SUPP_NETWORKS;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053014967 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Abhishek Singh0481d662017-04-11 18:20:11 +053014968 wiphy->max_sched_scan_plans = SCAN_PNO_MAX_PLAN_REQUEST;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053014969 if (config->max_sched_scan_plan_interval)
14970 wiphy->max_sched_scan_plan_interval =
14971 config->max_sched_scan_plan_interval;
14972 if (config->max_sched_scan_plan_iterations)
14973 wiphy->max_sched_scan_plan_iterations =
14974 config->max_sched_scan_plan_iterations;
14975 }
14976}
14977#else
14978static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
14979 struct hdd_config *config)
14980{
14981}
14982#endif
14983
14984
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080014985/**
14986 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
14987 * @priv_size: Size of the hdd context.
14988 *
14989 * Allocate wiphy context and hdd context.
14990 *
14991 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014992 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070014993struct hdd_context *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014994{
14995 struct wiphy *wiphy;
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070014996 struct hdd_context *hdd_ctx;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080014997
Dustin Brown491d54b2018-03-14 12:39:11 -070014998 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014999
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015000 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
15001
15002 if (!wiphy) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015003 hdd_err("wiphy init failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015004 return NULL;
15005 }
15006
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080015007 hdd_ctx = wiphy_priv(wiphy);
15008
15009 hdd_ctx->wiphy = wiphy;
15010
15011 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015012}
15013
15014/*
15015 * FUNCTION: wlan_hdd_cfg80211_update_band
15016 * This function is called from the supplicant through a
15017 * private ioctl to change the band value
15018 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070015019int wlan_hdd_cfg80211_update_band(struct hdd_context *hdd_ctx, struct wiphy *wiphy,
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080015020 enum band_info eBand)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015021{
15022 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070015023 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015024
Dustin Brown491d54b2018-03-14 12:39:11 -070015025 hdd_enter();
Srinivas Girigowda5da651b2017-08-04 11:22:54 -070015026
15027 for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015028
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080015029 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015030 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015031
15032 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
15033 struct ieee80211_supported_band *band = wiphy->bands[i];
15034
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070015035 channelEnabledState = wlan_reg_get_channel_state(
15036 hdd_ctx->hdd_pdev,
15037 band->channels[j].hw_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015038
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015039 if (HDD_NL80211_BAND_2GHZ == i &&
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080015040 BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015041 /* 5G only */
15042#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
15043 /* Enable Social channels for P2P */
15044 if (WLAN_HDD_IS_SOCIAL_CHANNEL
15045 (band->channels[j].center_freq)
15046 && CHANNEL_STATE_ENABLE ==
15047 channelEnabledState)
15048 band->channels[j].flags &=
15049 ~IEEE80211_CHAN_DISABLED;
15050 else
15051#endif
15052 band->channels[j].flags |=
15053 IEEE80211_CHAN_DISABLED;
15054 continue;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015055 } else if (HDD_NL80211_BAND_5GHZ == i &&
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080015056 BAND_2G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015057 /* 2G only */
15058 band->channels[j].flags |=
15059 IEEE80211_CHAN_DISABLED;
15060 continue;
15061 }
15062
Amar Singhal6842e8f2016-02-23 16:30:32 -080015063 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015064 band->channels[j].flags &=
15065 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015066 }
15067 }
15068 return 0;
15069}
15070
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +053015071#if defined(CFG80211_SCAN_RANDOM_MAC_ADDR) || \
15072 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
15073static void wlan_hdd_cfg80211_scan_randomization_init(struct wiphy *wiphy)
15074{
Paul Zhang382248f2017-10-17 14:24:45 +080015075 struct hdd_context *hdd_ctx;
Jeff Johnsone0847ba2018-03-01 12:34:50 -080015076
Paul Zhang382248f2017-10-17 14:24:45 +080015077 hdd_ctx = wiphy_priv(wiphy);
15078
15079 if (false == hdd_ctx->config->enable_mac_spoofing) {
15080 hdd_warn("MAC address spoofing is not enabled");
15081 } else {
15082 wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
15083 wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR;
15084 }
Rajeev Kumar Sirasanagandla686abd92017-06-08 18:09:01 +053015085}
15086#else
15087static void wlan_hdd_cfg80211_scan_randomization_init(struct wiphy *wiphy)
15088{
15089}
15090#endif
15091
Peng Xuacfdda12017-02-06 16:15:38 -080015092#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053015093
15094#if defined(WLAN_FEATURE_FILS_SK) && \
15095 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
15096 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053015097static void wlan_hdd_cfg80211_set_wiphy_fils_feature(struct wiphy *wiphy)
15098{
15099 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_SK_OFFLOAD);
15100}
15101#else
15102static void wlan_hdd_cfg80211_set_wiphy_fils_feature(struct wiphy *wiphy)
15103{
15104}
15105#endif
15106
gaurank kathpaliaa398d5f2018-02-27 16:42:22 +053015107#if defined (CFG80211_SCAN_DBS_CONTROL_SUPPORT) || \
15108 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0))
15109static void wlan_hdd_cfg80211_set_wiphy_scan_flags(struct wiphy *wiphy)
15110{
15111 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_LOW_SPAN_SCAN);
15112 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_LOW_POWER_SCAN);
15113 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN);
15114}
15115#else
15116static void wlan_hdd_cfg80211_set_wiphy_scan_flags(struct wiphy *wiphy)
15117{
15118}
15119#endif
15120
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053015121#if defined(WLAN_FEATURE_SAE) && \
15122 defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053015123/**
15124 * wlan_hdd_cfg80211_set_wiphy_sae_feature() - Indicates support of SAE feature
15125 * @wiphy: Pointer to wiphy
15126 * @config: pointer to config
15127 *
15128 * This function is used to indicate the support of SAE
15129 *
15130 * Return: None
15131 */
15132static void wlan_hdd_cfg80211_set_wiphy_sae_feature(struct wiphy *wiphy,
15133 struct hdd_config *config)
15134{
15135 if (config->is_sae_enabled)
15136 wiphy->features |= NL80211_FEATURE_SAE;
15137}
15138#else
15139static void wlan_hdd_cfg80211_set_wiphy_sae_feature(struct wiphy *wiphy,
15140 struct hdd_config *config)
15141{
15142}
15143#endif
15144
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015145/*
15146 * FUNCTION: wlan_hdd_cfg80211_init
15147 * This function is called by hdd_wlan_startup()
15148 * during initialization.
15149 * This function is used to initialize and register wiphy structure.
15150 */
15151int wlan_hdd_cfg80211_init(struct device *dev,
15152 struct wiphy *wiphy, struct hdd_config *pCfg)
15153{
15154 int i, j;
Jeff Johnsonb8944722017-09-03 09:03:19 -070015155 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +053015156 int len = 0;
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053015157 uint32_t *cipher_suites;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015158
Dustin Brown491d54b2018-03-14 12:39:11 -070015159 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015160
15161 /* Now bind the underlying wlan device with wiphy */
15162 set_wiphy_dev(wiphy, dev);
15163
15164 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
15165
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015166 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
15167 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
15168 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
15169#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
15170 | WIPHY_FLAG_4ADDR_STATION
15171#endif
15172 | WIPHY_FLAG_OFFCHAN_TX;
15173
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015174#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
15175 wiphy->wowlan = &wowlan_support_cfg80211_init;
15176#else
15177 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
15178 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
15179 wiphy->wowlan.pattern_min_len = 1;
15180 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
15181#endif
15182
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070015183 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015184#ifdef FEATURE_WLAN_ESE
15185 || pCfg->isEseIniFeatureEnabled
15186#endif
15187 ) {
15188 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
15189 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015190#ifdef FEATURE_WLAN_TDLS
15191 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
15192 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
15193#endif
15194
15195 wiphy->features |= NL80211_FEATURE_HT_IBSS;
15196
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015197#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
15198 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
15199#endif
Vignesh Viswanathancc7f1b92017-09-28 13:12:24 +053015200 if (pCfg->is_fils_enabled)
15201 wlan_hdd_cfg80211_set_wiphy_fils_feature(wiphy);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015202
gaurank kathpaliaa398d5f2018-02-27 16:42:22 +053015203 wlan_hdd_cfg80211_set_wiphy_scan_flags(wiphy);
15204
Padma, Santhosh Kumar3e47c632017-09-01 20:15:27 +053015205 wlan_hdd_cfg80211_set_wiphy_sae_feature(wiphy, pCfg);
15206
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053015207 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Padma, Santhosh Kumar4b302b62017-07-21 17:33:27 +053015208 wlan_hdd_cfg80211_add_connected_pno_support(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015209
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015210 wiphy->max_scan_ssids = MAX_SCAN_SSID;
15211
15212 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
15213
15214 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
15215
Arun Khandavallifae92942016-08-01 13:31:08 +053015216 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
15217 | BIT(NL80211_IFTYPE_ADHOC)
15218 | BIT(NL80211_IFTYPE_P2P_CLIENT)
15219 | BIT(NL80211_IFTYPE_P2P_GO)
15220 | BIT(NL80211_IFTYPE_AP)
15221 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015222
Arun Khandavallifae92942016-08-01 13:31:08 +053015223 if (pCfg->advertiseConcurrentOperation) {
15224 if (pCfg->enableMCC) {
15225 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015226
Arun Khandavallifae92942016-08-01 13:31:08 +053015227 for (i = 0;
15228 i < ARRAY_SIZE(wlan_hdd_iface_combination);
15229 i++) {
15230 if (!pCfg->allowMCCGODiffBI)
15231 wlan_hdd_iface_combination[i].
15232 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015233 }
15234 }
15235 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053015236 ARRAY_SIZE(wlan_hdd_iface_combination);
15237 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015238 }
15239
15240 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015241 * on ini values
15242 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015243 if (!pCfg->ShortGI20MhzEnable) {
15244 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
15245 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015246 }
15247
Srinivas Girigowda576b2352017-08-25 14:44:26 -070015248 if (!pCfg->ShortGI40MhzEnable)
15249 wlan_hdd_band_5_ghz.ht_cap.cap &=
15250 ~IEEE80211_HT_CAP_SGI_40;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015251
Srinivas Girigowda576b2352017-08-25 14:44:26 -070015252 if (!pCfg->nChannelBondingMode5GHz)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015253 wlan_hdd_band_5_ghz.ht_cap.cap &=
15254 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015255
Abhishek Singhf512bf32016-05-04 16:47:46 +053015256 /*
15257 * In case of static linked driver at the time of driver unload,
15258 * module exit doesn't happens. Module cleanup helps in cleaning
15259 * of static memory.
15260 * If driver load happens statically, at the time of driver unload,
15261 * wiphy flags don't get reset because of static memory.
15262 * It's better not to store channel in static memory.
15263 */
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015264 wiphy->bands[HDD_NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
15265 wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053015266 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015267 if (wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053015268 hdd_err("Not enough memory to allocate channels");
15269 return -ENOMEM;
15270 }
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015271 qdf_mem_copy(wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053015272 &hdd_channels_2_4_ghz[0],
15273 sizeof(hdd_channels_2_4_ghz));
Jeff Johnsonb8944722017-09-03 09:03:19 -070015274 if ((hdd_is_5g_supported(hdd_ctx)) &&
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053015275 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
15276 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
15277 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
15278 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015279 wiphy->bands[HDD_NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +053015280
15281 if (pCfg->dot11p_mode) {
15282 wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels =
15283 qdf_mem_malloc(sizeof(hdd_channels_5_ghz) +
15284 sizeof(hdd_channels_dot11p));
15285 if (wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels ==
15286 NULL) {
15287 goto mem_fail;
15288 }
15289 wiphy->bands[HDD_NL80211_BAND_5GHZ]->n_channels =
15290 QDF_ARRAY_SIZE(hdd_channels_5_ghz) +
15291 QDF_ARRAY_SIZE(hdd_channels_dot11p);
15292
15293 qdf_mem_copy(wiphy->bands[HDD_NL80211_BAND_5GHZ]->
15294 channels, &hdd_channels_5_ghz[0],
15295 sizeof(hdd_channels_5_ghz));
15296 len = sizeof(hdd_channels_5_ghz);
15297 qdf_mem_copy((char *)wiphy->
15298 bands[HDD_NL80211_BAND_5GHZ]->channels
15299 + len,
15300 &hdd_channels_dot11p[0],
15301 sizeof(hdd_channels_dot11p));
15302
15303 } else {
15304 wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053015305 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +053015306 if (wiphy->bands[HDD_NL80211_BAND_5GHZ]->channels ==
15307 NULL) {
15308 goto mem_fail;
15309 }
15310 qdf_mem_copy(wiphy->
15311 bands[HDD_NL80211_BAND_5GHZ]->channels,
15312 &hdd_channels_5_ghz[0],
15313 sizeof(hdd_channels_5_ghz));
Abhishek Singhf512bf32016-05-04 16:47:46 +053015314 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015315 }
15316
Srinivas Girigowda5da651b2017-08-04 11:22:54 -070015317 for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015318
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080015319 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015320 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015321
15322 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
15323 struct ieee80211_supported_band *band = wiphy->bands[i];
15324
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015325 if (HDD_NL80211_BAND_2GHZ == i &&
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080015326 BAND_5G == pCfg->nBandCapability) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015327 /* 5G only */
15328#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
15329 /* Enable social channels for P2P */
15330 if (WLAN_HDD_IS_SOCIAL_CHANNEL
15331 (band->channels[j].center_freq))
15332 band->channels[j].flags &=
15333 ~IEEE80211_CHAN_DISABLED;
15334 else
15335#endif
15336 band->channels[j].flags |=
15337 IEEE80211_CHAN_DISABLED;
15338 continue;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015339 } else if (HDD_NL80211_BAND_5GHZ == i &&
Varun Reddy Yeturua48bc412017-11-17 15:33:35 -080015340 BAND_2G == pCfg->nBandCapability) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015341 /* 2G only */
15342 band->channels[j].flags |=
15343 IEEE80211_CHAN_DISABLED;
15344 continue;
15345 }
15346 }
15347 }
15348 /*Initialise the supported cipher suite details */
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053015349 if (pCfg->gcmp_enabled) {
15350 cipher_suites = qdf_mem_malloc(sizeof(hdd_cipher_suites) +
15351 sizeof(hdd_gcmp_cipher_suits));
15352 if (cipher_suites == NULL) {
15353 hdd_err("Not enough memory for cipher suites");
15354 return -ENOMEM;
15355 }
15356 wiphy->n_cipher_suites = QDF_ARRAY_SIZE(hdd_cipher_suites) +
15357 QDF_ARRAY_SIZE(hdd_gcmp_cipher_suits);
15358 qdf_mem_copy(cipher_suites, &hdd_cipher_suites,
15359 sizeof(hdd_cipher_suites));
15360 qdf_mem_copy(cipher_suites + QDF_ARRAY_SIZE(hdd_cipher_suites),
15361 &hdd_gcmp_cipher_suits,
15362 sizeof(hdd_gcmp_cipher_suits));
15363 } else {
15364 cipher_suites = qdf_mem_malloc(sizeof(hdd_cipher_suites));
15365 if (cipher_suites == NULL) {
15366 hdd_err("Not enough memory for cipher suites");
15367 return -ENOMEM;
15368 }
15369 wiphy->n_cipher_suites = QDF_ARRAY_SIZE(hdd_cipher_suites);
15370 qdf_mem_copy(cipher_suites, &hdd_cipher_suites,
15371 sizeof(hdd_cipher_suites));
15372 }
15373 wiphy->cipher_suites = cipher_suites;
15374 cipher_suites = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015375 /*signal strength in mBm (100*dBm) */
15376 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
15377 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
15378
Anurag Chouhan6d760662016-02-20 16:05:43 +053015379 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015380 wiphy->n_vendor_commands =
15381 ARRAY_SIZE(hdd_wiphy_vendor_commands);
15382 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
15383
15384 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
15385 wiphy->n_vendor_events =
15386 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
15387 }
15388
Srinivas Girigowda576b2352017-08-25 14:44:26 -070015389 if (pCfg->enableDFSMasterCap)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015390 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015391
15392 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
15393
15394#ifdef QCA_HT_2040_COEX
15395 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
15396#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053015397 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080015398
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053015399#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) || \
wadesonga75734c2017-02-07 16:03:25 +080015400 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
15401 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
15402 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
15403 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
15404#endif
15405
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015406 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080015407 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Kiran Kumar Lokered547fdd2017-09-13 17:20:55 -070015408 if (pCfg->enable_mac_spoofing)
15409 wlan_hdd_cfg80211_scan_randomization_init(wiphy);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015410
Dustin Browne74003f2018-03-14 12:51:58 -070015411 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015412 return 0;
Ashish Kumar Dhanotiyacc2e0d32017-08-24 20:13:08 +053015413
15414mem_fail:
15415 hdd_err("Not enough memory to allocate channels");
15416 if (wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels != NULL) {
15417 qdf_mem_free(wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels);
15418 wiphy->bands[HDD_NL80211_BAND_2GHZ]->channels = NULL;
15419 }
15420 return -ENOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015421}
15422
Abhishek Singhf512bf32016-05-04 16:47:46 +053015423/**
Yingying Tang80e15f32016-09-27 18:23:01 +080015424 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
15425 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053015426 *
15427 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053015428 * memory allocated in wlan_hdd_cfg80211_init also
15429 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053015430 *
15431 * Return: void
15432 */
15433void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
15434{
15435 int i;
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053015436 const uint32_t *cipher_suites;
Abhishek Singhf512bf32016-05-04 16:47:46 +053015437
Srinivas Girigowda5da651b2017-08-04 11:22:54 -070015438 for (i = 0; i < HDD_NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053015439 if (NULL != wiphy->bands[i] &&
15440 (NULL != wiphy->bands[i]->channels)) {
15441 qdf_mem_free(wiphy->bands[i]->channels);
15442 wiphy->bands[i]->channels = NULL;
15443 }
15444 }
Amar Singhal5cccafe2017-02-15 12:42:58 -080015445
Ashish Kumar Dhanotiyacb14b112018-01-19 19:26:44 +053015446 cipher_suites = wiphy->cipher_suites;
15447 wiphy->cipher_suites = NULL;
15448 wiphy->n_cipher_suites = 0;
15449 qdf_mem_free((uint32_t *)cipher_suites);
15450 cipher_suites = NULL;
Abhishek Singh3e6172f2016-05-04 16:56:48 +053015451 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053015452}
15453
Yingying Tang80e15f32016-09-27 18:23:01 +080015454/**
15455 * wlan_hdd_update_band_cap() - update capabilities for supported bands
15456 * @hdd_ctx: HDD context
15457 *
15458 * this function will update capabilities for supported bands
15459 *
15460 * Return: void
15461 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070015462static void wlan_hdd_update_band_cap(struct hdd_context *hdd_ctx)
Yingying Tang80e15f32016-09-27 18:23:01 +080015463{
15464 uint32_t val32;
15465 uint16_t val16;
15466 tSirMacHTCapabilityInfo *ht_cap_info;
15467 QDF_STATUS status;
15468
15469 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
15470 if (QDF_STATUS_SUCCESS != status) {
15471 hdd_err("could not get HT capability info");
15472 val32 = 0;
15473 }
15474 val16 = (uint16_t)val32;
15475 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
15476
15477 if (ht_cap_info->txSTBC == true) {
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015478 if (NULL != hdd_ctx->wiphy->bands[HDD_NL80211_BAND_2GHZ])
15479 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_2GHZ]->ht_cap.cap |=
Yingying Tang80e15f32016-09-27 18:23:01 +080015480 IEEE80211_HT_CAP_TX_STBC;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015481 if (NULL != hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ])
15482 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ]->ht_cap.cap |=
Yingying Tang80e15f32016-09-27 18:23:01 +080015483 IEEE80211_HT_CAP_TX_STBC;
15484 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080015485
15486 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015487 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_2GHZ]->
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080015488 vht_cap.vht_supported = 0;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015489 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_2GHZ]->vht_cap.cap = 0;
15490 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ]->
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080015491 vht_cap.vht_supported = 0;
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070015492 hdd_ctx->wiphy->bands[HDD_NL80211_BAND_5GHZ]->vht_cap.cap = 0;
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080015493 }
Yingying Tang80e15f32016-09-27 18:23:01 +080015494}
15495
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015496/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053015497 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015498 * initialization. In wlan_hdd_cfg80211_init, only the
15499 * default values will be initialized. The final initialization
15500 * of all required members can be done here.
15501 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070015502void wlan_hdd_update_wiphy(struct hdd_context *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015503{
Yingying Tang80e15f32016-09-27 18:23:01 +080015504 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
15505
15506 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015507}
15508
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080015509/**
15510 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
15511 * @cfg: hdd cfg
15512 *
15513 * this function update 11n mode in hdd cfg
15514 *
15515 * Return: void
15516 */
15517void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
15518{
15519 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015520 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080015521 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015522 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080015523 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
15524 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
15525 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
15526 cfg->sap_p2p_11ac_override = 0;
15527 }
15528 }
15529}
15530
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015531/* In this function we are registering wiphy. */
15532int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
15533{
Dustin Brown491d54b2018-03-14 12:39:11 -070015534 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015535 /* Register our wiphy dev with cfg80211 */
15536 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070015537 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015538 return -EIO;
15539 }
15540
Dustin Browne74003f2018-03-14 12:51:58 -070015541 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015542 return 0;
15543}
15544
15545/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015546 * HDD function to update wiphy capability based on target offload status.
15547 *
15548 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
15549 * capability even before downloading firmware to the target. In discrete
15550 * case, host will get know certain offload capability (say sched_scan
15551 * caps) only after downloading firmware to the target and target boots up.
15552 * This function is used to override setting done in wlan_hdd_cfg80211_init()
15553 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015554 */
15555void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
15556{
15557#ifdef FEATURE_WLAN_SCAN_PNO
Jeff Johnsonb8944722017-09-03 09:03:19 -070015558 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
15559 struct hdd_config *pCfg = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015560
15561 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
15562 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015563 * have PNO support.
15564 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015565 if (!pCfg->PnoOffload) {
Dustin Brown52ba1ce2017-08-16 12:10:55 -070015566 hdd_wiphy_set_max_sched_scans(wiphy, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015567 wiphy->max_sched_scan_ssids = 0;
15568 wiphy->max_match_sets = 0;
15569 wiphy->max_sched_scan_ie_len = 0;
15570 }
15571#endif
15572}
15573
15574/* This function registers for all frame which supplicant is interested in */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015575int wlan_hdd_cfg80211_register_frames(struct hdd_adapter *adapter)
Wu Gao84d120c2017-03-24 18:46:00 +080015576{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015577 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(adapter);
Wu Gao84d120c2017-03-24 18:46:00 +080015578 /* Register for all P2P action, public action etc frames */
15579 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015580 QDF_STATUS status;
Wu Gao84d120c2017-03-24 18:46:00 +080015581
Dustin Brown491d54b2018-03-14 12:39:11 -070015582 hdd_enter();
Wu Gao84d120c2017-03-24 18:46:00 +080015583
15584 /* Register frame indication call back */
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015585 status = sme_register_mgmt_frame_ind_callback(hHal,
15586 hdd_indicate_mgmt_frame);
15587 if (status != QDF_STATUS_SUCCESS) {
15588 hdd_err("Failed to register hdd_indicate_mgmt_frame");
15589 goto ret_status;
15590 }
Wu Gao84d120c2017-03-24 18:46:00 +080015591
Wu Gao84d120c2017-03-24 18:46:00 +080015592 /* Right now we are registering these frame when driver is getting
15593 * initialized. Once we will move to 2.6.37 kernel, in which we have
15594 * frame register ops, we will move this code as a part of that
15595 */
15596
15597 /* GAS Initial Request */
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015598 status = sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
Wu Gao84d120c2017-03-24 18:46:00 +080015599 (uint8_t *) GAS_INITIAL_REQ,
15600 GAS_INITIAL_REQ_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015601 if (status != QDF_STATUS_SUCCESS) {
15602 hdd_err("Failed to register GAS_INITIAL_REQ");
15603 goto ret_status;
15604 }
Wu Gao84d120c2017-03-24 18:46:00 +080015605
15606 /* GAS Initial Response */
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015607 status = sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
Wu Gao84d120c2017-03-24 18:46:00 +080015608 (uint8_t *) GAS_INITIAL_RSP,
15609 GAS_INITIAL_RSP_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015610 if (status != QDF_STATUS_SUCCESS) {
15611 hdd_err("Failed to register GAS_INITIAL_RSP");
15612 goto dereg_gas_initial_req;
15613 }
Wu Gao84d120c2017-03-24 18:46:00 +080015614
15615 /* GAS Comeback Request */
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015616 status = sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
Wu Gao84d120c2017-03-24 18:46:00 +080015617 (uint8_t *) GAS_COMEBACK_REQ,
15618 GAS_COMEBACK_REQ_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015619 if (status != QDF_STATUS_SUCCESS) {
15620 hdd_err("Failed to register GAS_COMEBACK_REQ");
15621 goto dereg_gas_initial_rsp;
15622 }
Wu Gao84d120c2017-03-24 18:46:00 +080015623
15624 /* GAS Comeback Response */
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015625 status = sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
Wu Gao84d120c2017-03-24 18:46:00 +080015626 (uint8_t *) GAS_COMEBACK_RSP,
15627 GAS_COMEBACK_RSP_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015628 if (status != QDF_STATUS_SUCCESS) {
15629 hdd_err("Failed to register GAS_COMEBACK_RSP");
15630 goto dereg_gas_comeback_req;
15631 }
Wu Gao84d120c2017-03-24 18:46:00 +080015632
15633 /* WNM BSS Transition Request frame */
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015634 status = sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
Wu Gao84d120c2017-03-24 18:46:00 +080015635 (uint8_t *) WNM_BSS_ACTION_FRAME,
15636 WNM_BSS_ACTION_FRAME_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015637 if (status != QDF_STATUS_SUCCESS) {
15638 hdd_err("Failed to register WNM_BSS_ACTION_FRAME");
15639 goto dereg_gas_comeback_rsp;
15640 }
Wu Gao84d120c2017-03-24 18:46:00 +080015641
15642 /* WNM-Notification */
Jeff Johnson1b780e42017-10-31 14:11:45 -070015643 status = sme_register_mgmt_frame(hHal, adapter->session_id, type,
Wu Gao84d120c2017-03-24 18:46:00 +080015644 (uint8_t *) WNM_NOTIFICATION_FRAME,
15645 WNM_NOTIFICATION_FRAME_SIZE);
Ganesh Kondabattini0dc1a6e2017-07-29 12:59:19 +053015646 if (status != QDF_STATUS_SUCCESS) {
15647 hdd_err("Failed to register WNM_NOTIFICATION_FRAME");
15648 goto dereg_wnm_bss_action_frm;
15649 }
15650
15651dereg_wnm_bss_action_frm:
15652 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
15653 (uint8_t *) WNM_BSS_ACTION_FRAME,
15654 WNM_BSS_ACTION_FRAME_SIZE);
15655dereg_gas_comeback_rsp:
15656 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
15657 (uint8_t *) GAS_COMEBACK_RSP,
15658 GAS_COMEBACK_RSP_SIZE);
15659dereg_gas_comeback_req:
15660 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
15661 (uint8_t *) GAS_COMEBACK_REQ,
15662 GAS_COMEBACK_REQ_SIZE);
15663dereg_gas_initial_rsp:
15664 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
15665 (uint8_t *) GAS_INITIAL_RSP,
15666 GAS_INITIAL_RSP_SIZE);
15667dereg_gas_initial_req:
15668 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
15669 (uint8_t *) GAS_INITIAL_REQ,
15670 GAS_INITIAL_REQ_SIZE);
15671ret_status:
15672 return qdf_status_to_os_return(status);
Wu Gao84d120c2017-03-24 18:46:00 +080015673}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015674
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015675void wlan_hdd_cfg80211_deregister_frames(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015676{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015677 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015678 /* Register for all P2P action, public action etc frames */
15679 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
15680
Dustin Brown491d54b2018-03-14 12:39:11 -070015681 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015682
15683 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015684 * initialized. Once we will move to 2.6.37 kernel, in which we have
15685 * frame register ops, we will move this code as a part of that
15686 */
15687
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015688 /* GAS Initial Request */
15689
15690 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
15691 (uint8_t *) GAS_INITIAL_REQ,
15692 GAS_INITIAL_REQ_SIZE);
15693
15694 /* GAS Initial Response */
15695 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
15696 (uint8_t *) GAS_INITIAL_RSP,
15697 GAS_INITIAL_RSP_SIZE);
15698
15699 /* GAS Comeback Request */
15700 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
15701 (uint8_t *) GAS_COMEBACK_REQ,
15702 GAS_COMEBACK_REQ_SIZE);
15703
15704 /* GAS Comeback Response */
15705 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
15706 (uint8_t *) GAS_COMEBACK_RSP,
15707 GAS_COMEBACK_RSP_SIZE);
15708
15709 /* P2P Public Action */
15710 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
15711 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
15712 P2P_PUBLIC_ACTION_FRAME_SIZE);
15713
15714 /* P2P Action */
15715 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
15716 (uint8_t *) P2P_ACTION_FRAME,
15717 P2P_ACTION_FRAME_SIZE);
15718
15719 /* WNM-Notification */
Jeff Johnson1b780e42017-10-31 14:11:45 -070015720 sme_deregister_mgmt_frame(hHal, adapter->session_id, type,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015721 (uint8_t *) WNM_NOTIFICATION_FRAME,
15722 WNM_NOTIFICATION_FRAME_SIZE);
15723}
15724
15725#ifdef FEATURE_WLAN_WAPI
Jeff Johnsonfee20aa2017-10-30 21:33:14 -070015726void wlan_hdd_cfg80211_set_key_wapi(struct hdd_adapter *adapter,
15727 uint8_t key_index,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015728 const uint8_t *mac_addr, const uint8_t *key,
15729 int key_Len)
15730{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015731 tCsrRoamSetKey setKey;
15732 bool isConnected = true;
15733 int status = 0;
Krunal Sonibfd05492017-10-03 15:48:37 -070015734 uint32_t roamId = INVALID_ROAM_ID;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015735 uint8_t *pKeyPtr = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015736
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015737 hdd_debug("Device_mode %s(%d)",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015738 hdd_device_mode_to_string(adapter->device_mode),
15739 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015740
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015741 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015742 setKey.keyId = key_index; /* Store Key ID */
15743 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
15744 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
15745 setKey.paeRole = 0; /* the PAE role */
Srinivas Girigowda576b2352017-08-25 14:44:26 -070015746 if (!mac_addr || is_broadcast_ether_addr(mac_addr))
Anurag Chouhanc5548422016-02-24 18:33:27 +053015747 qdf_set_macaddr_broadcast(&setKey.peerMac);
Srinivas Girigowda576b2352017-08-25 14:44:26 -070015748 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015749 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda576b2352017-08-25 14:44:26 -070015750
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015751 setKey.keyLength = key_Len;
15752 pKeyPtr = setKey.Key;
15753 memcpy(pKeyPtr, key, key_Len);
15754
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015755 hdd_debug("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015756
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015757 if (isConnected) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015758 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -070015759 adapter->session_id, &setKey, &roamId);
Jeff Johnsonfee20aa2017-10-30 21:33:14 -070015760 if (status != 0)
15761 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015762 }
15763}
15764#endif /* FEATURE_WLAN_WAPI */
15765
Krunal Soni364e0872017-05-10 21:24:34 -070015766bool wlan_hdd_is_ap_supports_immediate_power_save(uint8_t *ies, int length)
15767{
Naveen Rawat08db88f2017-09-08 15:07:48 -070015768 const uint8_t *vendor_ie;
Krunal Soni364e0872017-05-10 21:24:34 -070015769
15770 if (length < 2) {
15771 hdd_debug("bss size is less than expected");
15772 return true;
15773 }
15774 if (!ies) {
15775 hdd_debug("invalid IE pointer");
15776 return true;
15777 }
Naveen Rawat08db88f2017-09-08 15:07:48 -070015778 vendor_ie = wlan_get_vendor_ie_ptr_from_oui(VENDOR1_AP_OUI_TYPE,
Krunal Soni364e0872017-05-10 21:24:34 -070015779 VENDOR1_AP_OUI_TYPE_SIZE, ies, length);
15780 if (vendor_ie) {
15781 hdd_debug("AP can't support immediate powersave. defer it");
15782 return false;
15783 }
15784 return true;
15785}
15786
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015787/*
15788 * FUNCTION: wlan_hdd_validate_operation_channel
15789 * called by wlan_hdd_cfg80211_start_bss() and
15790 * wlan_hdd_set_channel()
15791 * This function validates whether given channel is part of valid
15792 * channel list.
15793 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015794QDF_STATUS wlan_hdd_validate_operation_channel(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015795 int channel)
15796{
15797
15798 uint32_t num_ch = 0;
15799 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
15800 u32 indx = 0;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015801 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015802 uint8_t fValidChannel = false, count = 0;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015803 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(adapter))->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015804
15805 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
15806
15807 if (hdd_pConfig_ini->sapAllowAllChannel) {
15808 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080015809 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070015810 if (channel == WLAN_REG_CH_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015811 fValidChannel = true;
15812 break;
15813 }
15814 }
15815 if (fValidChannel != true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015816 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015817 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015818 }
15819 } else {
15820 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
15821 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070015822 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015823 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015824 }
15825 for (indx = 0; indx < num_ch; indx++) {
Srinivas Girigowda576b2352017-08-25 14:44:26 -070015826 if (channel == valid_ch[indx])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015827 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015828 }
15829
15830 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015831 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015832 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015833 }
15834 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015835 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015836
15837}
15838
15839#ifdef DHCP_SERVER_OFFLOAD
Jeff Johnson9c4f93d2017-10-04 08:56:22 -070015840static void wlan_hdd_set_dhcp_server_offload(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015841{
Jeff Johnson9c4f93d2017-10-04 08:56:22 -070015842 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015843 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
15844 uint8_t numEntries = 0;
15845 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
15846 uint8_t num;
15847 uint32_t temp;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070015848
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015849 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015850 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070015851 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015852 return;
15853 }
Jeff Johnson1b780e42017-10-31 14:11:45 -070015854 pDhcpSrvInfo->vdev_id = adapter->session_id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015855 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
Jeff Johnsonb8944722017-09-03 09:03:19 -070015856 pDhcpSrvInfo->dhcpClientNum = hdd_ctx->config->dhcpMaxNumClients;
15857 hdd_string_to_u8_array(hdd_ctx->config->dhcpServerIP,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015858 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
15859 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnsonb8944722017-09-03 09:03:19 -070015860 hdd_err("Incorrect IP address (%s) assigned for DHCP server!", hdd_ctx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015861 goto end;
15862 }
15863 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnsonb8944722017-09-03 09:03:19 -070015864 hdd_err("Invalid IP address (%s)! It could NOT be multicast IP address!", hdd_ctx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015865 goto end;
15866 }
15867 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnsonb8944722017-09-03 09:03:19 -070015868 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 -080015869 goto end;
15870 }
15871 for (num = 0; num < numEntries; num++) {
15872 temp = srv_ip[num];
15873 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
15874 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015875 if (QDF_STATUS_SUCCESS !=
Jeff Johnsonb8944722017-09-03 09:03:19 -070015876 sme_set_dhcp_srv_offload(hdd_ctx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070015877 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015878 goto end;
15879 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015880 hdd_debug("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015881end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015882 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015883}
15884#endif /* DHCP_SERVER_OFFLOAD */
15885
15886static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
15887 struct net_device *dev,
15888 struct bss_parameters *params)
15889{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015890 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
15891 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015892 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053015893 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015894
Dustin Brown491d54b2018-03-14 12:39:11 -070015895 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015896
Anurag Chouhan6d760662016-02-20 16:05:43 +053015897 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070015898 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015899 return -EINVAL;
15900 }
15901
Jeff Johnson1b780e42017-10-31 14:11:45 -070015902 if (wlan_hdd_validate_session_id(adapter->session_id)) {
15903 hdd_err("invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015904 return -EINVAL;
15905 }
15906
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015907 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015908 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
Jeff Johnson1b780e42017-10-31 14:11:45 -070015909 adapter->session_id, params->ap_isolate));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015910 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015911 hdd_device_mode_to_string(adapter->device_mode),
15912 adapter->device_mode, params->ap_isolate);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015913
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015914 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070015915 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015916 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015917 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015918
Jeff Johnsonce2ba702017-10-02 13:30:24 -070015919 if (!(adapter->device_mode == QDF_SAP_MODE ||
15920 adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015921 return -EOPNOTSUPP;
15922 }
15923
15924 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080015925 * want to update this parameter
15926 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015927 if (-1 != params->ap_isolate) {
Jeff Johnsonb9424862017-10-30 08:49:35 -070015928 adapter->session.ap.disable_intrabss_fwd =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015929 !!params->ap_isolate;
15930
Jeff Johnsonb8944722017-09-03 09:03:19 -070015931 qdf_ret_status = sme_ap_disable_intra_bss_fwd(hdd_ctx->hHal,
Jeff Johnson1b780e42017-10-31 14:11:45 -070015932 adapter->session_id,
Jeff Johnsonb9424862017-10-30 08:49:35 -070015933 adapter->session.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015934 ap.
Jeff Johnson82ceb082017-10-27 14:52:42 -070015935 disable_intrabss_fwd);
Srinivas Girigowda576b2352017-08-25 14:44:26 -070015936 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015937 ret = -EINVAL;
Sravan Kumar Kairam858073b2018-03-13 09:03:32 +053015938
15939 ucfg_ipa_set_ap_ibss_fwd(hdd_ctx->hdd_pdev,
15940 adapter->session.ap.
15941 disable_intrabss_fwd);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015942 }
15943
Dustin Browne74003f2018-03-14 12:51:58 -070015944 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015945 return ret;
15946}
15947
Krunal Soni8c37e322016-02-03 16:08:37 -080015948/**
15949 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
15950 * @ndev: pointer to net device provided by supplicant
15951 * @type: type of the interface, upper layer wanted to change
15952 *
15953 * Upper layer provides the new interface mode that needs to be changed
15954 * for given net device
15955 *
15956 * Return: success or failure in terms of integer value
15957 */
15958static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015959 enum nl80211_iftype type)
15960{
Jeff Johnsone5006672017-08-29 14:39:02 -070015961 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070015962 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080015963 struct hdd_config *config = hdd_ctx->config;
Jeff Johnson20227a92018-03-13 09:41:05 -070015964 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015965 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053015966 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015967
Dustin Brown491d54b2018-03-14 12:39:11 -070015968 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015969
Krunal Soni8c37e322016-02-03 16:08:37 -080015970 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015971 hdd_warn("ACS is in progress, don't change iface!");
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070015972 return -EBUSY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015973 }
15974
15975 wdev = ndev->ieee80211_ptr;
Dustin Browndb2a8be2017-12-20 11:49:56 -080015976 hdd_stop_adapter(hdd_ctx, adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080015977 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015978 wdev->iftype = type;
15979 /*Check for sub-string p2p to confirm its a p2p interface */
15980 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080015981 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015982 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080015983 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080015984 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080015985 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015986 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080015987 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015988 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080015989 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015990 }
Jeff Johnsonb9424862017-10-30 08:49:35 -070015991 memset(&adapter->session, 0, sizeof(adapter->session));
Krunal Soni8c37e322016-02-03 16:08:37 -080015992 hdd_set_station_ops(adapter->dev);
Jeff Johnson20227a92018-03-13 09:41:05 -070015993
15994 roam_profile = hdd_roam_profile(adapter);
15995 roam_profile->pAddIEScan = adapter->scan_info.scan_add_ie.addIEdata;
15996 roam_profile->nAddIEScanLength =
Jeff Johnson37fa0402017-10-28 12:42:29 -070015997 adapter->scan_info.scan_add_ie.length;
Krunal Soni8c37e322016-02-03 16:08:37 -080015998 if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib51eec72017-11-20 21:53:01 -080015999 status = hdd_start_station_adapter(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070016000 roam_profile->BSSType = eCSR_BSS_TYPE_START_IBSS;
16001 roam_profile->phyMode =
Krunal Soni8c37e322016-02-03 16:08:37 -080016002 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
16003 }
Dustin Browne74003f2018-03-14 12:51:58 -070016004 hdd_exit();
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070016005
16006 return qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016007}
16008
16009static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
16010 struct net_device *dev,
16011 struct bss_parameters *params)
16012{
16013 int ret;
16014
16015 cds_ssr_protect(__func__);
16016 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
16017 cds_ssr_unprotect(__func__);
16018
16019 return ret;
16020}
16021
Rajeev Kumar98edb772016-01-19 12:42:19 -080016022/**
16023 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
16024 * @wiphy: Pointer to the wiphy structure
16025 * @ndev: Pointer to the net device
16026 * @type: Interface type
16027 * @flags: Flags for change interface
16028 * @params: Pointer to change interface parameters
16029 *
16030 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016031 */
16032static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
16033 struct net_device *ndev,
16034 enum nl80211_iftype type,
16035 u32 *flags,
16036 struct vif_params *params)
16037{
16038 struct wireless_dev *wdev;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016039 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070016040 struct hdd_context *hdd_ctx;
Jeff Johnson61b5e982018-03-15 11:33:31 -070016041 struct csr_roam_profile *roam_profile = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016042 eCsrRoamBssType LastBSSType;
16043 struct hdd_config *pConfig = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016044 int status;
16045
Dustin Brown491d54b2018-03-14 12:39:11 -070016046 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016047
Anurag Chouhan6d760662016-02-20 16:05:43 +053016048 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070016049 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016050 return -EINVAL;
16051 }
16052
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016053 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070016054 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016055 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016056 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016057
Nachiket Kukade08b9f292017-11-17 18:27:37 +053016058 if (cds_is_fw_down()) {
16059 hdd_err("Ignore if FW is already down");
16060 return -EINVAL;
16061 }
16062
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016063 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016064 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
Jeff Johnson1b780e42017-10-31 14:11:45 -070016065 adapter->session_id, type));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016066
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016067 hdd_debug("Device_mode = %d, IFTYPE = 0x%x",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016068 adapter->device_mode, type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016069
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016070 status = hdd_wlan_start_modules(hdd_ctx, adapter, false);
Arun Khandavallifae92942016-08-01 13:31:08 +053016071 if (status) {
16072 hdd_err("Failed to start modules");
16073 return -EINVAL;
16074 }
16075
Jeff Johnsonb8944722017-09-03 09:03:19 -070016076 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016077 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
16078 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070016079 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016080 return -EINVAL;
16081 }
16082
Jeff Johnsonb8944722017-09-03 09:03:19 -070016083 pConfig = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016084 wdev = ndev->ieee80211_ptr;
16085
16086 /* Reset the current device mode bit mask */
Jeff Johnsonb8944722017-09-03 09:03:19 -070016087 policy_mgr_clear_concurrency_mode(hdd_ctx->hdd_psoc,
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016088 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016089
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016090 hdd_notify_teardown_tdls_links(adapter->hdd_vdev);
16091 if ((adapter->device_mode == QDF_STA_MODE) ||
16092 (adapter->device_mode == QDF_P2P_CLIENT_MODE) ||
16093 (adapter->device_mode == QDF_P2P_DEVICE_MODE) ||
16094 (adapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016095
Jeff Johnson20227a92018-03-13 09:41:05 -070016096 roam_profile = hdd_roam_profile(adapter);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016097 LastBSSType = roam_profile->BSSType;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016098
16099 switch (type) {
16100 case NL80211_IFTYPE_STATION:
16101 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080016102 case NL80211_IFTYPE_ADHOC:
16103 if (type == NL80211_IFTYPE_ADHOC) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016104 hdd_deregister_tx_flow_control(adapter);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016105 hdd_debug("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080016106 }
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070016107 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
Krunal Soni8c37e322016-02-03 16:08:37 -080016108 type);
Sandeep Puligilla1e6da362017-04-07 14:16:03 -070016109 if (status) {
16110 hdd_err("Failed to change iface to new mode:%d status %d",
16111 type, status);
16112 return status;
16113 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016114 if (hdd_start_adapter(adapter)) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053016115 hdd_err("Failed to start adapter :%d",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016116 adapter->device_mode);
Arun Khandavallib2f6c262016-08-18 19:07:19 +053016117 return -EINVAL;
16118 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016119 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016120 case NL80211_IFTYPE_AP:
16121 case NL80211_IFTYPE_P2P_GO:
16122 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016123 hdd_debug("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016124 (type ==
16125 NL80211_IFTYPE_AP) ? "SoftAP" :
16126 "P2pGo");
16127
16128 /* Cancel any remain on channel for GO mode */
16129 if (NL80211_IFTYPE_P2P_GO == type) {
16130 wlan_hdd_cancel_existing_remain_on_channel
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016131 (adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016132 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016133
Dustin Browndb2a8be2017-12-20 11:49:56 -080016134 hdd_stop_adapter(hdd_ctx, adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016135 /* De-init the adapter */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016136 hdd_deinit_adapter(hdd_ctx, adapter, true);
Jeff Johnsonb9424862017-10-30 08:49:35 -070016137 memset(&adapter->session, 0,
16138 sizeof(adapter->session));
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016139 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016140 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080016141 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
16142 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016143
16144 /*
16145 * Fw will take care incase of concurrency
16146 */
16147
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016148 if ((QDF_SAP_MODE == adapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016149 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016150 /* To meet Android requirements create
16151 * a randomized MAC address of the
16152 * form 02:1A:11:Fx:xx:xx
16153 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016154 get_random_bytes(&ndev->dev_addr[3], 3);
16155 ndev->dev_addr[0] = 0x02;
16156 ndev->dev_addr[1] = 0x1A;
16157 ndev->dev_addr[2] = 0x11;
16158 ndev->dev_addr[3] |= 0xF0;
Jeff Johnson1e851a12017-10-28 14:36:12 -070016159 memcpy(adapter->mac_addr.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016160 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053016161 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016162 pr_info("wlan: Generated HotSpot BSSID "
16163 MAC_ADDRESS_STR "\n",
16164 MAC_ADDR_ARRAY(ndev->dev_addr));
16165 }
16166
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016167 hdd_set_ap_ops(adapter->dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016168
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016169 if (hdd_start_adapter(adapter)) {
Arun Khandavallifae92942016-08-01 13:31:08 +053016170 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016171 return -EINVAL;
16172 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016173 /* Interface type changed update in wiphy structure */
16174 if (wdev) {
16175 wdev->iftype = type;
16176 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070016177 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016178 return -EINVAL;
16179 }
16180 goto done;
16181 }
16182
16183 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016184 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016185 return -EOPNOTSUPP;
16186 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016187 } else if ((adapter->device_mode == QDF_SAP_MODE) ||
16188 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016189 switch (type) {
16190 case NL80211_IFTYPE_STATION:
16191 case NL80211_IFTYPE_P2P_CLIENT:
16192 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080016193 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
16194 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016195 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016196 return status;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016197 if (hdd_start_adapter(adapter)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016198 hdd_err("Failed to start adapter: %d",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016199 adapter->device_mode);
Arun Khandavallib2f6c262016-08-18 19:07:19 +053016200 return -EINVAL;
16201 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016202 goto done;
16203
16204 case NL80211_IFTYPE_AP:
16205 case NL80211_IFTYPE_P2P_GO:
16206 wdev->iftype = type;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016207 adapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080016208 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016209 goto done;
16210
16211 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016212 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016213 return -EOPNOTSUPP;
16214 }
16215 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016216 hdd_err("Unsupported device mode: %d",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016217 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016218 return -EOPNOTSUPP;
16219 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016220done:
16221 /* Set bitmask based on updated value */
Jeff Johnsonb8944722017-09-03 09:03:19 -070016222 policy_mgr_set_concurrency_mode(hdd_ctx->hdd_psoc,
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016223 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016224
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016225 hdd_lpass_notify_mode_change(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016226
Dustin Browne74003f2018-03-14 12:51:58 -070016227 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016228 return 0;
16229}
16230
Dustin Brown9ed30a52017-08-16 13:59:38 -070016231#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
Rajeev Kumar98edb772016-01-19 12:42:19 -080016232/**
16233 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
16234 * @wiphy: Pointer to the wiphy structure
16235 * @ndev: Pointer to the net device
16236 * @type: Interface type
16237 * @flags: Flags for change interface
16238 * @params: Pointer to change interface parameters
16239 *
16240 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016241 */
16242static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
16243 struct net_device *ndev,
16244 enum nl80211_iftype type,
16245 u32 *flags,
16246 struct vif_params *params)
16247{
16248 int ret;
16249
16250 cds_ssr_protect(__func__);
16251 ret =
16252 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
16253 cds_ssr_unprotect(__func__);
16254
16255 return ret;
16256}
Dustin Brown9ed30a52017-08-16 13:59:38 -070016257#else
16258static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
16259 struct net_device *ndev,
16260 enum nl80211_iftype type,
16261 struct vif_params *params)
16262{
16263 int ret;
16264
16265 cds_ssr_protect(__func__);
16266 ret = __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type,
16267 &params->flags, params);
16268 cds_ssr_unprotect(__func__);
16269
16270 return ret;
16271}
16272#endif /* KERNEL_VERSION(4, 12, 0) */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016273
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016274/**
16275 * __wlan_hdd_change_station() - change station
16276 * @wiphy: Pointer to the wiphy structure
16277 * @dev: Pointer to the net device.
16278 * @mac: bssid
16279 * @params: Pointer to station parameters
16280 *
16281 * Return: 0 for success, error number on failure.
16282 */
16283#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
16284static int __wlan_hdd_change_station(struct wiphy *wiphy,
16285 struct net_device *dev,
16286 const uint8_t *mac,
16287 struct station_parameters *params)
16288#else
16289static int __wlan_hdd_change_station(struct wiphy *wiphy,
16290 struct net_device *dev,
16291 uint8_t *mac,
16292 struct station_parameters *params)
16293#endif
16294{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016295 QDF_STATUS status = QDF_STATUS_SUCCESS;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016296 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070016297 struct hdd_context *hdd_ctx;
Jeff Johnsond377dce2017-10-04 10:32:42 -070016298 struct hdd_station_ctx *sta_ctx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053016299 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016300 int ret;
16301
Dustin Brown491d54b2018-03-14 12:39:11 -070016302 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016303
Anurag Chouhan6d760662016-02-20 16:05:43 +053016304 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016305 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016306 return -EINVAL;
16307 }
16308
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016309 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016310 TRACE_CODE_HDD_CHANGE_STATION,
Jeff Johnson1b780e42017-10-31 14:11:45 -070016311 adapter->session_id, params->listen_interval));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016312
Jeff Johnson1b780e42017-10-31 14:11:45 -070016313 if (wlan_hdd_validate_session_id(adapter->session_id)) {
16314 hdd_err("invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016315 return -EINVAL;
16316 }
16317
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016318 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070016319 ret = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016320 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016321 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016322
Jeff Johnsond377dce2017-10-04 10:32:42 -070016323 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016324
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016325 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016326
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016327 if ((adapter->device_mode == QDF_SAP_MODE) ||
16328 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016329 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
16330 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016331 hdd_softap_change_sta_state(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016332 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080016333 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016334
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016335 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016336 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016337 return -EINVAL;
16338 }
16339 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016340 } else if ((adapter->device_mode == QDF_STA_MODE) ||
16341 (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016342 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud1a28462017-09-06 22:55:48 +080016343#if defined(FEATURE_WLAN_TDLS)
Jeff Johnsonb8944722017-09-03 09:03:19 -070016344 ret = wlan_cfg80211_tdls_update_peer(hdd_ctx->hdd_pdev,
Frank Liud4b2fa02017-03-29 11:46:48 +080016345 dev, mac, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016346#endif
Frank Liud4b2fa02017-03-29 11:46:48 +080016347 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016348 }
Dustin Browne74003f2018-03-14 12:51:58 -070016349 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016350 return ret;
16351}
16352
16353/**
16354 * wlan_hdd_change_station() - cfg80211 change station handler function
16355 * @wiphy: Pointer to the wiphy structure
16356 * @dev: Pointer to the net device.
16357 * @mac: bssid
16358 * @params: Pointer to station parameters
16359 *
16360 * This is the cfg80211 change station handler function which invokes
16361 * the internal function @__wlan_hdd_change_station with
16362 * SSR protection.
16363 *
16364 * Return: 0 for success, error number on failure.
16365 */
16366#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
16367static int wlan_hdd_change_station(struct wiphy *wiphy,
16368 struct net_device *dev,
16369 const u8 *mac,
16370 struct station_parameters *params)
16371#else
16372static int wlan_hdd_change_station(struct wiphy *wiphy,
16373 struct net_device *dev,
16374 u8 *mac,
16375 struct station_parameters *params)
16376#endif
16377{
16378 int ret;
16379
16380 cds_ssr_protect(__func__);
16381 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
16382 cds_ssr_unprotect(__func__);
16383
16384 return ret;
16385}
16386
16387/*
16388 * FUNCTION: __wlan_hdd_cfg80211_add_key
16389 * This function is used to initialize the key information
16390 */
16391static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
16392 struct net_device *ndev,
16393 u8 key_index, bool pairwise,
16394 const u8 *mac_addr,
16395 struct key_params *params)
16396{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016397 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016398 tCsrRoamSetKey setKey;
16399 int status;
Krunal Sonibfd05492017-10-03 15:48:37 -070016400 uint32_t roamId = INVALID_ROAM_ID;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053016401 QDF_STATUS qdf_ret_status;
Jeff Johnsonb8944722017-09-03 09:03:19 -070016402 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016403
Dustin Brown491d54b2018-03-14 12:39:11 -070016404 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016405
Anurag Chouhan6d760662016-02-20 16:05:43 +053016406 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016407 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016408 return -EINVAL;
16409 }
16410
Jeff Johnson1b780e42017-10-31 14:11:45 -070016411 if (wlan_hdd_validate_session_id(adapter->session_id)) {
16412 hdd_err("Invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016413 return -EINVAL;
16414 }
16415
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016416 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016417 TRACE_CODE_HDD_CFG80211_ADD_KEY,
Jeff Johnson1b780e42017-10-31 14:11:45 -070016418 adapter->session_id, params->key_len));
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016419 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070016420 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016421
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016422 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016423 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016424
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016425 hdd_debug("Device_mode %s(%d)",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016426 hdd_device_mode_to_string(adapter->device_mode),
16427 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016428
16429 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016430 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016431
16432 return -EINVAL;
16433 }
16434
16435 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016436 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016437
16438 return -EINVAL;
16439 }
16440
Jeff Johnsonb05f4fd2017-10-18 15:08:21 -070016441 if (CSR_MAX_RSC_LEN < params->seq_len) {
16442 hdd_err("Invalid seq length %d", params->seq_len);
16443
16444 return -EINVAL;
16445 }
16446
16447 hdd_debug("key index %d, key length %d, seq length %d",
16448 key_index, params->key_len, params->seq_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016449
16450 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016451 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016452 setKey.keyId = key_index;
16453 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016454 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Jeff Johnsonb05f4fd2017-10-18 15:08:21 -070016455 qdf_mem_copy(&setKey.keyRsc[0], params->seq, params->seq_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016456
16457 switch (params->cipher) {
16458 case WLAN_CIPHER_SUITE_WEP40:
16459 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
16460 break;
16461
16462 case WLAN_CIPHER_SUITE_WEP104:
16463 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
16464 break;
16465
16466 case WLAN_CIPHER_SUITE_TKIP:
16467 {
16468 u8 *pKey = &setKey.Key[0];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016469
Srinivas Girigowda576b2352017-08-25 14:44:26 -070016470 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016471 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016472
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016473 /* Supplicant sends the 32bytes key in this order
16474 *
16475 * |--------------|----------|----------|
16476 * | Tk1 |TX-MIC | RX Mic |
16477 * |--------------|----------|----------|
16478 * <---16bytes---><--8bytes--><--8bytes-->
16479 *
16480 * Sme expects the 32 bytes key to be in the below order
16481 *
16482 * |--------------|----------|----------|
16483 * | Tk1 |RX-MIC | TX Mic |
16484 * |--------------|----------|----------|
16485 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016486 */
16487 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016488 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016489
16490 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016491 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016492
16493 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016494 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016495
16496 break;
16497 }
16498
16499 case WLAN_CIPHER_SUITE_CCMP:
16500 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
16501 break;
16502
16503#ifdef FEATURE_WLAN_WAPI
16504 case WLAN_CIPHER_SUITE_SMS4:
16505 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016506 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016507 wlan_hdd_cfg80211_set_key_wapi(adapter, key_index,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016508 mac_addr, params->key,
16509 params->key_len);
16510 return 0;
16511 }
16512#endif
16513
16514#ifdef FEATURE_WLAN_ESE
16515 case WLAN_CIPHER_SUITE_KRK:
16516 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
16517 break;
16518#ifdef WLAN_FEATURE_ROAM_OFFLOAD
16519 case WLAN_CIPHER_SUITE_BTK:
16520 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
16521 break;
16522#endif
16523#endif
16524
16525#ifdef WLAN_FEATURE_11W
16526 case WLAN_CIPHER_SUITE_AES_CMAC:
16527 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
16528 break;
Padma, Santhosh Kumar4117d7a2017-12-20 17:39:33 +053016529#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
16530 case WLAN_CIPHER_SUITE_BIP_GMAC_128:
16531 setKey.encType = eCSR_ENCRYPT_TYPE_AES_GMAC_128;
16532 break;
16533 case WLAN_CIPHER_SUITE_BIP_GMAC_256:
16534 setKey.encType = eCSR_ENCRYPT_TYPE_AES_GMAC_256;
16535 break;
16536#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016537#endif
Mukul Sharma05504ac2017-06-08 12:35:53 +053016538 case WLAN_CIPHER_SUITE_GCMP:
16539 setKey.encType = eCSR_ENCRYPT_TYPE_AES_GCMP;
16540 break;
16541 case WLAN_CIPHER_SUITE_GCMP_256:
16542 setKey.encType = eCSR_ENCRYPT_TYPE_AES_GCMP_256;
16543 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016544
16545 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016546 hdd_err("Unsupported cipher type: %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016547 return -EOPNOTSUPP;
16548 }
16549
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016550 hdd_debug("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016551
16552 if (!pairwise) {
16553 /* set group key */
Jeff Johnson96aa2ac2017-10-18 15:55:36 -070016554 hdd_debug("setting Broadcast key");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016555 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053016556 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016557 } else {
16558 /* set pairwise key */
Jeff Johnson96aa2ac2017-10-18 15:55:36 -070016559 hdd_debug("setting pairwise key");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016560 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016561 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016562 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016563 if ((QDF_IBSS_MODE == adapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016564 /* if a key is already installed, block all subsequent ones */
Jeff Johnsonb9424862017-10-30 08:49:35 -070016565 if (adapter->session.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016566 hdd_debug("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016567 return 0;
16568 }
16569
16570 setKey.keyDirection = eSIR_TX_RX;
16571 /*Set the group key */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016572 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -070016573 adapter->session_id, &setKey, &roamId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016574
16575 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016576 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016577 return -EINVAL;
16578 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016579 /* Save the keys here and call sme_roam_set_key for setting
16580 * the PTK after peer joins the IBSS network
16581 */
Jeff Johnsonb9424862017-10-30 08:49:35 -070016582 qdf_mem_copy(&adapter->session.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016583 &setKey, sizeof(tCsrRoamSetKey));
16584
Jeff Johnsonb9424862017-10-30 08:49:35 -070016585 adapter->session.station.ibss_enc_key_installed = 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016586 return status;
16587 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016588 if ((adapter->device_mode == QDF_SAP_MODE) ||
16589 (adapter->device_mode == QDF_P2P_GO_MODE)) {
Nachiket Kukaded9152832017-10-16 16:18:22 +053016590 struct hdd_hostapd_state *hostapd_state =
16591 WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
16592 struct hdd_ap_ctx *ap_ctx =
16593 WLAN_HDD_GET_AP_CTX_PTR(adapter);
16594
Jeff Johnson0f9f87b2017-10-28 09:21:06 -070016595 if (hostapd_state->bss_state == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070016596 status = wlansap_set_key_sta(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016597 WLAN_HDD_GET_SAP_CTX_PTR(adapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016598 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016599 hdd_err("wlansap_set_key_sta failed status: %d",
16600 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016601 }
16602 }
16603
Jeff Johnson413c15f2017-10-27 18:56:35 -070016604 /* Save the key in ap ctx for use on START_BSS and restart */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016605 if (pairwise ||
16606 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
16607 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Jeff Johnson3d731362017-10-27 19:06:41 -070016608 qdf_mem_copy(&ap_ctx->wep_key[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016609 sizeof(tCsrRoamSetKey));
16610 else
Jeff Johnson413c15f2017-10-27 18:56:35 -070016611 qdf_mem_copy(&ap_ctx->group_key, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016612 sizeof(tCsrRoamSetKey));
16613
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016614 } else if ((adapter->device_mode == QDF_STA_MODE) ||
16615 (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Jeff Johnsond377dce2017-10-04 10:32:42 -070016616 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016617 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070016618 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016619
16620 if (!pairwise) {
16621 /* set group key */
Jeff Johnsonaf2ae4b2017-11-01 11:38:50 -070016622 if (sta_ctx->roam_info.defer_key_complete) {
Jeff Johnson96aa2ac2017-10-18 15:55:36 -070016623 hdd_debug("Perform Set key Complete");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016624 hdd_perform_roam_set_key_complete(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016625 }
16626 }
16627
Jeff Johnson20227a92018-03-13 09:41:05 -070016628 roam_profile = hdd_roam_profile(adapter);
16629 roam_profile->Keys.KeyLength[key_index] = params->key_len;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016630
Jeff Johnson20227a92018-03-13 09:41:05 -070016631 roam_profile->Keys.defaultIndex = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016632
Jeff Johnson20227a92018-03-13 09:41:05 -070016633 qdf_mem_copy(&roam_profile->Keys.KeyMaterial[key_index][0],
16634 params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016635
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016636 hdd_debug("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016637 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
16638 setKey.keyDirection);
16639
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016640 /* The supplicant may attempt to set the PTK once
16641 * pre-authentication is done. Save the key in the
16642 * UMAC and include it in the ADD BSS request
16643 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016644 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -070016645 adapter->session_id, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053016646 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016647 hdd_debug("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016648 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053016649 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016650 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016651 return -EINVAL;
16652 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016653
16654 /* issue set key request to SME */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016655 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -070016656 adapter->session_id, &setKey, &roamId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016657
16658 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016659 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016660 return -EINVAL;
16661 }
16662
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016663 /* in case of IBSS as there was no information
16664 * available about WEP keys during IBSS join, group
16665 * key intialized with NULL key, so re-initialize
16666 * group key with correct value
16667 */
Jeff Johnson20227a92018-03-13 09:41:05 -070016668 if ((eCSR_BSS_TYPE_START_IBSS == roam_profile->BSSType) &&
Jeff Johnson37ecea42018-03-18 17:54:40 -070016669 !((HDD_AUTH_KEY_MGMT_802_1X ==
16670 (sta_ctx->auth_key_mgmt & HDD_AUTH_KEY_MGMT_802_1X))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016671 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
Jeff Johnsond377dce2017-10-04 10:32:42 -070016672 sta_ctx->conn_info.authType)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016673 )
16674 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
16675 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
16676 )
16677 ) {
16678 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053016679 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016680
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016681 hdd_debug("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016682 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
16683 setKey.keyDirection);
16684
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016685 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -070016686 adapter->session_id, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016687 &roamId);
16688
16689 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016690 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016691 return -EINVAL;
16692 }
16693 }
16694 }
Dustin Browne74003f2018-03-14 12:51:58 -070016695 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016696 return 0;
16697}
16698
16699static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
16700 struct net_device *ndev,
16701 u8 key_index, bool pairwise,
16702 const u8 *mac_addr,
16703 struct key_params *params)
16704{
16705 int ret;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070016706
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016707 cds_ssr_protect(__func__);
16708 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
16709 mac_addr, params);
16710 cds_ssr_unprotect(__func__);
16711
16712 return ret;
16713}
16714
16715/*
16716 * FUNCTION: __wlan_hdd_cfg80211_get_key
16717 * This function is used to get the key information
16718 */
16719static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
16720 struct net_device *ndev,
16721 u8 key_index, bool pairwise,
16722 const u8 *mac_addr, void *cookie,
16723 void (*callback)(void *cookie,
16724 struct key_params *)
16725 )
16726{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016727 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnson61b5e982018-03-15 11:33:31 -070016728 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016729 struct key_params params;
16730
Dustin Brown491d54b2018-03-14 12:39:11 -070016731 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016732
Anurag Chouhan6d760662016-02-20 16:05:43 +053016733 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016734 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016735 return -EINVAL;
16736 }
16737
Jiachao Wud58cfc92017-12-27 14:15:23 +080016738 if (wlan_hdd_validate_session_id(adapter->session_id)) {
16739 hdd_err("Invalid session id: %d", adapter->session_id);
16740 return -EINVAL;
16741 }
16742
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016743 hdd_debug("Device_mode %s(%d)",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016744 hdd_device_mode_to_string(adapter->device_mode),
16745 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016746
16747 memset(&params, 0, sizeof(params));
16748
16749 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016750 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016751 return -EINVAL;
16752 }
16753
Nachiket Kukaded9152832017-10-16 16:18:22 +053016754 if ((adapter->device_mode == QDF_SAP_MODE) ||
16755 (adapter->device_mode == QDF_P2P_GO_MODE)) {
16756 struct hdd_ap_ctx *ap_ctx =
16757 WLAN_HDD_GET_AP_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070016758
Nachiket Kukaded9152832017-10-16 16:18:22 +053016759 roam_profile =
16760 wlan_sap_get_roam_profile(ap_ctx->sap_context);
16761 } else {
Jeff Johnson20227a92018-03-13 09:41:05 -070016762 roam_profile = hdd_roam_profile(adapter);
Nachiket Kukaded9152832017-10-16 16:18:22 +053016763 }
16764
Jiachao Wud58cfc92017-12-27 14:15:23 +080016765 if (roam_profile == NULL) {
16766 hdd_err("Get roam profile failed!");
16767 return -EINVAL;
16768 }
16769
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016770 switch (roam_profile->EncryptionType.encryptionType[0]) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016771 case eCSR_ENCRYPT_TYPE_NONE:
16772 params.cipher = IW_AUTH_CIPHER_NONE;
16773 break;
16774
16775 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
16776 case eCSR_ENCRYPT_TYPE_WEP40:
16777 params.cipher = WLAN_CIPHER_SUITE_WEP40;
16778 break;
16779
16780 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
16781 case eCSR_ENCRYPT_TYPE_WEP104:
16782 params.cipher = WLAN_CIPHER_SUITE_WEP104;
16783 break;
16784
16785 case eCSR_ENCRYPT_TYPE_TKIP:
16786 params.cipher = WLAN_CIPHER_SUITE_TKIP;
16787 break;
16788
16789 case eCSR_ENCRYPT_TYPE_AES:
16790 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
16791 break;
Mukul Sharma05504ac2017-06-08 12:35:53 +053016792 case eCSR_ENCRYPT_TYPE_AES_GCMP:
16793 params.cipher = WLAN_CIPHER_SUITE_GCMP;
16794 break;
16795 case eCSR_ENCRYPT_TYPE_AES_GCMP_256:
16796 params.cipher = WLAN_CIPHER_SUITE_GCMP_256;
16797 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016798 default:
16799 params.cipher = IW_AUTH_CIPHER_NONE;
16800 break;
16801 }
16802
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016803 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016804 TRACE_CODE_HDD_CFG80211_GET_KEY,
Jeff Johnson1b780e42017-10-31 14:11:45 -070016805 adapter->session_id, params.cipher));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016806
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016807 params.key_len = roam_profile->Keys.KeyLength[key_index];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016808 params.seq_len = 0;
16809 params.seq = NULL;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070016810 params.key = &roam_profile->Keys.KeyMaterial[key_index][0];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016811 callback(cookie, &params);
16812
Dustin Browne74003f2018-03-14 12:51:58 -070016813 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016814 return 0;
16815}
16816
16817static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
16818 struct net_device *ndev,
16819 u8 key_index, bool pairwise,
16820 const u8 *mac_addr, void *cookie,
16821 void (*callback)(void *cookie,
16822 struct key_params *)
16823 )
16824{
16825 int ret;
16826
16827 cds_ssr_protect(__func__);
16828 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
16829 mac_addr, cookie, callback);
16830 cds_ssr_unprotect(__func__);
16831
16832 return ret;
16833}
16834
16835/**
16836 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
16837 * @wiphy: wiphy interface context
16838 * @ndev: pointer to net device
16839 * @key_index: Key index used in 802.11 frames
16840 * @unicast: true if it is unicast key
16841 * @multicast: true if it is multicast key
16842 *
16843 * This function is required for cfg80211_ops API.
16844 * It is used to delete the key information
16845 * Underlying hardware implementation does not have API to delete the
16846 * encryption key. It is automatically deleted when the peer is
16847 * removed. Hence this function currently does nothing.
16848 * Future implementation may interprete delete key operation to
16849 * replacing the key with a random junk value, effectively making it
16850 * useless.
16851 *
16852 * Return: status code, always 0.
16853 */
16854
16855static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
16856 struct net_device *ndev,
16857 u8 key_index,
16858 bool pairwise, const u8 *mac_addr)
16859{
Dustin Browne74003f2018-03-14 12:51:58 -070016860 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016861 return 0;
16862}
16863
16864/**
16865 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
16866 * @wiphy: Pointer to wiphy structure.
16867 * @dev: Pointer to net_device structure.
16868 * @key_index: key index
16869 * @pairwise: pairwise
16870 * @mac_addr: mac address
16871 *
16872 * This is the cfg80211 delete key handler function which invokes
16873 * the internal function @__wlan_hdd_cfg80211_del_key with
16874 * SSR protection.
16875 *
16876 * Return: 0 for success, error number on failure.
16877 */
16878static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
16879 struct net_device *dev,
16880 u8 key_index,
16881 bool pairwise, const u8 *mac_addr)
16882{
16883 int ret;
16884
16885 cds_ssr_protect(__func__);
16886 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
16887 pairwise, mac_addr);
16888 cds_ssr_unprotect(__func__);
16889
16890 return ret;
16891}
16892
Hu Wangc3148842017-06-20 19:03:29 +080016893#ifdef FEATURE_WLAN_WAPI
16894static bool hdd_is_wapi_enc_type(eCsrEncryptionType ucEncryptionType)
16895{
16896 if (ucEncryptionType == eCSR_ENCRYPT_TYPE_WPI)
16897 return true;
16898
16899 return false;
16900}
16901#else
16902static bool hdd_is_wapi_enc_type(eCsrEncryptionType ucEncryptionType)
16903{
16904 return false;
16905}
16906#endif
16907
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016908/*
16909 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
16910 * This function is used to set the default tx key index
16911 */
16912static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
16913 struct net_device *ndev,
16914 u8 key_index,
16915 bool unicast, bool multicast)
16916{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016917 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070016918 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016919 int status;
16920
Dustin Brown491d54b2018-03-14 12:39:11 -070016921 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016922
Anurag Chouhan6d760662016-02-20 16:05:43 +053016923 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070016924 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016925 return -EINVAL;
16926 }
16927
Jeff Johnson1b780e42017-10-31 14:11:45 -070016928 if (wlan_hdd_validate_session_id(adapter->session_id)) {
16929 hdd_err("Invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016930 return -EINVAL;
16931 }
16932
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016933 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016934 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
Jeff Johnson1b780e42017-10-31 14:11:45 -070016935 adapter->session_id, key_index));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016936
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016937 hdd_debug("Device_mode %s(%d) key_index = %d",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016938 hdd_device_mode_to_string(adapter->device_mode),
16939 adapter->device_mode, key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016940
16941 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016942 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016943 return -EINVAL;
16944 }
16945
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016946 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070016947 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016948
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016949 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016950 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016951
Jeff Johnsonce2ba702017-10-02 13:30:24 -070016952 if ((adapter->device_mode == QDF_STA_MODE) ||
16953 (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Nachiket Kukaded9152832017-10-16 16:18:22 +053016954 struct hdd_station_ctx *sta_ctx =
16955 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070016956 struct csr_roam_profile *roam_profile;
16957
16958 roam_profile = hdd_roam_profile(adapter);
Nachiket Kukaded9152832017-10-16 16:18:22 +053016959
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016960 if ((eCSR_ENCRYPT_TYPE_TKIP !=
Jeff Johnsond377dce2017-10-04 10:32:42 -070016961 sta_ctx->conn_info.ucEncryptionType) &&
Hu Wangc3148842017-06-20 19:03:29 +080016962 !hdd_is_wapi_enc_type(
Jeff Johnsond377dce2017-10-04 10:32:42 -070016963 sta_ctx->conn_info.ucEncryptionType) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016964 (eCSR_ENCRYPT_TYPE_AES !=
Jeff Johnsond377dce2017-10-04 10:32:42 -070016965 sta_ctx->conn_info.ucEncryptionType) &&
Mukul Sharma05504ac2017-06-08 12:35:53 +053016966 (eCSR_ENCRYPT_TYPE_AES_GCMP !=
Jeff Johnsond377dce2017-10-04 10:32:42 -070016967 sta_ctx->conn_info.ucEncryptionType) &&
Mukul Sharma05504ac2017-06-08 12:35:53 +053016968 (eCSR_ENCRYPT_TYPE_AES_GCMP_256 !=
Jeff Johnsond377dce2017-10-04 10:32:42 -070016969 sta_ctx->conn_info.ucEncryptionType)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016970 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016971 * then update the default key index
16972 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016973
16974 tCsrRoamSetKey setKey;
Krunal Sonibfd05492017-10-03 15:48:37 -070016975 uint32_t roamId = INVALID_ROAM_ID;
Jeff Johnson20227a92018-03-13 09:41:05 -070016976 tCsrKeys *Keys = &roam_profile->Keys;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016977
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016978 hdd_debug("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016979
16980 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016981 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016982 setKey.keyId = key_index;
16983 setKey.keyLength = Keys->KeyLength[key_index];
16984
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016985 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016986 &Keys->KeyMaterial[key_index][0],
16987 Keys->KeyLength[key_index]);
16988
16989 setKey.keyDirection = eSIR_TX_RX;
16990
Anurag Chouhanc5548422016-02-24 18:33:27 +053016991 qdf_copy_macaddr(&setKey.peerMac,
Jeff Johnsond377dce2017-10-04 10:32:42 -070016992 &sta_ctx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016993
16994 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
Jeff Johnson20227a92018-03-13 09:41:05 -070016995 roam_profile->EncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016996 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080016997 /* In the case of dynamic wep
16998 * supplicant hardcodes DWEP type to
16999 * eCSR_ENCRYPT_TYPE_WEP104 even
17000 * though ap is configured for WEP-40
17001 * encryption. In this canse the key
17002 * length is 5 but the encryption type
17003 * is 104 hence checking the key
17004 * lenght(5) and encryption type(104)
17005 * and switching encryption type to 40
17006 */
Jeff Johnson20227a92018-03-13 09:41:05 -070017007 roam_profile->EncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017008 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
Jeff Johnson20227a92018-03-13 09:41:05 -070017009 roam_profile->mcEncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017010 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
17011 }
17012
17013 setKey.encType =
Jeff Johnson20227a92018-03-13 09:41:05 -070017014 roam_profile->EncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017015 encryptionType[0];
17016
17017 /* Issue set key request */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017018 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -070017019 adapter->session_id, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017020 &roamId);
17021
17022 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017023 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017024 status);
17025 return -EINVAL;
17026 }
17027 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017028 } else if (QDF_SAP_MODE == adapter->device_mode) {
Nachiket Kukaded9152832017-10-16 16:18:22 +053017029 struct hdd_ap_ctx *ap_ctx =
17030 WLAN_HDD_GET_AP_CTX_PTR(adapter);
Jeff Johnson61b5e982018-03-15 11:33:31 -070017031 struct csr_roam_profile *profile =
Nachiket Kukaded9152832017-10-16 16:18:22 +053017032 wlan_sap_get_roam_profile(ap_ctx->sap_context);
17033
17034 if (!profile) {
17035 hdd_err("Failed to get SAP Roam Profile");
17036 return -EINVAL;
17037 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017038 /* In SoftAp mode setting key direction for default mode */
17039 if ((eCSR_ENCRYPT_TYPE_TKIP !=
Nachiket Kukaded9152832017-10-16 16:18:22 +053017040 profile->EncryptionType.encryptionType[0]) &&
Mukul Sharma05504ac2017-06-08 12:35:53 +053017041 (eCSR_ENCRYPT_TYPE_AES !=
Nachiket Kukaded9152832017-10-16 16:18:22 +053017042 profile->EncryptionType.encryptionType[0]) &&
Mukul Sharma05504ac2017-06-08 12:35:53 +053017043 (eCSR_ENCRYPT_TYPE_AES_GCMP !=
Nachiket Kukaded9152832017-10-16 16:18:22 +053017044 profile->EncryptionType.encryptionType[0]) &&
Mukul Sharma05504ac2017-06-08 12:35:53 +053017045 (eCSR_ENCRYPT_TYPE_AES_GCMP_256 !=
Nachiket Kukaded9152832017-10-16 16:18:22 +053017046 profile->EncryptionType.encryptionType[0])) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017047 /* Saving key direction for default key index to TX default */
Nachiket Kukaded9152832017-10-16 16:18:22 +053017048 ap_ctx->wep_key[key_index].keyDirection =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017049 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017050 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053017051 key_index);
Nachiket Kukaded9152832017-10-16 16:18:22 +053017052 ap_ctx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017053 }
17054 }
17055
Dustin Browne74003f2018-03-14 12:51:58 -070017056 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017057 return status;
17058}
17059
17060static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
17061 struct net_device *ndev,
17062 u8 key_index,
17063 bool unicast, bool multicast)
17064{
17065 int ret;
Jeff Johnson4f7f7c62017-10-05 08:53:41 -070017066
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017067 cds_ssr_protect(__func__);
17068 ret =
17069 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
17070 multicast);
17071 cds_ssr_unprotect(__func__);
17072
17073 return ret;
17074}
17075
Abhishek Singhc9941602016-08-09 16:06:22 +053017076/*
Abhishek Singhc9941602016-08-09 16:06:22 +053017077 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
17078 * interface that BSS might have been lost.
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017079 * @adapter: adaptor
Abhishek Singhc9941602016-08-09 16:06:22 +053017080 * @bssid: bssid which might have been lost
17081 *
17082 * Return: bss which is unlinked from kernel cache
17083 */
17084struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017085 struct hdd_adapter *adapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017086{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017087 struct net_device *dev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017088 struct wireless_dev *wdev = dev->ieee80211_ptr;
17089 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017090 struct cfg80211_bss *bss = NULL;
17091
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053017092 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053017093 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017094 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070017095 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017096 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017097 hdd_debug("cfg80211_unlink_bss called for BSSID "
Abhishek Singhc9941602016-08-09 16:06:22 +053017098 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017099 cfg80211_unlink_bss(wiphy, bss);
17100 }
17101 return bss;
17102}
17103
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017104#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017105static inline int
17106wlan_hdd_get_frame_len(struct bss_description *bss_desc)
17107{
17108 return GET_IE_LEN_IN_BSS(bss_desc->length) + sizeof(qcom_ie_age);
17109}
17110
17111static inline void wlan_hdd_add_age_ie(struct ieee80211_mgmt *mgmt,
Abhishek Singhf1c16762018-03-07 10:48:46 +053017112 uint32_t *ie_length, struct bss_description *bss_desc)
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017113{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017114 qcom_ie_age *qie_age = NULL;
Nachiket Kukade348ede72017-04-28 16:34:24 +053017115
17116 /*
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017117 * GPS Requirement: need age ie per entry. Using vendor specific.
17118 * Assuming this is the last IE, copy at the end
Nachiket Kukade348ede72017-04-28 16:34:24 +053017119 */
Abhishek Singhf1c16762018-03-07 10:48:46 +053017120 *ie_length -= sizeof(qcom_ie_age);
17121 qie_age = (qcom_ie_age *)(mgmt->u.probe_resp.variable + *ie_length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017122 qie_age->element_id = QCOM_VENDOR_IE_ID;
17123 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
17124 qie_age->oui_1 = QCOM_OUI1;
17125 qie_age->oui_2 = QCOM_OUI2;
17126 qie_age->oui_3 = QCOM_OUI3;
17127 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053017128 /*
17129 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
17130 * all bss related timestamp is in units of ms. Due to this when scan
17131 * results are sent to lowi the scan age is high.To address this,
17132 * send age in units of 1/10 ms.
17133 */
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017134 qie_age->age = (uint32_t)(qdf_mc_timer_get_system_time() -
17135 bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017136 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070017137 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
17138 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070017139 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
17140 sizeof(qie_age->seq_ctrl));
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017141}
17142#else
17143static inline int
17144wlan_hdd_get_frame_len(struct bss_description *bss_desc)
17145{
17146 return GET_IE_LEN_IN_BSS(bss_desc->length);
17147}
17148static inline void wlan_hdd_add_age_ie(struct ieee80211_mgmt *mgmt,
Abhishek Singhf1c16762018-03-07 10:48:46 +053017149 uint32_t *ie_length, struct bss_description *bss_desc)
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017150{
17151}
17152#endif /* WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017153
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017154
17155struct cfg80211_bss *
17156wlan_hdd_inform_bss_frame(struct hdd_adapter *adapter,
17157 struct bss_description *bss_desc)
17158{
17159 struct wireless_dev *wdev = adapter->dev->ieee80211_ptr;
17160 struct wiphy *wiphy = wdev->wiphy;
Abhishek Singhf1c16762018-03-07 10:48:46 +053017161 uint32_t ie_length = wlan_hdd_get_frame_len(bss_desc);
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017162 const char *ie =
17163 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
17164 uint32_t freq, i;
17165 struct cfg80211_bss *bss_status = NULL;
17166 struct hdd_context *hdd_ctx;
17167 struct timespec ts;
17168 struct hdd_config *cfg_param;
17169 struct wlan_cfg80211_inform_bss bss_data = {0};
17170
17171 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
17172 /*
17173 * wlan_hdd_validate_context should not be used here, In validate ctx
17174 * start_modules_in_progress or stop_modules_in_progress is validated,
17175 * If the start_modules_in_progress is set to true means the interface
17176 * is not UP yet if the stop_modules_in_progress means that interface
17177 * is already down. So in both the two scenario's driver should not be
17178 * informing bss to kernel. Hence removing the validate context.
17179 */
17180
17181 if (!hdd_ctx || !hdd_ctx->config) {
17182 hdd_debug("HDD context is Null");
17183 return NULL;
17184 }
17185
17186 if (cds_is_driver_recovering() ||
17187 cds_is_load_or_unload_in_progress()) {
17188 hdd_debug("Recovery or load/unload in progress. State: 0x%x",
17189 cds_get_driver_state());
17190 return NULL;
17191 }
17192
17193 cfg_param = hdd_ctx->config;
17194 bss_data.frame_len = ie_length + offsetof(struct ieee80211_mgmt,
17195 u.probe_resp.variable);
17196 bss_data.mgmt = qdf_mem_malloc(bss_data.frame_len);
17197 if (!bss_data.mgmt) {
17198 hdd_err("memory allocation failed");
17199 return NULL;
17200 }
17201
17202 memcpy(bss_data.mgmt->bssid, bss_desc->bssId, ETH_ALEN);
17203
17204 /* Android does not want the timestamp from the frame.
17205 * Instead it wants a monotonic increasing value
17206 */
17207 get_monotonic_boottime(&ts);
17208 bss_data.mgmt->u.probe_resp.timestamp =
17209 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
17210
17211 bss_data.mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
17212 bss_data.mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
17213
Abhishek Singhf1c16762018-03-07 10:48:46 +053017214 wlan_hdd_add_age_ie(bss_data.mgmt, &ie_length, bss_desc);
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017215
17216 memcpy(bss_data.mgmt->u.probe_resp.variable, ie, ie_length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017217 if (bss_desc->fProbeRsp) {
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017218 bss_data.mgmt->frame_control |=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017219 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
17220 } else {
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017221 bss_data.mgmt->frame_control |=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017222 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
17223 }
17224
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017225 if (bss_desc->channelId <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070017226 (wiphy->bands[HDD_NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017227 freq =
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017228 ieee80211_channel_to_frequency(bss_desc->channelId,
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -070017229 HDD_NL80211_BAND_2GHZ);
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017230 } else if ((bss_desc->channelId > ARRAY_SIZE(hdd_channels_2_4_ghz))
Srinivas Girigowda11c28e02017-06-27 20:06:21 -070017231 && (wiphy->bands[HDD_NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017232 freq =
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017233 ieee80211_channel_to_frequency(bss_desc->channelId,
Srinivas Girigowda38f1ded2017-06-12 23:00:38 -070017234 HDD_NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017235 } else {
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017236 hdd_err("Invalid channel: %d", bss_desc->channelId);
17237 qdf_mem_free(bss_data.mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017238 return NULL;
17239 }
17240
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017241 bss_data.chan = ieee80211_get_channel(wiphy, freq);
17242 if (!bss_data.chan) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053017243 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017244 bss_desc->channelId, freq);
17245 qdf_mem_free(bss_data.mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017246 return NULL;
17247 }
17248
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017249 /*
17250 * Based on .ini configuration, raw rssi can be reported for bss.
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070017251 * Raw rssi is typically used for estimating power.
17252 */
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017253 bss_data.rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070017254 bss_desc->rssi;
17255
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017256 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017257 bss_data.rssi = QDF_MIN(bss_data.rssi, 0) * 100;
17258
17259 bss_data.boottime_ns = bss_desc->scansystimensec;
17260
17261 /* Set all per chain rssi as invalid */
17262 for (i = 0; i < WLAN_MGMT_TXRX_HOST_MAX_ANTENNA; i++)
17263 bss_data.per_chain_snr[i] = WLAN_INVALID_PER_CHAIN_RSSI;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017264
Srinivas Girigowdac06543c2017-03-09 15:10:03 -080017265 hdd_debug("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017266 MAC_ADDR_ARRAY(bss_data.mgmt->bssid), bss_data.chan->center_freq,
17267 (int)(bss_data.rssi / 100),
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070017268 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017269
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017270 bss_status = wlan_cfg80211_inform_bss_frame_data(wiphy, &bss_data);
Jeff Johnsonb8944722017-09-03 09:03:19 -070017271 hdd_ctx->beacon_probe_rsp_cnt_per_scan++;
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017272 qdf_mem_free(bss_data.mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017273 return bss_status;
17274}
17275
17276/**
17277 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017278 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070017279 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017280 *
17281 * This function is used to update the BSS data base of CFG8011
17282 *
17283 * Return: struct cfg80211_bss pointer
17284 */
Jeff Johnson172237b2017-11-07 15:32:59 -080017285struct cfg80211_bss *
17286wlan_hdd_cfg80211_update_bss_db(struct hdd_adapter *adapter,
17287 struct csr_roam_info *roam_info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017288{
17289 tCsrRoamConnectedProfile roamProfile;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017290 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017291 struct cfg80211_bss *bss = NULL;
17292
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017293 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
Jeff Johnson1b780e42017-10-31 14:11:45 -070017294 sme_roam_get_connect_profile(hHal, adapter->session_id, &roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017295
17296 if (NULL != roamProfile.pBssDesc) {
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017297 bss = wlan_hdd_inform_bss_frame(adapter, roamProfile.pBssDesc);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017298
17299 if (NULL == bss)
Abhishek Singhf05b0cb62018-02-20 18:06:13 +053017300 hdd_debug("wlan_hdd_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017301
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080017302 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017303 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070017304 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017305 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017306 return bss;
17307}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017308
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017309/**
17310 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017311 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070017312 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017313 * @index: Index
17314 * @preauth: Preauth flag
17315 *
17316 * This function is used to notify the supplicant of a new PMKSA candidate.
Deepak Dhamdhere828f1892017-02-09 11:51:19 -080017317 * PMK value is notified to supplicant whether PMK caching or OKC is enabled
17318 * in firmware or not. Supplicant needs this value becaue it uses PMK caching
17319 * by default.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017320 *
17321 * Return: 0 for success, non-zero for failure
17322 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017323int wlan_hdd_cfg80211_pmksa_candidate_notify(struct hdd_adapter *adapter,
Jeff Johnson172237b2017-11-07 15:32:59 -080017324 struct csr_roam_info *roam_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017325 int index, bool preauth)
17326{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017327 struct net_device *dev = adapter->dev;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017328
Dustin Brown491d54b2018-03-14 12:39:11 -070017329 hdd_enter();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017330 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017331
Jeff Johnsonfd060852017-10-04 10:50:51 -070017332 if (NULL == roam_info) {
17333 hdd_err("roam_info is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017334 return -EINVAL;
17335 }
17336
Dustin Brown5e89ef82018-03-14 11:50:23 -070017337 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Deepak Dhamdhere828f1892017-02-09 11:51:19 -080017338 cfg80211_pmksa_candidate_notify(dev, index,
Jeff Johnsonfd060852017-10-04 10:50:51 -070017339 roam_info->bssid.bytes,
Deepak Dhamdhere828f1892017-02-09 11:51:19 -080017340 preauth, GFP_KERNEL);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017341 return 0;
17342}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017343
17344#ifdef FEATURE_WLAN_LFR_METRICS
17345/**
17346 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017347 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070017348 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017349 *
17350 * 802.11r/LFR metrics reporting function to report preauth initiation
17351 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053017352 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017353 */
17354#define MAX_LFR_METRICS_EVENT_LENGTH 100
Jeff Johnson172237b2017-11-07 15:32:59 -080017355QDF_STATUS
17356wlan_hdd_cfg80211_roam_metrics_preauth(struct hdd_adapter *adapter,
17357 struct csr_roam_info *roam_info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017358{
17359 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
17360 union iwreq_data wrqu;
17361
Dustin Brown491d54b2018-03-14 12:39:11 -070017362 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017363
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017364 if (NULL == adapter) {
17365 hdd_err("adapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017366 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017367 }
17368
17369 /* create the event */
17370 memset(&wrqu, 0, sizeof(wrqu));
17371 memset(metrics_notification, 0, sizeof(metrics_notification));
17372
17373 wrqu.data.pointer = metrics_notification;
17374 wrqu.data.length = scnprintf(metrics_notification,
17375 sizeof(metrics_notification),
17376 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
Jeff Johnsonfd060852017-10-04 10:50:51 -070017377 MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017378
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017379 wireless_send_event(adapter->dev, IWEVCUSTOM, &wrqu,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017380 metrics_notification);
17381
Dustin Browne74003f2018-03-14 12:51:58 -070017382 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017383
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017384 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017385}
17386
17387/**
17388 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017389 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070017390 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017391 * @preauth_status: Preauth status
17392 *
17393 * 802.11r/LFR metrics reporting function to report handover initiation
17394 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053017395 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017396 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017397QDF_STATUS
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017398wlan_hdd_cfg80211_roam_metrics_preauth_status(struct hdd_adapter *adapter,
Jeff Johnson172237b2017-11-07 15:32:59 -080017399 struct csr_roam_info *roam_info,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017400 bool preauth_status)
17401{
17402 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
17403 union iwreq_data wrqu;
17404
Dustin Brown491d54b2018-03-14 12:39:11 -070017405 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017406
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017407 if (NULL == adapter) {
17408 hdd_err("adapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017409 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017410 }
17411
17412 /* create the event */
17413 memset(&wrqu, 0, sizeof(wrqu));
17414 memset(metrics_notification, 0, sizeof(metrics_notification));
17415
17416 scnprintf(metrics_notification, sizeof(metrics_notification),
17417 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
Jeff Johnsonfd060852017-10-04 10:50:51 -070017418 MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017419
17420 if (1 == preauth_status)
17421 strlcat(metrics_notification, " true",
17422 sizeof(metrics_notification));
17423 else
17424 strlcat(metrics_notification, " false",
17425 sizeof(metrics_notification));
17426
17427 wrqu.data.pointer = metrics_notification;
17428 wrqu.data.length = strlen(metrics_notification);
17429
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017430 wireless_send_event(adapter->dev, IWEVCUSTOM, &wrqu,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017431 metrics_notification);
17432
Dustin Browne74003f2018-03-14 12:51:58 -070017433 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017434
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017435 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017436}
17437
17438/**
17439 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017440 * @adapter: Pointer to adapter
Jeff Johnsonfd060852017-10-04 10:50:51 -070017441 * @roam_info: Pointer to roam info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017442 *
17443 * 802.11r/LFR metrics reporting function to report handover initiation
17444 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053017445 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017446 */
Jeff Johnson172237b2017-11-07 15:32:59 -080017447QDF_STATUS
17448wlan_hdd_cfg80211_roam_metrics_handover(struct hdd_adapter *adapter,
17449 struct csr_roam_info *roam_info)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017450{
17451 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
17452 union iwreq_data wrqu;
17453
Dustin Brown491d54b2018-03-14 12:39:11 -070017454 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017455
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017456 if (NULL == adapter) {
17457 hdd_err("adapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017458 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017459 }
17460
17461 /* create the event */
17462 memset(&wrqu, 0, sizeof(wrqu));
17463 memset(metrics_notification, 0, sizeof(metrics_notification));
17464
17465 wrqu.data.pointer = metrics_notification;
17466 wrqu.data.length = scnprintf(metrics_notification,
17467 sizeof(metrics_notification),
17468 "QCOM: LFR_PREAUTH_HANDOVER "
17469 MAC_ADDRESS_STR,
Jeff Johnsonfd060852017-10-04 10:50:51 -070017470 MAC_ADDR_ARRAY(roam_info->bssid.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017471
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017472 wireless_send_event(adapter->dev, IWEVCUSTOM, &wrqu,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017473 metrics_notification);
17474
Dustin Browne74003f2018-03-14 12:51:58 -070017475 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017476
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053017477 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017478}
17479#endif
17480
17481/**
17482 * hdd_select_cbmode() - select channel bonding mode
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017483 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017484 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017485 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017486 *
17487 * Return: none
17488 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017489void hdd_select_cbmode(struct hdd_adapter *adapter, uint8_t operationChannel,
Amar Singhal5cccafe2017-02-15 12:42:58 -080017490 struct ch_params *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017491{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017492 struct hdd_station_ctx *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017493 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017494 uint8_t sec_ch = 0;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017495 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017496
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017497 /*
17498 * CDS api expects secondary channel for calculating
17499 * the channel params
17500 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017501 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017502 (WLAN_REG_IS_24GHZ_CH(operationChannel))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070017503 if (operationChannel >= 1 && operationChannel <= 5)
17504 sec_ch = operationChannel + 4;
17505 else if (operationChannel >= 6 && operationChannel <= 13)
17506 sec_ch = operationChannel - 4;
17507 }
17508
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017509 /* This call decides required channel bonding mode */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017510 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, operationChannel,
17511 sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017512
17513 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Srinivas Girigowda2fb677c2017-03-25 15:35:34 -070017514 enum hdd_dot11_mode hdd_dot11_mode;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017515 uint8_t iniDot11Mode =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017516 (WLAN_HDD_GET_CTX(adapter))->config->dot11Mode;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017517
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017518 hdd_debug("Dot11Mode is %u", iniDot11Mode);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017519 switch (iniDot11Mode) {
17520 case eHDD_DOT11_MODE_AUTO:
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -080017521 case eHDD_DOT11_MODE_11ax:
17522 case eHDD_DOT11_MODE_11ax_ONLY:
17523 if (sme_is_feature_supported_by_fw(DOT11AX))
17524 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
17525 else if (sme_is_feature_supported_by_fw(DOT11AC))
17526 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
17527 else
17528 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
17529 break;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017530 case eHDD_DOT11_MODE_11ac:
17531 case eHDD_DOT11_MODE_11ac_ONLY:
17532 if (sme_is_feature_supported_by_fw(DOT11AC))
17533 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
17534 else
17535 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
17536 break;
17537 case eHDD_DOT11_MODE_11n:
17538 case eHDD_DOT11_MODE_11n_ONLY:
17539 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
17540 break;
17541 default:
17542 hdd_dot11_mode = iniDot11Mode;
17543 break;
17544 }
17545 ch_info->channel_width = ch_params->ch_width;
17546 ch_info->phy_mode =
17547 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017548 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017549 ch_info->cb_mode = ch_params->ch_width;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017550 hdd_debug("ch_info width %d, phymode %d channel %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017551 ch_info->channel_width, ch_info->phy_mode,
17552 ch_info->channel);
17553 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017554}
17555
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017556/**
17557 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
17558 * @adapter: STA adapter
17559 * @roam_profile: STA roam profile
17560 *
17561 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
17562 *
17563 * Return: false if sta-sap conc is not allowed, else return true
17564 */
Jeff Johnson61b5e982018-03-15 11:33:31 -070017565static
17566bool wlan_hdd_handle_sap_sta_dfs_conc(struct hdd_adapter *adapter,
17567 struct csr_roam_profile *roam_profile)
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017568{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070017569 struct hdd_context *hdd_ctx;
Jeff Johnsone5006672017-08-29 14:39:02 -070017570 struct hdd_adapter *ap_adapter;
Jeff Johnson87251032017-08-29 13:31:11 -070017571 struct hdd_ap_ctx *hdd_ap_ctx;
Jeff Johnsonca2530c2017-09-30 18:25:40 -070017572 struct hdd_hostapd_state *hostapd_state;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017573 uint8_t channel = 0;
17574 QDF_STATUS status;
17575
17576 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
17577 if (!hdd_ctx) {
17578 hdd_err("HDD context is NULL");
17579 return true;
17580 }
17581
17582 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
17583 /* probably no sap running, no handling required */
17584 if (ap_adapter == NULL)
17585 return true;
17586
17587 /*
17588 * sap is not in started state, so it is fine to go ahead with sta.
17589 * if sap is currently doing CAC then don't allow sta to go further.
17590 */
17591 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
17592 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
17593 return true;
17594
17595 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
17596 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
17597 return false;
17598 }
17599
17600 /*
17601 * log and return error, if we allow STA to go through, we don't
17602 * know what is going to happen better stop sta connection
17603 */
17604 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
17605 if (NULL == hdd_ap_ctx) {
17606 hdd_err("AP context not found");
17607 return false;
17608 }
17609
17610 /* sap is on non-dfs channel, nothing to handle */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017611 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
Jeff Johnson01206862017-10-27 20:55:59 -070017612 hdd_ap_ctx->operating_channel)) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017613 hdd_info("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017614 return true;
17615 }
17616 /*
17617 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053017618 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017619 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017620 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->hdd_psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017621 roam_profile, &channel);
17622
Nitesh Shah59774522016-09-16 15:14:21 +053017623 /*
17624 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
17625 * channels for roaming case.
17626 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017627 if (WLAN_REG_IS_24GHZ_CH(channel)) {
17628 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053017629 return true;
17630 }
17631
17632 /*
Jeff Johnsondcf84ce2017-10-05 09:26:24 -070017633 * If channel is 0 or DFS or LTE unsafe then better to call pcl and
Tushnim Bhattacharyya9a929992017-06-18 00:59:09 -070017634 * find out the best channel. If channel is non-dfs 5 GHz then
17635 * better move SAP to STA's channel to make scc, so we have room
17636 * for 3port MCC scenario.
Nitesh Shah59774522016-09-16 15:14:21 +053017637 */
Tushnim Bhattacharyya9a929992017-06-18 00:59:09 -070017638 if ((0 == channel) || wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel) ||
17639 !policy_mgr_is_safe_channel(hdd_ctx->hdd_psoc, channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017640 channel = policy_mgr_get_nondfs_preferred_channel(
17641 hdd_ctx->hdd_psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017642
17643 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
17644 qdf_event_reset(&hostapd_state->qdf_event);
17645 status = wlansap_set_channel_change_with_csa(
17646 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
Jeff Johnson91df29d2017-10-27 19:29:50 -070017647 hdd_ap_ctx->sap_config.ch_width_orig, false);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017648
17649 if (QDF_STATUS_SUCCESS != status) {
17650 hdd_err("Set channel with CSA IE failed, can't allow STA");
17651 return false;
17652 }
17653
17654 /*
17655 * wait here for SAP to finish the channel switch. When channel
17656 * switch happens, SAP sends few beacons with CSA_IE. After
17657 * successfully Transmission of those beacons, it will move its
17658 * state from started to disconnected and move to new channel.
17659 * once it moves to new channel, sap again moves its state
17660 * machine from disconnected to started and set this event.
17661 * wait for 10 secs to finish this.
17662 */
Nachiket Kukade0396b732017-11-14 16:35:16 +053017663 status = qdf_wait_for_event_completion(&hostapd_state->qdf_event, 10000);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017664 if (!QDF_IS_STATUS_SUCCESS(status)) {
17665 hdd_err("wait for qdf_event failed, STA not allowed!!");
17666 return false;
17667 }
17668
17669 return true;
17670}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017671
Abhishek Singhcfb44482017-03-10 12:42:37 +053017672#ifdef WLAN_FEATURE_11W
17673/**
17674 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
17675 * @roam_profile: pointer to roam profile
17676 *
17677 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
17678 * or pmf=2 is an explicit configuration in the supplicant
17679 * configuration, drop the connection request.
17680 *
17681 * Return: 0 if check result is valid, otherwise return error code
17682 */
Jeff Johnson61b5e982018-03-15 11:33:31 -070017683static
17684int wlan_hdd_cfg80211_check_pmf_valid(struct csr_roam_profile *roam_profile)
Abhishek Singhcfb44482017-03-10 12:42:37 +053017685{
17686 if (roam_profile->MFPEnabled &&
Jeff Johnson20227a92018-03-13 09:41:05 -070017687 !(roam_profile->MFPRequired || roam_profile->MFPCapable)) {
Abhishek Singhcfb44482017-03-10 12:42:37 +053017688 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
17689 roam_profile->MFPEnabled,
17690 roam_profile->MFPRequired,
17691 roam_profile->MFPCapable);
17692 return -EINVAL;
17693 }
17694 return 0;
17695}
17696#else
17697static inline
Jeff Johnson61b5e982018-03-15 11:33:31 -070017698int wlan_hdd_cfg80211_check_pmf_valid(struct csr_roam_profile *roam_profile)
Abhishek Singhcfb44482017-03-10 12:42:37 +053017699{
17700 return 0;
17701}
17702#endif
17703
Krunal Soni31949422016-07-29 17:17:53 -070017704/**
17705 * wlan_hdd_cfg80211_connect_start() - to start the association process
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017706 * @adapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070017707 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017708 * @ssid_len: Length of ssid
17709 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070017710 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017711 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017712 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017713 *
17714 * This function is used to start the association process
17715 *
17716 * Return: 0 for success, non-zero for failure
17717 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017718static int wlan_hdd_cfg80211_connect_start(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017719 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070017720 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017721 u8 operatingChannel,
17722 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017723{
17724 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080017725 QDF_STATUS qdf_status;
Jeff Johnsonb8944722017-09-03 09:03:19 -070017726 struct hdd_context *hdd_ctx;
Jeff Johnson40dae4e2017-08-29 14:00:25 -070017727 struct hdd_station_ctx *hdd_sta_ctx;
Krunal Sonibfd05492017-10-03 15:48:37 -070017728 uint32_t roamId = INVALID_ROAM_ID;
Jeff Johnson61b5e982018-03-15 11:33:31 -070017729 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017730 eCsrAuthType RSNAuthType;
17731 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053017732 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017733
Dustin Brown491d54b2018-03-14 12:39:11 -070017734 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017735
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017736 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
17737 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017738
Jeff Johnsonb8944722017-09-03 09:03:19 -070017739 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053017740 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017741 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017742
17743 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070017744 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017745 status = -EINVAL;
17746 goto ret_status;
17747 }
17748
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017749 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017750 hdd_err("Connection refused: conn in progress");
17751 status = -EINVAL;
17752 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017753 }
17754
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017755 hdd_notify_teardown_tdls_links(adapter->hdd_vdev);
Nitesh Shah273e4e52017-04-03 12:53:36 +053017756
Anurag Chouhand939d3d2016-07-20 17:45:48 +053017757 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
17758 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017759
Jeff Johnson20227a92018-03-13 09:41:05 -070017760 roam_profile = hdd_roam_profile(adapter);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017761 if (roam_profile) {
Jeff Johnsond377dce2017-10-04 10:32:42 -070017762 struct hdd_station_ctx *sta_ctx;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070017763
Jeff Johnsond377dce2017-10-04 10:32:42 -070017764 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017765
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017766 /* Restart the opportunistic timer
17767 *
17768 * If hw_mode_change_in_progress is true, then wait
17769 * till firmware sends the callback for hw_mode change.
17770 *
17771 * Else set connect_in_progress as true and proceed.
17772 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017773 policy_mgr_restart_opportunistic_timer(
Jeff Johnsonb8944722017-09-03 09:03:19 -070017774 hdd_ctx->hdd_psoc, false);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017775 if (policy_mgr_is_hw_mode_change_in_progress(
Jeff Johnsonb8944722017-09-03 09:03:19 -070017776 hdd_ctx->hdd_psoc)) {
Abhishek Singh471652b2017-04-14 12:28:32 +053017777 qdf_status = policy_mgr_wait_for_connection_update(
Jeff Johnsonb8944722017-09-03 09:03:19 -070017778 hdd_ctx->hdd_psoc);
Abhishek Singh471652b2017-04-14 12:28:32 +053017779 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017780 hdd_err("qdf wait for event failed!!");
17781 status = -EINVAL;
17782 goto ret_status;
17783 }
17784 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080017785 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017786
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017787 if (HDD_WMM_USER_MODE_NO_QOS ==
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017788 (WLAN_HDD_GET_CTX(adapter))->config->WmmMode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017789 /*QoS not enabled in cfg file */
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017790 roam_profile->uapsd_mask = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017791 } else {
17792 /*QoS enabled, update uapsd mask from cfg file */
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017793 roam_profile->uapsd_mask =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017794 (WLAN_HDD_GET_CTX(adapter))->config->UapsdMask;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017795 }
17796
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017797 roam_profile->SSIDs.numOfSSIDs = 1;
17798 roam_profile->SSIDs.SSIDList->SSID.length = ssid_len;
17799 qdf_mem_zero(roam_profile->SSIDs.SSIDList->SSID.ssId,
17800 sizeof(roam_profile->SSIDs.SSIDList->SSID.ssId));
17801 qdf_mem_copy((void *)(roam_profile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017802 ssid, ssid_len);
17803
Abhishek Singh1f217ec2017-12-22 11:48:27 +053017804 roam_profile->supplicant_disabled_roaming = false;
Varun Reddy Yeturue5a35d12017-10-20 11:26:57 -070017805
Abhishek Singh3c9910e2017-01-06 17:56:47 +053017806 /* cleanup bssid hint */
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017807 qdf_mem_zero(roam_profile->bssid_hint.bytes,
Abhishek Singh3c9910e2017-01-06 17:56:47 +053017808 QDF_MAC_ADDR_SIZE);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017809 qdf_mem_zero((void *)(roam_profile->BSSIDs.bssid),
Abhishek Singh3c9910e2017-01-06 17:56:47 +053017810 QDF_MAC_ADDR_SIZE);
17811
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017812 if (bssid) {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017813 roam_profile->BSSIDs.numOfBSSIDs = 1;
Varun Reddy Yeturue5a35d12017-10-20 11:26:57 -070017814 roam_profile->supplicant_disabled_roaming = true;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017815 qdf_mem_copy((void *)(roam_profile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053017816 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070017817 /*
17818 * Save BSSID in seperate variable as
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017819 * roam_profile's BSSID is getting zeroed out in the
Krunal Soni31949422016-07-29 17:17:53 -070017820 * association process. In case of join failure
17821 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017822 */
Jeff Johnson731bc322017-10-14 19:53:44 -070017823 qdf_mem_copy(sta_ctx->requested_bssid.bytes,
17824 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017825 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017826 } else if (bssid_hint) {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017827 qdf_mem_copy(roam_profile->bssid_hint.bytes,
Abhishek Singh3c9910e2017-01-06 17:56:47 +053017828 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070017829 /*
17830 * Save BSSID in a separate variable as
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017831 * roam_profile's BSSID is getting zeroed out in the
Krunal Soni31949422016-07-29 17:17:53 -070017832 * association process. In case of join failure
17833 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017834 */
Jeff Johnson731bc322017-10-14 19:53:44 -070017835 qdf_mem_copy(sta_ctx->requested_bssid.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053017836 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017837 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070017838 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017839 }
17840
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017841 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017842 roam_profile->SSIDs.SSIDList->SSID.length,
17843 roam_profile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017844 operatingChannel);
17845
Jeff Johnsonce4a8342017-10-14 13:12:22 -070017846 if (hdd_sta_ctx->wpa_versions) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017847 hdd_set_genie_to_csr(adapter, &RSNAuthType);
17848 hdd_set_csr_auth_type(adapter, RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017849 }
17850#ifdef FEATURE_WLAN_WAPI
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070017851 if (adapter->wapi_info.wapi_mode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017852 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070017853 switch (adapter->wapi_info.wapi_auth_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017854 case WAPI_AUTH_MODE_PSK:
17855 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017856 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070017857 adapter->wapi_info.wapi_auth_mode);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017858 roam_profile->AuthType.authType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017859 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
17860 break;
17861 }
17862 case WAPI_AUTH_MODE_CERT:
17863 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017864 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070017865 adapter->wapi_info.wapi_auth_mode);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017866 roam_profile->AuthType.authType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017867 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
17868 break;
17869 }
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070017870 default:
17871 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017872 } /* End of switch */
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070017873 if (adapter->wapi_info.wapi_auth_mode ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017874 WAPI_AUTH_MODE_PSK
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070017875 || adapter->wapi_info.wapi_auth_mode ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017876 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080017877 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017878 roam_profile->AuthType.numEntries = 1;
17879 roam_profile->EncryptionType.numEntries = 1;
17880 roam_profile->EncryptionType.encryptionType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017881 eCSR_ENCRYPT_TYPE_WPI;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017882 roam_profile->mcEncryptionType.numEntries = 1;
17883 roam_profile->mcEncryptionType.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017884 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
17885 }
17886 }
Krunal Soni31949422016-07-29 17:17:53 -070017887#endif
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017888 pmo_ucfg_flush_gtk_offload_req(adapter->hdd_vdev);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017889 roam_profile->csrPersona = adapter->device_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017890
17891 if (operatingChannel) {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017892 roam_profile->ChannelInfo.ChannelList =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017893 &operatingChannel;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017894 roam_profile->ChannelInfo.numOfChannels = 1;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017895 } else {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017896 roam_profile->ChannelInfo.ChannelList = NULL;
17897 roam_profile->ChannelInfo.numOfChannels = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017898 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017899 if ((QDF_IBSS_MODE == adapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017900 && operatingChannel) {
17901 /*
17902 * Need to post the IBSS power save parameters
17903 * to WMA. WMA will configure this parameters
17904 * to firmware if power save is enabled by the
17905 * firmware.
17906 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017907 qdf_status = hdd_set_ibss_power_save_params(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017908
Abhishek Singh471652b2017-04-14 12:28:32 +053017909 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070017910 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017911 status = -EINVAL;
17912 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017913 }
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017914 roam_profile->ch_params.ch_width =
Naveen Rawatc77e6e72016-08-05 15:19:03 -070017915 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053017916 /*
17917 * In IBSS mode while operating in 2.4 GHz,
17918 * the device supports only 20 MHz.
17919 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070017920 if (WLAN_REG_IS_24GHZ_CH(operatingChannel))
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017921 roam_profile->ch_params.ch_width =
Nitesh Shah87335a52016-09-05 15:47:32 +053017922 CH_WIDTH_20MHZ;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017923 hdd_select_cbmode(adapter, operatingChannel,
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017924 &roam_profile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017925 }
17926
Jeff Johnson20227a92018-03-13 09:41:05 -070017927 if (wlan_hdd_cfg80211_check_pmf_valid(roam_profile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017928 status = -EINVAL;
17929 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017930 }
17931
Krunal Soni31949422016-07-29 17:17:53 -070017932 /*
17933 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017934 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070017935 * enhancements, the supplicant is not issuing the scan command
17936 * now. So the unicast frames which are sent from the host are
17937 * not having the additional IEs. If it is P2P CLIENT and there
17938 * is no additional IE present in roamProfile, then use the
17939 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017940 */
17941
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017942 if ((adapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017943 (!roam_profile->pAddIEScan)) {
17944 roam_profile->pAddIEScan =
Jeff Johnson37fa0402017-10-28 12:42:29 -070017945 &adapter->scan_info.scan_add_ie.addIEdata[0];
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017946 roam_profile->nAddIEScanLength =
Jeff Johnson37fa0402017-10-28 12:42:29 -070017947 adapter->scan_info.scan_add_ie.length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017948 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017949
Jeff Johnsonb8944722017-09-03 09:03:19 -070017950 if ((policy_mgr_is_hw_dbs_capable(hdd_ctx->hdd_psoc) == true)
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017951 && (false == wlan_hdd_handle_sap_sta_dfs_conc(adapter,
Jeff Johnson5b34fce2017-10-13 13:24:51 -070017952 roam_profile))) {
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017953 hdd_err("sap-sta conc will fail, can't allow sta");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017954 hdd_conn_set_connection_state(adapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017955 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017956 status = -ENOMEM;
17957 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017958 }
17959
Anurag Chouhan600c3a02016-03-01 10:33:54 +053017960 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017961 if (!sme_config) {
17962 hdd_err("unable to allocate sme_config");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070017963 hdd_conn_set_connection_state(adapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070017964 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053017965 status = -ENOMEM;
17966 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017967 }
Jeff Johnsonb8944722017-09-03 09:03:19 -070017968 sme_get_config_param(hdd_ctx->hHal, sme_config);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017969 /* These values are not sessionized. So, any change in these SME
17970 * configs on an older or parallel interface will affect the
17971 * cb mode. So, restoring the default INI params before starting
17972 * interfaces such as sta, cli etc.,
17973 */
17974 sme_config->csrConfig.channelBondingMode5GHz =
Jeff Johnsonb8944722017-09-03 09:03:19 -070017975 hdd_ctx->config->nChannelBondingMode5GHz;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017976 sme_config->csrConfig.channelBondingMode24GHz =
Jeff Johnsonb8944722017-09-03 09:03:19 -070017977 hdd_ctx->config->nChannelBondingMode24GHz;
17978 sme_update_config(hdd_ctx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053017979 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053017980 /*
17981 * Change conn_state to connecting before sme_roam_connect(),
17982 * because sme_roam_connect() has a direct path to call
17983 * hdd_sme_roam_callback(), which will change the conn_state
17984 * If direct path, conn_state will be accordingly changed to
17985 * NotConnected or Associated by either
17986 * hdd_association_completion_handler() or
17987 * hdd_dis_connect_handler() in sme_RoamCallback()if
17988 * sme_RomConnect is to be queued,
17989 * Connecting state will remain until it is completed.
17990 *
17991 * If connection state is not changed, connection state will
17992 * remain in eConnectionState_NotConnected state.
17993 * In hdd_association_completion_handler, "hddDisconInProgress"
17994 * is set to true if conn state is
17995 * eConnectionState_NotConnected.
17996 * If "hddDisconInProgress" is set to true then cfg80211 layer
17997 * is not informed of connect result indication which
17998 * is an issue.
17999 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018000 if (QDF_STA_MODE == adapter->device_mode ||
18001 QDF_P2P_CLIENT_MODE == adapter->device_mode)
18002 hdd_conn_set_connection_state(adapter,
Agrawal Ashish6b015762016-05-05 11:22:18 +053018003 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018004
Alok Kumarb64650c2018-03-23 17:05:11 +053018005 hdd_set_disconnect_status(adapter, false);
18006
Jingxiang Geb49aa302018-01-17 20:54:15 +080018007 qdf_runtime_pm_prevent_suspend(
18008 &hdd_ctx->runtime_context.connect);
Dustin Brownceed67e2017-05-26 11:57:31 -070018009 hdd_prevent_suspend_timeout(HDD_WAKELOCK_TIMEOUT_CONNECT,
18010 WIFI_POWER_EVENT_WAKELOCK_CONNECT);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018011 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -070018012 adapter->session_id, roam_profile,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018013 &roamId);
Abhishek Singh471652b2017-04-14 12:28:32 +053018014 if (QDF_IS_STATUS_ERROR(qdf_status))
18015 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018016
Rajeev Kumard31e1542017-01-13 14:37:42 -080018017 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018018 (QDF_STA_MODE == adapter->device_mode ||
18019 QDF_P2P_CLIENT_MODE == adapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018020 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080018021 "qdf_status %d. -> NotConnected",
Jeff Johnson1b780e42017-10-31 14:11:45 -070018022 adapter->session_id, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018023 /* change back to NotAssociated */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018024 hdd_conn_set_connection_state(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018025 eConnectionState_NotConnected);
Jingxiang Geb49aa302018-01-17 20:54:15 +080018026 qdf_runtime_pm_allow_suspend(
18027 &hdd_ctx->runtime_context.connect);
Dustin Brownceed67e2017-05-26 11:57:31 -070018028 hdd_allow_suspend(WIFI_POWER_EVENT_WAKELOCK_CONNECT);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018029 }
18030
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018031 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080018032 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018033
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018034 roam_profile->ChannelInfo.ChannelList = NULL;
18035 roam_profile->ChannelInfo.numOfChannels = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018036
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018037 if ((QDF_STA_MODE == adapter->device_mode)
Jeff Johnsonb8944722017-09-03 09:03:19 -070018038 && policy_mgr_is_current_hwmode_dbs(hdd_ctx->hdd_psoc)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080018039 && !policy_mgr_is_hw_dbs_2x2_capable(
Jeff Johnsonb8944722017-09-03 09:03:19 -070018040 hdd_ctx->hdd_psoc)) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080018041 policy_mgr_get_channel_from_scan_result(
Jeff Johnsonb8944722017-09-03 09:03:19 -070018042 hdd_ctx->hdd_psoc,
Jeff Johnson5b34fce2017-10-13 13:24:51 -070018043 roam_profile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080018044 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053018045 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080018046 policy_mgr_checkn_update_hw_mode_single_mac_mode(
Jeff Johnsonb8944722017-09-03 09:03:19 -070018047 hdd_ctx->hdd_psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053018048 }
18049
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018050 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018051 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018052 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018053 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018054 goto ret_status;
18055
18056conn_failure:
18057 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080018058 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053018059
18060ret_status:
Dustin Browne74003f2018-03-14 12:51:58 -070018061 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018062 return status;
18063}
18064
18065/**
18066 * wlan_hdd_cfg80211_set_auth_type() - set auth type
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018067 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018068 * @auth_type: Auth type
18069 *
18070 * This function is used to set the authentication type (OPEN/SHARED).
18071 *
18072 * Return: 0 for success, non-zero for failure
18073 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018074static int wlan_hdd_cfg80211_set_auth_type(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018075 enum nl80211_auth_type auth_type)
18076{
Jeff Johnsond377dce2017-10-04 10:32:42 -070018077 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018078 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070018079 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018080
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018081 /*set authentication type */
18082 switch (auth_type) {
18083 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018084 hdd_debug("set authentication type to AUTOSWITCH");
Jeff Johnsond377dce2017-10-04 10:32:42 -070018085 sta_ctx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018086 break;
18087
18088 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018089 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018090 hdd_debug("set authentication type to OPEN");
Jeff Johnsond377dce2017-10-04 10:32:42 -070018091 sta_ctx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018092 break;
18093
18094 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018095 hdd_debug("set authentication type to SHARED");
Jeff Johnsond377dce2017-10-04 10:32:42 -070018096 sta_ctx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018097 break;
18098#ifdef FEATURE_WLAN_ESE
18099 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018100 hdd_debug("set authentication type to CCKM WPA");
Jeff Johnsond377dce2017-10-04 10:32:42 -070018101 sta_ctx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018102 break;
18103#endif
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053018104#if defined(WLAN_FEATURE_FILS_SK) && \
18105 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
18106 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018107 case NL80211_AUTHTYPE_FILS_SK:
Dustin Brown5e89ef82018-03-14 11:50:23 -070018108 hdd_debug("set authentication type to FILS SHARED");
Jeff Johnsond377dce2017-10-04 10:32:42 -070018109 sta_ctx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018110 break;
18111#endif
Padma, Santhosh Kumar07eb80b2017-07-05 16:10:06 +053018112 case NL80211_AUTHTYPE_SAE:
18113 hdd_debug("set authentication type to SAE");
18114 sta_ctx->conn_info.authType = eCSR_AUTH_TYPE_SAE;
18115 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018116 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018117 hdd_err("Unsupported authentication type: %d", auth_type);
Jeff Johnsond377dce2017-10-04 10:32:42 -070018118 sta_ctx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018119 return -EINVAL;
18120 }
18121
Jeff Johnson20227a92018-03-13 09:41:05 -070018122 roam_profile = hdd_roam_profile(adapter);
18123 roam_profile->AuthType.authType[0] = sta_ctx->conn_info.authType;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018124 return 0;
18125}
18126
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053018127#if defined(WLAN_FEATURE_FILS_SK) && \
18128 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
18129 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Jeff Johnson20227a92018-03-13 09:41:05 -070018130static bool hdd_validate_fils_info_ptr(struct csr_roam_profile *roam_profile)
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018131{
18132 struct cds_fils_connection_info *fils_con_info;
18133
Jeff Johnson20227a92018-03-13 09:41:05 -070018134 fils_con_info = roam_profile->fils_con_info;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018135 if (!fils_con_info) {
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018136 hdd_err("No valid Roam profile");
18137 return false;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018138 }
18139
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018140 return true;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018141}
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018142
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018143static enum eAniAuthType wlan_hdd_get_fils_auth_type(
18144 enum nl80211_auth_type auth)
18145{
18146 switch (auth) {
18147 case NL80211_AUTHTYPE_FILS_SK:
18148 return SIR_FILS_SK_WITHOUT_PFS;
18149 case NL80211_AUTHTYPE_FILS_SK_PFS:
18150 return SIR_FILS_SK_WITH_PFS;
18151 case NL80211_AUTHTYPE_FILS_PK:
18152 return SIR_FILS_PK_AUTH;
18153 default:
18154 return eSIR_DONOT_USE_AUTH_TYPE;
18155 }
18156}
18157
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080018158static bool wlan_hdd_fils_data_in_limits(struct cfg80211_connect_params *req)
18159{
18160 hdd_debug("seq=%d auth=%d lengths: user=%zu rrk=%zu realm=%zu",
18161 req->fils_erp_next_seq_num, req->auth_type,
18162 req->fils_erp_username_len, req->fils_erp_rrk_len,
18163 req->fils_erp_realm_len);
18164 if (!req->fils_erp_rrk_len || !req->fils_erp_realm_len ||
18165 !req->fils_erp_username_len ||
18166 req->fils_erp_rrk_len > FILS_MAX_RRK_LENGTH ||
18167 req->fils_erp_realm_len > FILS_MAX_REALM_LEN ||
18168 req->fils_erp_username_len > FILS_MAX_KEYNAME_NAI_LENGTH) {
18169 hdd_err("length incorrect, user=%zu rrk=%zu realm=%zu",
18170 req->fils_erp_username_len, req->fils_erp_rrk_len,
18171 req->fils_erp_realm_len);
18172 return false;
18173 }
18174
18175 return true;
18176}
18177
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018178/**
18179 * wlan_hdd_cfg80211_set_fils_config() - set fils config params during connect
18180 * @adapter: Pointer to adapter
18181 * @req: Pointer to fils parameters
18182 *
18183 * Return: 0 for success, non-zero for failure
18184 */
18185static int wlan_hdd_cfg80211_set_fils_config(struct hdd_adapter *adapter,
18186 struct cfg80211_connect_params *req)
18187{
Jeff Johnson61b5e982018-03-15 11:33:31 -070018188 struct csr_roam_profile *roam_profile;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018189 enum eAniAuthType auth_type;
18190 uint8_t *buf;
18191 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
18192
Jeff Johnson20227a92018-03-13 09:41:05 -070018193 roam_profile = hdd_roam_profile(adapter);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018194
18195 if (!hdd_ctx->config->is_fils_enabled) {
18196 hdd_err("FILS disabled");
18197 return -EINVAL;
18198 }
18199 hdd_clear_fils_connection_info(adapter);
18200 roam_profile->fils_con_info =
18201 qdf_mem_malloc(sizeof(*roam_profile->fils_con_info));
18202
18203 if (!roam_profile->fils_con_info) {
18204 hdd_err("failed to allocate memory");
18205 return -EINVAL;
18206 }
18207 /*
18208 * The initial connection for FILS may happen with an OPEN
18209 * auth type. Hence we need to allow the connection to go
18210 * through in that case as well. Below is_fils_connection
18211 * flag is propagated down to CSR and PE sessions through
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080018212 * the JOIN request. As the flag is used, do not free the
18213 * memory allocated to fils_con_info and return success.
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018214 */
18215 if (req->auth_type != NL80211_AUTHTYPE_FILS_SK) {
18216 roam_profile->fils_con_info->is_fils_connection = false;
18217 return 0;
18218 }
18219
18220 /*
18221 * Once above check is done, then we can check for valid FILS
18222 * auth types. Currently only NL80211_AUTHTYPE_FILS_SK is
18223 * supported. Once all auth types are supported, then we can
18224 * merge these 2 conditions into one.
18225 */
18226 auth_type = wlan_hdd_get_fils_auth_type(req->auth_type);
18227 if (auth_type == eSIR_DONOT_USE_AUTH_TYPE) {
18228 hdd_err("invalid auth type for fils %d", req->auth_type);
Varun Reddy Yeturu82e39cd2017-10-16 12:04:05 -070018229 goto fils_conn_fail;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018230 }
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080018231 if (!wlan_hdd_fils_data_in_limits(req))
Jeff Johnsonb8adae42018-02-27 16:12:00 -080018232 goto fils_conn_fail;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018233
18234 roam_profile->fils_con_info->is_fils_connection = true;
18235 roam_profile->fils_con_info->sequence_number =
18236 req->fils_erp_next_seq_num;
18237 roam_profile->fils_con_info->auth_type = auth_type;
18238
18239 roam_profile->fils_con_info->r_rk_length =
18240 req->fils_erp_rrk_len;
18241 if (req->fils_erp_rrk_len)
18242 qdf_mem_copy(roam_profile->fils_con_info->r_rk,
18243 req->fils_erp_rrk,
18244 roam_profile->fils_con_info->r_rk_length);
18245
18246 roam_profile->fils_con_info->realm_len = req->fils_erp_realm_len;
18247 if (req->fils_erp_realm_len)
18248 qdf_mem_copy(roam_profile->fils_con_info->realm,
18249 req->fils_erp_realm,
18250 roam_profile->fils_con_info->realm_len);
18251
18252 roam_profile->fils_con_info->key_nai_length =
18253 req->fils_erp_username_len + sizeof(char) +
18254 req->fils_erp_realm_len;
18255 hdd_debug("key_nai_length = %d",
18256 roam_profile->fils_con_info->key_nai_length);
Varun Reddy Yeturu82e39cd2017-10-16 12:04:05 -070018257 if (roam_profile->fils_con_info->key_nai_length >
18258 FILS_MAX_KEYNAME_NAI_LENGTH) {
18259 hdd_err("Do not allow FILS conn due to excess NAI Length %d",
18260 roam_profile->fils_con_info->key_nai_length);
18261 goto fils_conn_fail;
18262 }
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080018263 buf = roam_profile->fils_con_info->keyname_nai;
18264 qdf_mem_copy(buf, req->fils_erp_username, req->fils_erp_username_len);
18265 buf += req->fils_erp_username_len;
18266 *buf++ = '@';
18267 qdf_mem_copy(buf, req->fils_erp_realm, req->fils_erp_realm_len);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018268
18269 return 0;
Varun Reddy Yeturu82e39cd2017-10-16 12:04:05 -070018270
18271fils_conn_fail:
18272 if (roam_profile->fils_con_info) {
18273 qdf_mem_free(roam_profile->fils_con_info);
18274 roam_profile->fils_con_info = NULL;
18275 }
18276 return -EINVAL;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018277}
18278
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018279static bool wlan_hdd_is_akm_suite_fils(uint32_t key_mgmt)
18280{
18281 switch (key_mgmt) {
18282 case WLAN_AKM_SUITE_FILS_SHA256:
18283 case WLAN_AKM_SUITE_FILS_SHA384:
18284 case WLAN_AKM_SUITE_FT_FILS_SHA256:
18285 case WLAN_AKM_SUITE_FT_FILS_SHA384:
18286 return true;
18287 default:
18288 return false;
18289 }
18290}
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018291
18292static bool wlan_hdd_is_conn_type_fils(struct cfg80211_connect_params *req)
18293{
18294 enum nl80211_auth_type auth_type = req->auth_type;
18295 /*
18296 * Below n_akm_suites is defined as int in the kernel, even though it
18297 * is supposed to be unsigned.
18298 */
18299 int num_akm_suites = req->crypto.n_akm_suites;
18300 uint32_t key_mgmt = req->crypto.akm_suites[0];
18301 enum eAniAuthType fils_auth_type =
18302 wlan_hdd_get_fils_auth_type(req->auth_type);
18303
18304 hdd_debug("Num of AKM suites = %d", num_akm_suites);
18305 if (num_akm_suites <= 0)
18306 return false;
18307
18308 /*
18309 * Auth type will be either be OPEN or FILS type for a FILS connection
18310 */
18311 if ((auth_type != NL80211_AUTHTYPE_OPEN_SYSTEM) &&
18312 (fils_auth_type == eSIR_DONOT_USE_AUTH_TYPE)) {
18313 hdd_debug("Not a FILS auth type, auth = %d, fils auth = %d",
18314 auth_type, fils_auth_type);
18315 return false;
18316 }
18317
18318 if (!wlan_hdd_is_akm_suite_fils(key_mgmt)) {
18319 hdd_debug("Not a FILS AKM SUITE %d", key_mgmt);
18320 return false;
18321 }
18322
18323 return true;
18324}
18325
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018326#else
Jeff Johnson20227a92018-03-13 09:41:05 -070018327static bool hdd_validate_fils_info_ptr(struct csr_roam_profile *roam_profile)
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018328{
18329 return true;
18330}
18331
18332static int wlan_hdd_cfg80211_set_fils_config(struct hdd_adapter *adapter,
18333 struct cfg80211_connect_params *req)
18334{
18335 return 0;
18336}
18337
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018338static bool wlan_hdd_is_akm_suite_fils(uint32_t key_mgmt)
18339{
18340 return false;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018341}
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070018342
18343static bool wlan_hdd_is_conn_type_fils(struct cfg80211_connect_params *req)
18344{
18345 return false;
18346}
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018347#endif
18348
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018349/**
18350 * wlan_hdd_set_akm_suite() - set key management type
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018351 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018352 * @key_mgmt: Key management type
18353 *
18354 * This function is used to set the key mgmt type(PSK/8021x).
18355 *
18356 * Return: 0 for success, non-zero for failure
18357 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018358static int wlan_hdd_set_akm_suite(struct hdd_adapter *adapter, u32 key_mgmt)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018359{
Jeff Johnson37ecea42018-03-18 17:54:40 -070018360 struct hdd_station_ctx *sta_ctx;
Jeff Johnson61b5e982018-03-15 11:33:31 -070018361 struct csr_roam_profile *roam_profile;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018362
Jeff Johnson20227a92018-03-13 09:41:05 -070018363 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018364
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018365 if (wlan_hdd_is_akm_suite_fils(key_mgmt) &&
Jeff Johnson20227a92018-03-13 09:41:05 -070018366 !hdd_validate_fils_info_ptr(roam_profile))
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018367 return -EINVAL;
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053018368#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018369#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053018370#endif
18371#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018372#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053018373#endif
Jeff Johnson37ecea42018-03-18 17:54:40 -070018374
18375 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
18376
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018377 /*set key mgmt type */
18378 switch (key_mgmt) {
18379 case WLAN_AKM_SUITE_PSK:
18380 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018381 case WLAN_AKM_SUITE_FT_PSK:
Abhishek Singh02cb9e02017-08-30 17:39:50 +053018382 case WLAN_AKM_SUITE_DPP_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018383 hdd_debug("setting key mgmt type to PSK");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018384 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_PSK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018385 break;
18386
18387 case WLAN_AKM_SUITE_8021X_SHA256:
18388 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018389 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018390 hdd_debug("setting key mgmt type to 8021x");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018391 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018392 break;
18393#ifdef FEATURE_WLAN_ESE
18394#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018395 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018396 hdd_debug("setting key mgmt type to CCKM");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018397 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_CCKM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018398 break;
18399#endif
18400#ifndef WLAN_AKM_SUITE_OSEN
18401#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
18402#endif
18403 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018404 hdd_debug("setting key mgmt type to OSEN");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018405 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018406 break;
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053018407#if defined(WLAN_FEATURE_FILS_SK) && \
18408 (defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
18409 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)))
Sridhar Selvaraj6cf642f2017-08-21 14:28:10 +053018410 case WLAN_AKM_SUITE_FILS_SHA256:
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018411 hdd_debug("setting key mgmt type to FILS SHA256");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018412 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018413 roam_profile->fils_con_info->akm_type =
18414 eCSR_AUTH_TYPE_FILS_SHA256;
18415 break;
18416
18417 case WLAN_AKM_SUITE_FILS_SHA384:
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018418 hdd_debug("setting key mgmt type to FILS SHA384");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018419 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018420 roam_profile->fils_con_info->akm_type =
18421 eCSR_AUTH_TYPE_FILS_SHA384;
18422 break;
18423
18424 case WLAN_AKM_SUITE_FT_FILS_SHA256:
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018425 hdd_debug("setting key mgmt type to FILS FT SHA256");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018426 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018427 roam_profile->fils_con_info->akm_type =
18428 eCSR_AUTH_TYPE_FT_FILS_SHA256;
18429 break;
18430
18431 case WLAN_AKM_SUITE_FT_FILS_SHA384:
Varun Reddy Yeturu625a6412017-10-23 10:20:01 -070018432 hdd_debug("setting key mgmt type to FILS FT SHA384");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018433 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053018434 roam_profile->fils_con_info->akm_type =
18435 eCSR_AUTH_TYPE_FT_FILS_SHA384;
Sridhar Selvaraj6cf642f2017-08-21 14:28:10 +053018436 break;
18437#endif
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053018438
18439 case WLAN_AKM_SUITE_OWE:
18440 hdd_debug("setting key mgmt type to OWE");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018441 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053018442 break;
18443
Padma, Santhosh Kumare587a5c2017-12-21 12:44:46 +053018444 case WLAN_AKM_SUITE_EAP_SHA256:
18445 hdd_debug("setting key mgmt type to EAP_SHA256");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018446 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumare587a5c2017-12-21 12:44:46 +053018447 break;
18448 case WLAN_AKM_SUITE_EAP_SHA384:
18449 hdd_debug("setting key mgmt type to EAP_SHA384");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018450 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumare587a5c2017-12-21 12:44:46 +053018451 break;
18452
Padma, Santhosh Kumar07eb80b2017-07-05 16:10:06 +053018453 case WLAN_AKM_SUITE_SAE:
18454 hdd_debug("setting key mgmt type to SAE");
Jeff Johnson37ecea42018-03-18 17:54:40 -070018455 sta_ctx->auth_key_mgmt |= HDD_AUTH_KEY_MGMT_802_1X;
Padma, Santhosh Kumar07eb80b2017-07-05 16:10:06 +053018456 break;
18457
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018458 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018459 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018460 return -EINVAL;
18461
18462 }
18463 return 0;
18464}
18465
18466/**
18467 * wlan_hdd_cfg80211_set_cipher() - set encryption type
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018468 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018469 * @cipher: Cipher type
18470 * @ucast: Unicast flag
18471 *
18472 * This function is used to set the encryption type
18473 * (NONE/WEP40/WEP104/TKIP/CCMP).
18474 *
18475 * Return: 0 for success, non-zero for failure
18476 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018477static int wlan_hdd_cfg80211_set_cipher(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018478 u32 cipher, bool ucast)
18479{
18480 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
Jeff Johnsond377dce2017-10-04 10:32:42 -070018481 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018482 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070018483 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018484
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018485 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018486 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018487 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
18488 } else {
18489
18490 /*set encryption method */
18491 switch (cipher) {
18492 case IW_AUTH_CIPHER_NONE:
18493 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
18494 break;
18495
18496 case WLAN_CIPHER_SUITE_WEP40:
18497 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
18498 break;
18499
18500 case WLAN_CIPHER_SUITE_WEP104:
18501 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
18502 break;
18503
18504 case WLAN_CIPHER_SUITE_TKIP:
18505 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
18506 break;
18507
18508 case WLAN_CIPHER_SUITE_CCMP:
18509 encryptionType = eCSR_ENCRYPT_TYPE_AES;
18510 break;
18511#ifdef FEATURE_WLAN_WAPI
18512 case WLAN_CIPHER_SUITE_SMS4:
18513 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
18514 break;
18515#endif
18516
18517#ifdef FEATURE_WLAN_ESE
18518 case WLAN_CIPHER_SUITE_KRK:
18519 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
18520 break;
18521#ifdef WLAN_FEATURE_ROAM_OFFLOAD
18522 case WLAN_CIPHER_SUITE_BTK:
18523 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
18524 break;
18525#endif
18526#endif
Mukul Sharma05504ac2017-06-08 12:35:53 +053018527 case WLAN_CIPHER_SUITE_GCMP:
18528 encryptionType = eCSR_ENCRYPT_TYPE_AES_GCMP;
18529 break;
18530 case WLAN_CIPHER_SUITE_GCMP_256:
18531 encryptionType = eCSR_ENCRYPT_TYPE_AES_GCMP_256;
18532 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018533 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018534 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018535 return -EOPNOTSUPP;
18536 }
18537 }
18538
Jeff Johnson20227a92018-03-13 09:41:05 -070018539 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018540 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018541 hdd_debug("setting unicast cipher type to %d", encryptionType);
Jeff Johnsond377dce2017-10-04 10:32:42 -070018542 sta_ctx->conn_info.ucEncryptionType = encryptionType;
Jeff Johnson20227a92018-03-13 09:41:05 -070018543 roam_profile->EncryptionType.numEntries = 1;
18544 roam_profile->EncryptionType.encryptionType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018545 encryptionType;
18546 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018547 hdd_debug("setting mcast cipher type to %d", encryptionType);
Jeff Johnsond377dce2017-10-04 10:32:42 -070018548 sta_ctx->conn_info.mcEncryptionType = encryptionType;
Jeff Johnson20227a92018-03-13 09:41:05 -070018549 roam_profile->mcEncryptionType.numEntries = 1;
18550 roam_profile->mcEncryptionType.encryptionType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018551 encryptionType;
18552 }
18553
18554 return 0;
18555}
18556
18557/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018558 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
Jeff Johnson20227a92018-03-13 09:41:05 -070018559 * @adapter: Pointer to adapter
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018560 * @gen_ie: Pointer to IE data
18561 * @len: length of IE data
18562 *
18563 * Return: 0 for success, non-zero for failure
18564 */
Jeff Johnson20227a92018-03-13 09:41:05 -070018565static int wlan_hdd_add_assoc_ie(struct hdd_adapter *adapter,
18566 const uint8_t *gen_ie, uint16_t len)
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018567{
Jeff Johnson20227a92018-03-13 09:41:05 -070018568 struct csr_roam_profile *roam_profile;
18569 tSirAddie *assoc_add_ie;
18570 uint16_t cur_add_ie_len;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018571
Jeff Johnson20227a92018-03-13 09:41:05 -070018572 assoc_add_ie = hdd_assoc_additional_ie(adapter);
18573 cur_add_ie_len = assoc_add_ie->length;
18574 if (SIR_MAC_MAX_ADD_IE_LENGTH < (cur_add_ie_len + len)) {
18575 hdd_err("current len %u, new ie of len %u will overflow",
18576 cur_add_ie_len, len);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018577 return -ENOMEM;
18578 }
Jeff Johnson20227a92018-03-13 09:41:05 -070018579 memcpy(assoc_add_ie->addIEdata + cur_add_ie_len, gen_ie, len);
18580 assoc_add_ie->length += len;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018581
Jeff Johnson20227a92018-03-13 09:41:05 -070018582 roam_profile = hdd_roam_profile(adapter);
18583 roam_profile->pAddIEAssoc = assoc_add_ie->addIEdata;
18584 roam_profile->nAddIEAssocLength = assoc_add_ie->length;
18585
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018586 return 0;
18587}
18588
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053018589#ifdef WLAN_FEATURE_FILS_SK
18590/**
18591 * wlan_hdd_save_hlp_ie - API to save HLP IE
18592 * @roam_profile: Pointer to roam profile
18593 * @gen_ie: IE buffer to store
18594 * @len: length of the IE buffer @gen_ie
18595 * @flush: Flush the older saved HLP if any
18596 *
18597 * Return: None
18598 */
Jeff Johnson61b5e982018-03-15 11:33:31 -070018599static void wlan_hdd_save_hlp_ie(struct csr_roam_profile *roam_profile,
Jeff Johnson20227a92018-03-13 09:41:05 -070018600 const uint8_t *gen_ie, uint16_t len,
18601 bool flush)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053018602{
18603 uint8_t *hlp_ie = roam_profile->hlp_ie;
18604
18605 if (flush) {
18606 roam_profile->hlp_ie_len = 0;
18607 if (hlp_ie) {
18608 qdf_mem_free(hlp_ie);
18609 roam_profile->hlp_ie = NULL;
18610 }
18611 }
18612
18613 if ((roam_profile->hlp_ie_len +
18614 len) > FILS_MAX_HLP_DATA_LEN) {
18615 hdd_err("HLP len exceeds: hlp_ie_len %d len %d",
18616 roam_profile->hlp_ie_len, len);
18617 return;
18618 }
18619
18620 if (!roam_profile->hlp_ie) {
18621 roam_profile->hlp_ie =
18622 qdf_mem_malloc(FILS_MAX_HLP_DATA_LEN);
18623 hlp_ie = roam_profile->hlp_ie;
18624 if (!hlp_ie) {
18625 hdd_err("HLP IE mem alloc fails");
18626 return;
18627 }
18628 }
18629
18630 qdf_mem_copy(hlp_ie + roam_profile->hlp_ie_len, gen_ie, len);
18631 roam_profile->hlp_ie_len += len;
18632}
18633#else
Jeff Johnson61b5e982018-03-15 11:33:31 -070018634static inline void wlan_hdd_save_hlp_ie(struct csr_roam_profile *roam_profile,
Jeff Johnson20227a92018-03-13 09:41:05 -070018635 const uint8_t *gen_ie, uint16_t len,
18636 bool flush)
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053018637{}
18638#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018639/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018640 * wlan_hdd_cfg80211_set_ie() - set IEs
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018641 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018642 * @ie: Pointer ot ie
18643 * @ie: IE length
18644 *
18645 * Return: 0 for success, non-zero for failure
18646 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018647static int wlan_hdd_cfg80211_set_ie(struct hdd_adapter *adapter,
Jeff Johnson2a722002017-09-30 20:02:35 -070018648 const uint8_t *ie,
18649 size_t ie_len)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018650{
Jeff Johnson20227a92018-03-13 09:41:05 -070018651 struct csr_roam_profile *roam_profile;
18652 tSirAddie *assoc_add_ie;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018653 const uint8_t *genie = ie;
18654 uint16_t remLen = ie_len;
18655#ifdef FEATURE_WLAN_WAPI
18656 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
18657 u16 *tmp;
18658 uint16_t akmsuiteCount;
18659 int *akmlist;
18660#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018661 int status;
Jeff Johnson20227a92018-03-13 09:41:05 -070018662 uint8_t *security_ie;
18663
18664 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018665
18666 /* clear previous assocAddIE */
Jeff Johnson20227a92018-03-13 09:41:05 -070018667 assoc_add_ie = hdd_assoc_additional_ie(adapter);
18668 assoc_add_ie->length = 0;
18669 roam_profile->bWPSAssociation = false;
18670 roam_profile->bOSENAssociation = false;
18671 security_ie = hdd_security_ie(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018672
18673 while (remLen >= 2) {
18674 uint16_t eLen = 0;
18675 uint8_t elementId;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070018676
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018677 elementId = *genie++;
18678 eLen = *genie++;
18679 remLen -= 2;
18680
Nachiket Kukade4bea8b42017-06-13 11:53:19 +053018681 /* Sanity check on eLen */
18682 if (eLen > remLen) {
18683 hdd_err("%s: Invalid IE length[%d] for IE[0x%X]",
18684 __func__, eLen, elementId);
18685 QDF_ASSERT(0);
18686 return -EINVAL;
18687 }
18688
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018689 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018690
18691 switch (elementId) {
18692 case DOT11F_EID_WPA:
18693 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 -070018694 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018695 return -EINVAL;
18696 } else if (0 ==
18697 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
Jeff Johnson20227a92018-03-13 09:41:05 -070018698 uint16_t curAddIELen = assoc_add_ie->length;
18699
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018700 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018701
18702 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070018703 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018704 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018705 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018706 return -ENOMEM;
18707 }
18708 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
Jeff Johnson20227a92018-03-13 09:41:05 -070018709 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018710 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070018711 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018712
Jeff Johnson20227a92018-03-13 09:41:05 -070018713 roam_profile->bWPSAssociation = true;
18714 roam_profile->pAddIEAssoc =
18715 assoc_add_ie->addIEdata;
18716 roam_profile->nAddIEAssocLength =
18717 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018718 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Nachiket Kukade2f6509f2017-06-13 17:45:46 +053018719 if (eLen > (MAX_WPA_RSN_IE_LEN - 2)) {
18720 hdd_err("%s: Invalid WPA IE length[%d]",
18721 __func__, eLen);
18722 QDF_ASSERT(0);
18723 return -EINVAL;
18724 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018725 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070018726 memset(security_ie, 0, MAX_WPA_RSN_IE_LEN);
18727 memcpy(security_ie, genie - 2, (eLen + 2));
18728 roam_profile->pWPAReqIE = security_ie;
18729 roam_profile->nWPAReqIELength = eLen + 2; /* ie_len; */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018730 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
18731 P2P_OUI_TYPE_SIZE))) {
18732 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070018733 assoc_add_ie->length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018734 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018735
18736 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070018737 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018738 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018739 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018740 return -ENOMEM;
18741 }
18742 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
Jeff Johnson20227a92018-03-13 09:41:05 -070018743 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018744 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070018745 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018746
Jeff Johnson20227a92018-03-13 09:41:05 -070018747 roam_profile->pAddIEAssoc =
18748 assoc_add_ie->addIEdata;
18749 roam_profile->nAddIEAssocLength =
18750 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018751 }
18752#ifdef WLAN_FEATURE_WFD
18753 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
18754 WFD_OUI_TYPE_SIZE)) &&
18755 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080018756 (QDF_P2P_CLIENT_MODE ==
Jeff Johnsonce2ba702017-10-02 13:30:24 -070018757 adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018758 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070018759 assoc_add_ie->length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018760 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018761
18762 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070018763 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018764 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018765 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018766 return -ENOMEM;
18767 }
18768 /* WFD IE is saved to Additional IE ; it should
18769 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080018770 * WFD IE
18771 */
Jeff Johnson20227a92018-03-13 09:41:05 -070018772 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018773 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070018774 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018775
Jeff Johnson20227a92018-03-13 09:41:05 -070018776 roam_profile->pAddIEAssoc =
18777 assoc_add_ie->addIEdata;
18778 roam_profile->nAddIEAssocLength =
18779 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018780 }
18781#endif
18782 /* Appending HS 2.0 Indication Element in Assiciation Request */
18783 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
18784 HS20_OUI_TYPE_SIZE))) {
18785 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070018786 assoc_add_ie->length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018787 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018788
18789 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070018790 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018791 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018792 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018793 return -ENOMEM;
18794 }
Jeff Johnson20227a92018-03-13 09:41:05 -070018795 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018796 curAddIELen, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070018797 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018798
Jeff Johnson20227a92018-03-13 09:41:05 -070018799 roam_profile->pAddIEAssoc =
18800 assoc_add_ie->addIEdata;
18801 roam_profile->nAddIEAssocLength =
18802 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018803 }
18804 /* Appending OSEN Information Element in Assiciation Request */
18805 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
18806 OSEN_OUI_TYPE_SIZE))) {
18807 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070018808 assoc_add_ie->length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018809 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018810
18811 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070018812 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018813 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018814 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018815 return -ENOMEM;
18816 }
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->bOSENAssociation = true;
18822 roam_profile->pAddIEAssoc =
18823 assoc_add_ie->addIEdata;
18824 roam_profile->nAddIEAssocLength =
18825 assoc_add_ie->length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018826 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
18827 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018828 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070018829 status = wlan_hdd_add_assoc_ie(adapter,
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018830 genie - 2, eLen + 2);
18831 if (status)
18832 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018833 } else {
18834 uint16_t add_ie_len =
Jeff Johnson20227a92018-03-13 09:41:05 -070018835 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018836
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018837 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018838
18839 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070018840 (assoc_add_ie->length + eLen)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018841 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018842 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018843 return -ENOMEM;
18844 }
18845
Jeff Johnson20227a92018-03-13 09:41:05 -070018846 memcpy(assoc_add_ie->addIEdata +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018847 add_ie_len, genie - 2, eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070018848 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018849
Jeff Johnson20227a92018-03-13 09:41:05 -070018850 roam_profile->pAddIEAssoc =
18851 assoc_add_ie->addIEdata;
18852 roam_profile->nAddIEAssocLength =
18853 assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018854 }
18855 break;
18856 case DOT11F_EID_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018857 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Vignesh Viswanathan96e0e702017-12-05 19:42:46 +053018858 if (eLen > (MAX_WPA_RSN_IE_LEN - 2)) {
18859 hdd_err("%s: Invalid WPA RSN IE length[%d]",
18860 __func__, eLen);
18861 return -EINVAL;
18862 }
Jeff Johnson20227a92018-03-13 09:41:05 -070018863 memset(security_ie, 0, MAX_WPA_RSN_IE_LEN);
18864 memcpy(security_ie, genie - 2, (eLen + 2));
18865 roam_profile->pRSNReqIE = security_ie;
18866 roam_profile->nRSNReqIELength = eLen + 2; /* ie_len; */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018867 break;
18868 /*
18869 * Appending Extended Capabilities with Interworking bit set
18870 * in Assoc Req.
18871 *
18872 * In assoc req this EXT Cap will only be taken into account if
18873 * interworkingService bit is set to 1. Currently
18874 * driver is only interested in interworkingService capability
18875 * from supplicant. If in future any other EXT Cap info is
18876 * required from supplicat, it needs to be handled while
18877 * sending Assoc Req in LIM.
18878 */
18879 case DOT11F_EID_EXTCAP:
18880 {
18881 uint16_t curAddIELen =
Jeff Johnson20227a92018-03-13 09:41:05 -070018882 assoc_add_ie->length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018883 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018884
18885 if (SIR_MAC_MAX_ADD_IE_LENGTH <
Jeff Johnson20227a92018-03-13 09:41:05 -070018886 (assoc_add_ie->length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070018887 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018888 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018889 return -ENOMEM;
18890 }
Jeff Johnson20227a92018-03-13 09:41:05 -070018891 memcpy(assoc_add_ie->addIEdata + curAddIELen, genie - 2, eLen + 2);
18892 assoc_add_ie->length += eLen + 2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018893
Jeff Johnson20227a92018-03-13 09:41:05 -070018894 roam_profile->pAddIEAssoc = assoc_add_ie->addIEdata;
18895 roam_profile->nAddIEAssocLength = assoc_add_ie->length;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018896 break;
18897 }
18898#ifdef FEATURE_WLAN_WAPI
18899 case WLAN_EID_WAPI:
18900 /* Setting WAPI Mode to ON=1 */
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070018901 adapter->wapi_info.wapi_mode = true;
18902 hdd_debug("WAPI MODE IS %u", adapter->wapi_info.wapi_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018903 tmp = (u16 *) ie;
18904 tmp = tmp + 2; /* Skip element Id and Len, Version */
18905 akmsuiteCount = WPA_GET_LE16(tmp);
18906 tmp = tmp + 1;
18907 akmlist = (int *)(tmp);
18908 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
18909 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
18910 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018911 hdd_err("Invalid akmSuite count: %u",
18912 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053018913 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018914 return -EINVAL;
18915 }
18916
18917 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018918 hdd_debug("WAPI AUTH MODE SET TO PSK");
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070018919 adapter->wapi_info.wapi_auth_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018920 WAPI_AUTH_MODE_PSK;
18921 }
18922 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018923 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Jeff Johnson7d2f4c62017-11-02 09:25:45 -070018924 adapter->wapi_info.wapi_auth_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018925 WAPI_AUTH_MODE_CERT;
18926 }
18927 break;
18928#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018929 case DOT11F_EID_SUPPOPERATINGCLASSES:
18930 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018931 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070018932 status = wlan_hdd_add_assoc_ie(adapter,
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053018933 genie - 2, eLen + 2);
18934 if (status)
18935 return status;
18936 break;
18937 }
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053018938 case SIR_MAC_REQUEST_EID_MAX:
18939 {
18940 if (genie[0] == SIR_FILS_HLP_EXT_EID) {
18941 hdd_debug("Set HLP EXT IE(len %d)",
18942 eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070018943 wlan_hdd_save_hlp_ie(roam_profile,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053018944 genie - 2, eLen + 2,
18945 true);
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053018946 status = wlan_hdd_add_assoc_ie(
Jeff Johnson20227a92018-03-13 09:41:05 -070018947 adapter, genie - 2,
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053018948 eLen + 2);
18949 if (status)
18950 return status;
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053018951 } else if (genie[0] ==
18952 SIR_DH_PARAMETER_ELEMENT_EXT_EID) {
18953 hdd_debug("Set DH EXT IE(len %d)",
18954 eLen + 2);
18955 status = wlan_hdd_add_assoc_ie(
Jeff Johnson20227a92018-03-13 09:41:05 -070018956 adapter, genie - 2,
Padma, Santhosh Kumarc69ce072017-11-06 18:21:05 +053018957 eLen + 2);
18958 if (status)
18959 return status;
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053018960 } else {
18961 hdd_err("UNKNOWN EID: %X", genie[0]);
18962 }
18963 break;
18964 }
18965 case DOT11F_EID_FRAGMENT_IE:
18966 {
18967 hdd_debug("Set Fragment IE(len %d)", eLen + 2);
Jeff Johnson20227a92018-03-13 09:41:05 -070018968 wlan_hdd_save_hlp_ie(roam_profile,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053018969 genie - 2, eLen + 2,
18970 false);
Jeff Johnson20227a92018-03-13 09:41:05 -070018971 status = wlan_hdd_add_assoc_ie(adapter,
Sridhar Selvaraj6d3e0d72017-08-17 17:32:37 +053018972 genie - 2, eLen + 2);
18973 if (status)
18974 return status;
18975 break;
18976 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018977 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080018978 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080018979 /* when Unknown IE is received we break
18980 * and continue to the next IE in the buffer
18981 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018982 break;
18983 }
18984 genie += eLen;
18985 remLen -= eLen;
18986 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080018987 return 0;
18988}
18989
18990/**
18991 * hdd_is_wpaie_present() - check for WPA ie
18992 * @ie: Pointer to ie
18993 * @ie_len: Ie length
18994 *
18995 * Parse the received IE to find the WPA IE
18996 *
18997 * Return: true if wpa ie is found else false
18998 */
18999static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
19000{
19001 uint8_t eLen = 0;
19002 uint16_t remLen = ie_len;
19003 uint8_t elementId = 0;
19004
19005 while (remLen >= 2) {
19006 elementId = *ie++;
19007 eLen = *ie++;
19008 remLen -= 2;
19009 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019010 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019011 return false;
19012 }
19013 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
19014 /* OUI - 0x00 0X50 0XF2
19015 * WPA Information Element - 0x01
19016 * WPA version - 0x01
19017 */
19018 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
19019 return true;
19020 }
19021 ie += eLen;
19022 remLen -= eLen;
19023 }
19024 return false;
19025}
19026
19027/**
19028 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019029 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019030 * @req: Pointer to security parameters
19031 *
19032 * Return: 0 for success, non-zero for failure
19033 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019034static int wlan_hdd_cfg80211_set_privacy(struct hdd_adapter *adapter,
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070019035 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019036{
19037 int status = 0;
Jeff Johnsonce4a8342017-10-14 13:12:22 -070019038 struct hdd_station_ctx *sta_ctx;
Jeff Johnson20227a92018-03-13 09:41:05 -070019039 struct csr_roam_profile *roam_profile;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070019040
Dustin Brown491d54b2018-03-14 12:39:11 -070019041 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019042
Jeff Johnsonce4a8342017-10-14 13:12:22 -070019043 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
19044 sta_ctx->wpa_versions = req->crypto.wpa_versions;
19045 hdd_debug("set wpa version to %d", sta_ctx->wpa_versions);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019046
Jeff Johnson20227a92018-03-13 09:41:05 -070019047 roam_profile = hdd_roam_profile(adapter);
19048
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019049 /*set authentication type */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019050 status = wlan_hdd_cfg80211_set_auth_type(adapter, req->auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019051
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070019052 if (wlan_hdd_is_conn_type_fils(req)) {
19053 status = wlan_hdd_cfg80211_set_fils_config(adapter, req);
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053019054
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070019055 if (0 > status) {
19056 hdd_err("Failed to set fils config");
19057 return status;
19058 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019059 }
19060
19061 /*set key mgmt type */
19062 if (req->crypto.n_akm_suites) {
19063 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019064 wlan_hdd_set_akm_suite(adapter, req->crypto.akm_suites[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019065 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019066 hdd_err("Failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019067 return status;
19068 }
19069 }
19070
19071 /*set pairwise cipher type */
19072 if (req->crypto.n_ciphers_pairwise) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019073 status = wlan_hdd_cfg80211_set_cipher(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019074 req->crypto.
19075 ciphers_pairwise[0],
19076 true);
19077 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019078 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019079 return status;
19080 }
19081 } else {
19082 /*Reset previous cipher suite to none */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019083 status = wlan_hdd_cfg80211_set_cipher(adapter, 0, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019084 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019085 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019086 return status;
19087 }
19088 }
19089
19090 /*set group cipher type */
19091 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019092 wlan_hdd_cfg80211_set_cipher(adapter, req->crypto.cipher_group,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019093 false);
19094
19095 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019096 hdd_err("Failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019097 return status;
19098 }
19099#ifdef WLAN_FEATURE_11W
Jeff Johnson20227a92018-03-13 09:41:05 -070019100 roam_profile->MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019101#endif
19102
19103 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
19104 if (req->ie_len) {
19105 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019106 wlan_hdd_cfg80211_set_ie(adapter, req->ie, req->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019107 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019108 hdd_err("Failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019109 return status;
19110 }
19111 }
19112
19113 /*incase of WEP set default key information */
19114 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080019115 u8 key_len = req->key_len;
19116 u8 key_idx = req->key_idx;
Jeff Johnson37ecea42018-03-18 17:54:40 -070019117 u32 cipher = req->crypto.ciphers_pairwise[0];
Jeff Johnson68755312017-02-10 11:46:55 -080019118
Jeff Johnson37ecea42018-03-18 17:54:40 -070019119 if ((WLAN_CIPHER_SUITE_WEP40 == cipher) ||
19120 (WLAN_CIPHER_SUITE_WEP104 == cipher)) {
19121 enum hdd_auth_key_mgmt key_mgmt =
19122 sta_ctx->auth_key_mgmt;
19123
19124 if (key_mgmt & HDD_AUTH_KEY_MGMT_802_1X) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019125 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019126 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080019127 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019128
Jeff Johnson68755312017-02-10 11:46:55 -080019129 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
19130 && (CSR_MAX_NUM_KEY > key_idx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019131 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson68755312017-02-10 11:46:55 -080019132 key_idx, key_len);
Jeff Johnson20227a92018-03-13 09:41:05 -070019133 qdf_mem_copy(&roam_profile->Keys.
Jeff Johnson68755312017-02-10 11:46:55 -080019134 KeyMaterial[key_idx][0],
19135 req->key, key_len);
Jeff Johnson20227a92018-03-13 09:41:05 -070019136 roam_profile->Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019137 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson20227a92018-03-13 09:41:05 -070019138 roam_profile->Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019139 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019140 }
19141 }
19142 }
19143
19144 return status;
19145}
19146
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019147int wlan_hdd_try_disconnect(struct hdd_adapter *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019148{
19149 unsigned long rc;
Jeff Johnsond377dce2017-10-04 10:32:42 -070019150 struct hdd_station_ctx *sta_ctx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019151 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080019152 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019153
Jeff Johnsond377dce2017-10-04 10:32:42 -070019154 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019155 hal = WLAN_HDD_GET_HAL_CTX(adapter);
19156 if (adapter->device_mode == QDF_STA_MODE) {
Jeff Johnson1b780e42017-10-31 14:11:45 -070019157 sme_indicate_disconnect_inprogress(hal, adapter->session_id);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019158 hdd_debug("Stop firmware roaming");
Jeff Johnson1b780e42017-10-31 14:11:45 -070019159 sme_stop_roaming(hal, adapter->session_id, eCsrForcedDisassoc);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080019160
Abhishek Singh533c9da2017-05-04 10:23:34 +053019161 /*
19162 * If firmware has already started roaming process, driver
19163 * needs to wait for processing of this disconnect request.
19164 *
19165 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019166 INIT_COMPLETION(adapter->roaming_comp_var);
19167 if (hdd_is_roaming_in_progress(adapter)) {
Abhishek Singh533c9da2017-05-04 10:23:34 +053019168 rc = wait_for_completion_timeout(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019169 &adapter->roaming_comp_var,
Abhishek Singh533c9da2017-05-04 10:23:34 +053019170 msecs_to_jiffies(WLAN_WAIT_TIME_STOP_ROAM));
19171 if (!rc) {
19172 hdd_err("roaming comp var timed out session Id: %d",
Jeff Johnson1b780e42017-10-31 14:11:45 -070019173 adapter->session_id);
Abhishek Singh533c9da2017-05-04 10:23:34 +053019174 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019175 if (adapter->roam_ho_fail) {
19176 INIT_COMPLETION(adapter->disconnect_comp_var);
19177 hdd_conn_set_connection_state(adapter,
Abhishek Singh533c9da2017-05-04 10:23:34 +053019178 eConnectionState_Disconnecting);
19179 }
19180 }
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080019181 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019182
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019183 if ((QDF_IBSS_MODE == adapter->device_mode) ||
Jeff Johnsond377dce2017-10-04 10:32:42 -070019184 (eConnectionState_Associated == sta_ctx->conn_info.connState) ||
19185 (eConnectionState_Connecting == sta_ctx->conn_info.connState) ||
19186 (eConnectionState_IbssConnected == sta_ctx->conn_info.connState)) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019187 hdd_conn_set_connection_state(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019188 eConnectionState_Disconnecting);
19189 /* Issue disconnect to CSR */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019190 INIT_COMPLETION(adapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019191
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019192 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -070019193 adapter->session_id,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019194 eCSR_DISCONNECT_REASON_UNSPECIFIED);
19195 /*
19196 * Wait here instead of returning directly, this will block the
19197 * next connect command and allow processing of the scan for
19198 * ssid and the previous connect command in CSR. Else we might
19199 * hit some race conditions leading to SME and HDD out of sync.
19200 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053019201 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019202 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019203 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019204 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019205 (int)status);
Jeff Johnson8380f232017-10-25 12:39:44 -070019206 sta_ctx->sta_debug_state = status;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019207 result = -EINVAL;
19208 goto disconnected;
19209 }
19210
19211 rc = wait_for_completion_timeout(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019212 &adapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019213 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053019214 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson8380f232017-10-25 12:39:44 -070019215 hdd_err("Sme disconnect event timed out session Id: %d sta_debug_state: %d",
Jeff Johnson1b780e42017-10-31 14:11:45 -070019216 adapter->session_id, sta_ctx->sta_debug_state);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019217 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019218 }
19219 } else if (eConnectionState_Disconnecting ==
Jeff Johnsond377dce2017-10-04 10:32:42 -070019220 sta_ctx->conn_info.connState) {
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019221 rc = wait_for_completion_timeout(&adapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019222 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019223 if (!rc) {
Jeff Johnson8380f232017-10-25 12:39:44 -070019224 hdd_err("Disconnect event timed out session Id: %d sta_debug_state: %d",
Jeff Johnson1b780e42017-10-31 14:11:45 -070019225 adapter->session_id, sta_ctx->sta_debug_state);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019226 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019227 }
19228 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019229disconnected:
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019230 hdd_conn_set_connection_state(adapter, eConnectionState_NotConnected);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053019231 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019232}
19233
19234/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019235 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
19236 * @adapter: Pointer to the HDD adapter
19237 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070019238 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019239 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053019240 * This function will start reassociation if prev_bssid is set and bssid/
19241 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019242 *
Naveen Rawat07332902016-07-27 09:13:17 -070019243 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019244 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053019245#if defined(CFG80211_CONNECT_PREV_BSSID) || \
19246 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Jeff Johnsone5006672017-08-29 14:39:02 -070019247static bool wlan_hdd_reassoc_bssid_hint(struct hdd_adapter *adapter,
Naveen Rawat07332902016-07-27 09:13:17 -070019248 struct cfg80211_connect_params *req,
19249 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019250{
Naveen Rawat07332902016-07-27 09:13:17 -070019251 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053019252 const uint8_t *bssid = NULL;
19253 uint16_t channel = 0;
Jeff Johnson731bc322017-10-14 19:53:44 -070019254 struct hdd_station_ctx *sta_ctx;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053019255
19256 if (req->bssid)
19257 bssid = req->bssid;
19258 else if (req->bssid_hint)
19259 bssid = req->bssid_hint;
19260
19261 if (req->channel)
19262 channel = req->channel->hw_value;
19263 else if (req->channel_hint)
19264 channel = req->channel_hint->hw_value;
19265
19266 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070019267 reassoc = true;
Dustin Brownbacc48f2018-03-14 14:48:44 -070019268 hdd_debug("REASSOC Attempt on channel %d to " MAC_ADDRESS_STR,
19269 channel, MAC_ADDR_ARRAY(bssid));
Arif Hussain43354e62017-05-24 11:24:25 -070019270 /*
19271 * Save BSSID in a separate variable as
Jeff Johnson5b34fce2017-10-13 13:24:51 -070019272 * roam_profile's BSSID is getting zeroed out in the
Arif Hussain43354e62017-05-24 11:24:25 -070019273 * association process. In case of join failure
19274 * we should send valid BSSID to supplicant
19275 */
Jeff Johnson731bc322017-10-14 19:53:44 -070019276 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
19277 qdf_mem_copy(sta_ctx->requested_bssid.bytes, bssid,
Arif Hussain43354e62017-05-24 11:24:25 -070019278 QDF_MAC_ADDR_SIZE);
19279
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053019280 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019281 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070019282 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019283 }
Naveen Rawat07332902016-07-27 09:13:17 -070019284 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019285}
19286#else
Jeff Johnsone5006672017-08-29 14:39:02 -070019287static bool wlan_hdd_reassoc_bssid_hint(struct hdd_adapter *adapter,
Naveen Rawat07332902016-07-27 09:13:17 -070019288 struct cfg80211_connect_params *req,
19289 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019290{
Naveen Rawat07332902016-07-27 09:13:17 -070019291 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019292}
19293#endif
19294
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019295
19296/**
19297 * wlan_hdd_check_ht20_ht40_ind() - check if Supplicant has indicated to
19298 * connect in HT20 mode
19299 * @hdd_ctx: hdd context
19300 * @adapter: Pointer to the HDD adapter
19301 * @req: Pointer to the structure cfg_connect_params receieved from user space
19302 *
19303 * This function will check if supplicant has indicated to to connect in HT20
19304 * mode. this is currently applicable only for 2.4Ghz mode only.
19305 * if feature is enabled and supplicant indicate HT20 set
19306 * force_24ghz_in_ht20 to true to force 2.4Ghz in HT20 else set it to false.
19307 *
19308 * Return: void
19309 */
19310#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
Jeff Johnson20227a92018-03-13 09:41:05 -070019311static void
19312wlan_hdd_check_ht20_ht40_ind(struct hdd_context *hdd_ctx,
19313 struct hdd_adapter *adapter,
19314 struct cfg80211_connect_params *req)
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019315{
Jeff Johnson61b5e982018-03-15 11:33:31 -070019316 struct csr_roam_profile *roam_profile;
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019317
Jeff Johnson20227a92018-03-13 09:41:05 -070019318 roam_profile = hdd_roam_profile(adapter);
19319
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019320 roam_profile->force_24ghz_in_ht20 = false;
19321
19322 if (hdd_ctx->config->override_ht20_40_24g &&
Jeff Johnson20227a92018-03-13 09:41:05 -070019323 !(req->ht_capa.cap_info & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019324 roam_profile->force_24ghz_in_ht20 = true;
19325
19326 hdd_debug("req->ht_capa.cap_info %x override_ht20_40_24g %d",
19327 req->ht_capa.cap_info,
19328 hdd_ctx->config->override_ht20_40_24g);
19329}
19330#else
Jeff Johnson20227a92018-03-13 09:41:05 -070019331static inline void
19332wlan_hdd_check_ht20_ht40_ind(struct hdd_context *hdd_ctx,
19333 struct hdd_adapter *adapter,
19334 struct cfg80211_connect_params *req)
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019335{
Jeff Johnson61b5e982018-03-15 11:33:31 -070019336 struct csr_roam_profile *roam_profile;
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019337
Jeff Johnson20227a92018-03-13 09:41:05 -070019338 roam_profile = hdd_roam_profile(adapter);
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019339
19340 roam_profile->force_24ghz_in_ht20 = false;
19341}
19342#endif
19343
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019344/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019345 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
19346 * @wiphy: Pointer to wiphy
19347 * @dev: Pointer to network device
19348 * @req: Pointer to cfg80211 connect request
19349 *
19350 * This function is used to start the association process
19351 *
19352 * Return: 0 for success, non-zero for failure
19353 */
19354static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
19355 struct net_device *ndev,
19356 struct cfg80211_connect_params *req)
19357{
19358 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053019359 u16 channel;
Arif Hussainee677012017-01-26 17:50:13 -080019360 const u8 *bssid = NULL;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053019361#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
19362 const u8 *bssid_hint = req->bssid_hint;
19363#else
19364 const u8 *bssid_hint = NULL;
19365#endif
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019366 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070019367 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019368
Dustin Brown491d54b2018-03-14 12:39:11 -070019369 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019370
Anurag Chouhan6d760662016-02-20 16:05:43 +053019371 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019372 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019373 return -EINVAL;
19374 }
19375
Jeff Johnson1b780e42017-10-31 14:11:45 -070019376 if (wlan_hdd_validate_session_id(adapter->session_id)) {
19377 hdd_err("invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053019378 return -EINVAL;
19379 }
19380
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053019381 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019382 TRACE_CODE_HDD_CFG80211_CONNECT,
Jeff Johnson1b780e42017-10-31 14:11:45 -070019383 adapter->session_id, adapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019384 hdd_debug("Device_mode %s(%d)",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019385 hdd_device_mode_to_string(adapter->device_mode),
19386 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019387
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019388 if (adapter->device_mode != QDF_STA_MODE &&
19389 adapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019390 hdd_err("Device_mode %s(%d) is not supported",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019391 hdd_device_mode_to_string(adapter->device_mode),
19392 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019393 return -EINVAL;
19394 }
19395
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019396 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070019397 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019398 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019399 return -EINVAL;
19400 }
19401
Jeff Johnsonb8944722017-09-03 09:03:19 -070019402 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053019403 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019404 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019405
Arif Hussainee677012017-01-26 17:50:13 -080019406 if (req->bssid)
19407 bssid = req->bssid;
19408 else if (bssid_hint)
19409 bssid = bssid_hint;
19410
Jeff Johnsonb8944722017-09-03 09:03:19 -070019411 if (bssid && hdd_get_adapter_by_macaddr(hdd_ctx, (uint8_t *)bssid)) {
Arif Hussain7631afa2017-02-08 14:35:00 -080019412 hdd_err("adapter exist with same mac address " MAC_ADDRESS_STR,
19413 MAC_ADDR_ARRAY(bssid));
19414 return -EINVAL;
Arif Hussainee677012017-01-26 17:50:13 -080019415 }
19416
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019417 if (true == wlan_hdd_reassoc_bssid_hint(adapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019418 return status;
19419
Agrawal Ashishf156e942016-08-04 14:54:47 +053019420 /* Try disconnecting if already in connected state */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019421 status = wlan_hdd_try_disconnect(adapter);
Agrawal Ashishf156e942016-08-04 14:54:47 +053019422 if (0 > status) {
19423 hdd_err("Failed to disconnect the existing connection");
19424 return -EALREADY;
19425 }
19426
19427 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019428 if (req->channel) {
Min Liuab6ed4f2018-01-09 13:13:57 +080019429 bool ok = false;
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053019430
19431 if (req->channel->hw_value && policy_mgr_is_chan_ok_for_dnbs(
Jeff Johnsonb8944722017-09-03 09:03:19 -070019432 hdd_ctx->hdd_psoc,
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053019433 req->channel->hw_value,
19434 &ok)) {
19435 hdd_warn("Unable to get channel:%d eligibility for DNBS",
19436 req->channel->hw_value);
19437 return -EINVAL;
19438 }
19439 /**
19440 * Send connection timedout, so that Android framework does not
19441 * blacklist us.
19442 */
19443 if (!ok) {
19444 struct ieee80211_channel *chan =
Dustin Brown2eb1e452017-08-15 12:40:34 -070019445 ieee80211_get_channel(wiphy,
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053019446 wlan_chan_to_freq(req->channel->hw_value));
19447 struct cfg80211_bss *bss;
19448
19449 hdd_warn("Channel:%d not OK for DNBS",
19450 req->channel->hw_value);
19451 if (chan) {
19452 bss = hdd_cfg80211_get_bss(wiphy,
19453 chan,
19454 req->bssid, req->ssid,
19455 req->ssid_len);
19456 if (bss) {
19457 cfg80211_assoc_timeout(ndev, bss);
19458 return -ETIMEDOUT;
19459 }
19460 }
19461 return -EINVAL;
19462 }
19463
Jeff Johnsonb8944722017-09-03 09:03:19 -070019464 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc,
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080019465 policy_mgr_convert_device_mode_to_qdf_type(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019466 adapter->device_mode),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019467 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019468 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019469 return -ECONNREFUSED;
19470 }
19471 } else {
Jeff Johnsonb8944722017-09-03 09:03:19 -070019472 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc,
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080019473 policy_mgr_convert_device_mode_to_qdf_type(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019474 adapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019475 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019476 return -ECONNREFUSED;
19477 }
19478 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070019479
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019480 /*initialise security parameters */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019481 status = wlan_hdd_cfg80211_set_privacy(adapter, req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019482
19483 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019484 hdd_err("Failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019485 return status;
19486 }
19487
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053019488 if (req->channel)
19489 channel = req->channel->hw_value;
19490 else
19491 channel = 0;
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019492
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019493 wlan_hdd_check_ht20_ht40_ind(hdd_ctx, adapter, req);
Abhishek Singhb59f8d42017-07-31 14:42:47 +053019494
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019495 status = wlan_hdd_cfg80211_connect_start(adapter, req->ssid,
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053019496 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070019497 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019498 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019499 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019500 return status;
19501 }
Dustin Browne74003f2018-03-14 12:51:58 -070019502 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019503 return status;
19504}
19505
19506/**
19507 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
19508 * @wiphy: Pointer to wiphy
19509 * @dev: Pointer to network device
19510 * @req: Pointer to cfg80211 connect request
19511 *
19512 * Return: 0 for success, non-zero for failure
19513 */
19514static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
19515 struct net_device *ndev,
19516 struct cfg80211_connect_params *req)
19517{
19518 int ret;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070019519
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019520 cds_ssr_protect(__func__);
19521 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
19522 cds_ssr_unprotect(__func__);
19523
19524 return ret;
19525}
19526
Himanshu Agarwal6c3607a2018-01-12 12:04:19 +053019527int wlan_hdd_disconnect(struct hdd_adapter *adapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019528{
19529 int status, result = 0;
19530 unsigned long rc;
Jeff Johnsond377dce2017-10-04 10:32:42 -070019531 struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019532 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053019533 eConnectionState prev_conn_state;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019534 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
Abhishek Singhe9706cc2017-10-12 17:25:06 +053019535 uint32_t wait_time = WLAN_WAIT_TIME_DISCONNECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019536
Dustin Brown491d54b2018-03-14 12:39:11 -070019537 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053019538
Jeff Johnsonb8944722017-09-03 09:03:19 -070019539 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019540
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053019541 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019542 return status;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019543 if (adapter->device_mode == QDF_STA_MODE) {
Jeff Johnson1b780e42017-10-31 14:11:45 -070019544 sme_indicate_disconnect_inprogress(hal, adapter->session_id);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019545 hdd_debug("Stop firmware roaming");
Jeff Johnson1b780e42017-10-31 14:11:45 -070019546 status = sme_stop_roaming(hal, adapter->session_id,
Abhishek Singh533c9da2017-05-04 10:23:34 +053019547 eCsrForcedDisassoc);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080019548 /*
Abhishek Singh533c9da2017-05-04 10:23:34 +053019549 * If firmware has already started roaming process, driver
19550 * needs to wait for processing of this disconnect request.
19551 *
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080019552 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019553 INIT_COMPLETION(adapter->roaming_comp_var);
19554 if (hdd_is_roaming_in_progress(adapter)) {
Abhishek Singh533c9da2017-05-04 10:23:34 +053019555 rc = wait_for_completion_timeout(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019556 &adapter->roaming_comp_var,
Abhishek Singh533c9da2017-05-04 10:23:34 +053019557 msecs_to_jiffies(WLAN_WAIT_TIME_STOP_ROAM));
19558 if (!rc) {
19559 hdd_err("roaming comp var timed out session Id: %d",
Jeff Johnson1b780e42017-10-31 14:11:45 -070019560 adapter->session_id);
Abhishek Singh533c9da2017-05-04 10:23:34 +053019561 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019562 if (adapter->roam_ho_fail) {
19563 INIT_COMPLETION(adapter->disconnect_comp_var);
Varun Reddy Yeturu8a5d3d42017-08-02 13:03:27 -070019564 hdd_debug("Disabling queues");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019565 wlan_hdd_netif_queue_control(adapter,
Abhishek Singh533c9da2017-05-04 10:23:34 +053019566 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
19567 WLAN_CONTROL_PATH);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019568 hdd_conn_set_connection_state(adapter,
Abhishek Singh533c9da2017-05-04 10:23:34 +053019569 eConnectionState_Disconnecting);
19570 goto wait_for_disconnect;
19571 }
19572 }
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080019573 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019574
Jeff Johnsond377dce2017-10-04 10:32:42 -070019575 prev_conn_state = sta_ctx->conn_info.connState;
Srinivas Girigowda6598eea2017-07-06 19:26:19 -070019576 /*stop tx queues */
19577 hdd_info("Disabling queues");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019578 wlan_hdd_netif_queue_control(adapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053019579 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019580 hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019581 hdd_conn_set_connection_state(adapter, eConnectionState_Disconnecting);
Varun Reddy Yeturu9e0032c2017-07-12 18:39:59 -070019582
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019583 INIT_COMPLETION(adapter->disconnect_comp_var);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019584
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080019585 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019586
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019587 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -070019588 adapter->session_id, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053019589 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
19590 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019591 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053019592 result = 0;
Abhishek Singhe9706cc2017-10-12 17:25:06 +053019593 /*
19594 * Wait here instead of returning directly. This will block the
19595 * next connect command and allow processing of the disconnect
19596 * in SME else we might hit some race conditions leading to SME
19597 * and HDD out of sync. As disconnect is already in progress,
19598 * wait here for 1 sec instead of 5 sec.
19599 */
19600 wait_time = WLAN_WAIT_DISCONNECT_ALREADY_IN_PROGRESS;
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053019601 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
19602 /*
19603 * Wait here instead of returning directly, this will block the
19604 * next connect command and allow processing of the scan for
19605 * ssid and the previous connect command in CSR. Else we might
19606 * hit some race conditions leading to SME and HDD out of sync.
19607 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019608 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019609 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019610 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Jeff Johnson8380f232017-10-25 12:39:44 -070019611 sta_ctx->sta_debug_state = status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019612 result = -EINVAL;
19613 goto disconnected;
19614 }
Abhishek Singh533c9da2017-05-04 10:23:34 +053019615wait_for_disconnect:
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019616 rc = wait_for_completion_timeout(&adapter->disconnect_comp_var,
Abhishek Singhe9706cc2017-10-12 17:25:06 +053019617 msecs_to_jiffies(wait_time));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019618
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053019619 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019620 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019621 result = -ETIMEDOUT;
19622 }
19623disconnected:
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019624 hdd_conn_set_connection_state(adapter, eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019625#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
19626 /* Sending disconnect event to userspace for kernel version < 3.11
19627 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
19628 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019629 hdd_debug("Send disconnected event to userspace");
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019630 wlan_hdd_cfg80211_indicate_disconnect(adapter->dev, true,
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053019631 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019632#endif
19633
19634 return result;
19635}
19636
19637/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080019638 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
19639 * @reason: ieee80211 reason code.
19640 *
19641 * This utility function helps log string conversion of reason code.
19642 *
19643 * Return: string conversion of reason code, if match found;
19644 * "Unknown" otherwise.
19645 */
19646static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
19647{
19648 switch (reason) {
19649 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
19650 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
19651 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
19652 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
19653 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
19654 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
19655 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
19656 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
19657 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
19658 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
19659 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
19660 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
19661 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
19662 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
19663 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
19664 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
19665 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
19666 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
19667 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
19668 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
19669 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
19670 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
19671 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
19672 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
19673 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
19674 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
19675 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
19676 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
19677 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
19678 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
19679 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
19680 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
19681 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
19682 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
19683 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
19684 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
19685 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
19686 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
19687 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
19688 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
19689 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
19690 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
19691 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
19692 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
19693 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
19694 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
19695 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
19696 default:
19697 return "Unknown";
19698 }
19699}
19700
19701/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019702 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
19703 * @wiphy: Pointer to wiphy
19704 * @dev: Pointer to network device
19705 * @reason: Disconnect reason code
19706 *
19707 * This function is used to issue a disconnect request to SME
19708 *
19709 * Return: 0 for success, non-zero for failure
19710 */
19711static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
19712 struct net_device *dev, u16 reason)
19713{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019714 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019715 int status;
Jeff Johnsond377dce2017-10-04 10:32:42 -070019716 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019717 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
19718 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019719
Dustin Brown491d54b2018-03-14 12:39:11 -070019720 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019721
Anurag Chouhan6d760662016-02-20 16:05:43 +053019722 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019723 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019724 return -EINVAL;
19725 }
19726
Jeff Johnson1b780e42017-10-31 14:11:45 -070019727 if (wlan_hdd_validate_session_id(adapter->session_id)) {
19728 hdd_err("Invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053019729 return -EINVAL;
19730 }
19731
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053019732 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019733 TRACE_CODE_HDD_CFG80211_DISCONNECT,
Jeff Johnson1b780e42017-10-31 14:11:45 -070019734 adapter->session_id, reason));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019735 hdd_debug("Device_mode %s(%d) reason code(%d)",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019736 hdd_device_mode_to_string(adapter->device_mode),
19737 adapter->device_mode, reason);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019738
Jeff Johnsonb8944722017-09-03 09:03:19 -070019739 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019740
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053019741 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019742 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019743
Alok Kumarb64650c2018-03-23 17:05:11 +053019744 qdf_mutex_acquire(&adapter->disconnection_status_lock);
19745 if (adapter->disconnection_in_progress) {
19746 qdf_mutex_release(&adapter->disconnection_status_lock);
19747 hdd_debug("Disconnect is already in progress");
19748 return 0;
19749 }
19750 adapter->disconnection_in_progress = true;
19751 qdf_mutex_release(&adapter->disconnection_status_lock);
19752
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019753 /* Issue disconnect request to SME, if station is in connected state */
Jeff Johnsond377dce2017-10-04 10:32:42 -070019754 if ((sta_ctx->conn_info.connState == eConnectionState_Associated) ||
19755 (sta_ctx->conn_info.connState == eConnectionState_Connecting)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019756 eCsrRoamDisconnectReason reasonCode =
19757 eCSR_DISCONNECT_REASON_UNSPECIFIED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019758
19759 switch (reason) {
19760 case WLAN_REASON_MIC_FAILURE:
19761 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
19762 break;
19763
19764 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
19765 case WLAN_REASON_DISASSOC_AP_BUSY:
19766 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
19767 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
19768 break;
19769
19770 case WLAN_REASON_PREV_AUTH_NOT_VALID:
19771 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
19772 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
19773 break;
19774
19775 case WLAN_REASON_DEAUTH_LEAVING:
19776 reasonCode =
Jeff Johnsonb8944722017-09-03 09:03:19 -070019777 hdd_ctx->config->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019778 gEnableDeauthToDisassocMap ?
19779 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
19780 eCSR_DISCONNECT_REASON_DEAUTH;
Mohit Khannaceb97782017-04-05 16:27:08 -070019781 qdf_dp_trace_dump_all(
19782 WLAN_DEAUTH_DPTRACE_DUMP_COUNT,
19783 QDF_TRACE_DEFAULT_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019784 break;
19785 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
19786 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
19787 break;
19788 default:
19789 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
19790 break;
19791 }
Sandeep Puligilla5f86d992017-10-29 14:58:53 -070019792 if (ucfg_scan_get_vdev_status(adapter->hdd_vdev) !=
19793 SCAN_NOT_IN_PROGRESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019794 hdd_debug("Disconnect is in progress, Aborting Scan");
Jeff Johnsonb8944722017-09-03 09:03:19 -070019795 wlan_abort_scan(hdd_ctx->hdd_pdev, INVAL_PDEV_ID,
Jeff Johnson1b780e42017-10-31 14:11:45 -070019796 adapter->session_id, INVALID_SCAN_ID, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019797 }
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019798 wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019799 /* First clean up the tdls peers if any */
Jeff Johnson1b780e42017-10-31 14:11:45 -070019800 hdd_notify_sta_disconnect(adapter->session_id,
Kabilan Kannanb6153b12017-07-13 17:54:02 -070019801 false, true, adapter->hdd_vdev);
19802
Srinivas Girigowdaf620d482017-04-06 19:03:20 -070019803 hdd_info("Disconnect request from user space with reason: %d (%s) internal reason code: %d",
19804 reason, hdd_ieee80211_reason_code_to_str(reason), reasonCode);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019805 status = wlan_hdd_disconnect(adapter, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019806 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019807 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Alok Kumarb64650c2018-03-23 17:05:11 +053019808 hdd_set_disconnect_status(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019809 return -EINVAL;
19810 }
19811 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019812 hdd_err("Unexpected cfg disconnect called while in state: %d",
Jeff Johnsond377dce2017-10-04 10:32:42 -070019813 sta_ctx->conn_info.connState);
Alok Kumarb64650c2018-03-23 17:05:11 +053019814 hdd_set_disconnect_status(adapter, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019815 }
19816
19817 return status;
19818}
19819
19820/**
19821 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
19822 * @wiphy: Pointer to wiphy
19823 * @dev: Pointer to network device
19824 * @reason: Disconnect reason code
19825 *
19826 * Return: 0 for success, non-zero for failure
19827 */
19828static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
19829 struct net_device *dev, u16 reason)
19830{
19831 int ret;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070019832
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019833 cds_ssr_protect(__func__);
19834 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
19835 cds_ssr_unprotect(__func__);
19836
19837 return ret;
19838}
19839
19840/**
19841 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019842 * @adapter: Pointer to adapter
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019843 * @param: Pointer to IBSS parameters
19844 *
19845 * This function is used to initialize the security settings in IBSS mode
19846 *
19847 * Return: 0 for success, non-zero for failure
19848 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019849static int wlan_hdd_cfg80211_set_privacy_ibss(struct hdd_adapter *adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019850 struct cfg80211_ibss_params
19851 *params)
19852{
Naveen Rawat72475db2017-12-13 18:07:35 -080019853 uint32_t ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019854 int status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019855 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
Jeff Johnsond377dce2017-10-04 10:32:42 -070019856 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019857 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Jeff Johnson20227a92018-03-13 09:41:05 -070019858 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019859
Dustin Brown491d54b2018-03-14 12:39:11 -070019860 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019861
Jeff Johnsonce4a8342017-10-14 13:12:22 -070019862 sta_ctx->wpa_versions = 0;
Jeff Johnsond377dce2017-10-04 10:32:42 -070019863 qdf_mem_zero(&sta_ctx->ibss_enc_key, sizeof(tCsrRoamSetKey));
19864 sta_ctx->ibss_enc_key_installed = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019865
19866 if (params->ie_len && (NULL != params->ie)) {
Naveen Rawat08db88f2017-09-08 15:07:48 -070019867 if (wlan_get_ie_ptr_from_eid(WLAN_EID_RSN, params->ie,
19868 params->ie_len)) {
Jeff Johnsonce4a8342017-10-14 13:12:22 -070019869 sta_ctx->wpa_versions = NL80211_WPA_VERSION_2;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019870 encryptionType = eCSR_ENCRYPT_TYPE_AES;
19871 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
19872 tDot11fIEWPA dot11WPAIE;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019873 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(adapter);
Naveen Rawat08db88f2017-09-08 15:07:48 -070019874 const u8 *ie;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019875
19876 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
Naveen Rawat08db88f2017-09-08 15:07:48 -070019877 ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_WPA,
19878 params->ie, params->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019879 if (NULL != ie) {
Jeff Johnsonce4a8342017-10-14 13:12:22 -070019880 sta_ctx->wpa_versions = NL80211_WPA_VERSION_1;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080019881 /* Unpack the WPA IE
19882 * Skip past the EID byte and length byte
19883 * and four byte WiFi OUI
19884 */
Hanumanth Reddy Pothulaf6e3db32018-01-24 17:54:15 +053019885 if (ie[1] < DOT11F_IE_WPA_MIN_LEN ||
19886 ie[1] > DOT11F_IE_WPA_MAX_LEN) {
19887 hdd_err("invalid ie len:%d", ie[1]);
19888 return -EINVAL;
19889 }
Naveen Rawat72475db2017-12-13 18:07:35 -080019890 ret = dot11f_unpack_ie_wpa(
19891 (tpAniSirGlobal) halHandle,
19892 (uint8_t *)&ie[2 + 4],
19893 ie[1] - 4, &dot11WPAIE, false);
19894 if (DOT11F_FAILED(ret)) {
19895 hdd_err("unpack failed ret: 0x%x", ret);
19896 return -EINVAL;
19897 }
Selvaraj, Sridhar75afbeb2017-04-03 17:08:59 +053019898 /*
19899 * Extract the multicast cipher, the
Jeff Johnsonf3826e12017-01-12 09:49:40 -080019900 * encType for unicast cipher for
19901 * wpa-none is none
19902 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019903 encryptionType =
19904 hdd_translate_wpa_to_csr_encryption_type
19905 (dot11WPAIE.multicast_cipher);
19906 }
19907 }
19908
19909 status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019910 wlan_hdd_cfg80211_set_ie(adapter, params->ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019911 params->ie_len);
19912
19913 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019914 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019915 return status;
19916 }
19917 }
19918
Jeff Johnson20227a92018-03-13 09:41:05 -070019919 roam_profile = hdd_roam_profile(adapter);
19920 roam_profile->AuthType.authType[0] =
Jeff Johnsond377dce2017-10-04 10:32:42 -070019921 sta_ctx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019922
19923 if (params->privacy) {
19924 /* Security enabled IBSS, At this time there is no information
19925 * available about the security paramters, so initialise the
19926 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
19927 * The correct security parameters will be updated later in
19928 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
19929 * set inorder enable privacy bit in beacons
19930 */
19931
19932 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
19933 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019934 hdd_debug("encryptionType=%d", encryptionType);
Jeff Johnsond377dce2017-10-04 10:32:42 -070019935 sta_ctx->conn_info.ucEncryptionType = encryptionType;
Jeff Johnson20227a92018-03-13 09:41:05 -070019936 roam_profile->EncryptionType.numEntries = 1;
19937 roam_profile->EncryptionType.encryptionType[0] =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019938 encryptionType;
19939 return status;
19940}
19941
19942/**
19943 * __wlan_hdd_cfg80211_join_ibss() - join ibss
19944 * @wiphy: Pointer to wiphy
19945 * @dev: Pointer to network device
19946 * @param: Pointer to IBSS join parameters
19947 *
19948 * This function is used to create/join an IBSS network
19949 *
19950 * Return: 0 for success, non-zero for failure
19951 */
19952static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
19953 struct net_device *dev,
19954 struct cfg80211_ibss_params *params)
19955{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019956 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson61b5e982018-03-15 11:33:31 -070019957 struct csr_roam_profile *roam_profile;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019958 int status;
Jeff Johnsond377dce2017-10-04 10:32:42 -070019959 struct hdd_station_ctx *sta_ctx =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019960 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
19961 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053019962 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019963 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019964
Dustin Brown491d54b2018-03-14 12:39:11 -070019965 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019966
Anurag Chouhan6d760662016-02-20 16:05:43 +053019967 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070019968 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019969 return -EINVAL;
19970 }
19971
Jeff Johnson1b780e42017-10-31 14:11:45 -070019972 if (wlan_hdd_validate_session_id(adapter->session_id)) {
19973 hdd_err("Invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053019974 return -EINVAL;
19975 }
19976
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053019977 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019978 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
Jeff Johnson1b780e42017-10-31 14:11:45 -070019979 adapter->session_id, adapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080019980 hdd_debug("Device_mode %s(%d)",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019981 hdd_device_mode_to_string(adapter->device_mode),
19982 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019983
Jeff Johnsonb8944722017-09-03 09:03:19 -070019984 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019985
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053019986 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019987 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019988
19989 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053019990 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019991 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
19992 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
Jeff Johnsonce2ba702017-10-02 13:30:24 -070019993 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019994 int indx;
19995
19996 /* Get channel number */
19997 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080019998 params->
19999 chandef.
20000 chan->
20001 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020002
20003 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
20004 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020005 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020006 return -EOPNOTSUPP;
20007 }
20008
20009 for (indx = 0; indx < numChans; indx++) {
Srinivas Girigowda576b2352017-08-25 14:44:26 -070020010 if (channelNum == validChan[indx])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020011 break;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020012 }
20013 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020014 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020015 return -EINVAL;
20016 }
20017 }
20018
Jeff Johnsonb8944722017-09-03 09:03:19 -070020019 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc,
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080020020 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020021 hdd_err("This concurrency combination is not allowed");
20022 return -ECONNREFUSED;
20023 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020024
Jeff Johnsonb8944722017-09-03 09:03:19 -070020025 status = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070020026 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020027 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070020028
Jeff Johnsonb8944722017-09-03 09:03:19 -070020029 status = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
Jeff Johnson1b780e42017-10-31 14:11:45 -070020030 adapter->session_id, channelNum,
Tushnim Bhattacharyya3b99f4b2018-03-26 14:19:24 -070020031 POLICY_MGR_UPDATE_REASON_JOIN_IBSS);
Krunal Soni3091bcc2016-06-23 12:28:21 -070020032 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020033 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070020034 return -EINVAL;
20035 }
20036
20037 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080020038 status = policy_mgr_wait_for_connection_update(
Jeff Johnsonb8944722017-09-03 09:03:19 -070020039 hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070020040 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020041 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020042 return -EINVAL;
20043 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020044 }
20045
20046 /*Try disconnecting if already in connected state */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020047 status = wlan_hdd_try_disconnect(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020048 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020049 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020050 return -EALREADY;
20051 }
20052
Jeff Johnson20227a92018-03-13 09:41:05 -070020053 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020054
Jeff Johnson5b34fce2017-10-13 13:24:51 -070020055 if (eCSR_BSS_TYPE_START_IBSS != roam_profile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020056 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020057 return -EINVAL;
20058 }
20059
20060 /* enable selected protection checks in IBSS mode */
Jeff Johnson5b34fce2017-10-13 13:24:51 -070020061 roam_profile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020062
Jeff Johnsonb8944722017-09-03 09:03:19 -070020063 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(hdd_ctx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020064 WNI_CFG_IBSS_ATIM_WIN_SIZE,
Jeff Johnsonb8944722017-09-03 09:03:19 -070020065 hdd_ctx->config->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020066 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020067 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020068 }
20069
20070 /* BSSID is provided by upper layers hence no need to AUTO generate */
20071 if (NULL != params->bssid) {
Jeff Johnsonb8944722017-09-03 09:03:19 -070020072 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020073 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020074 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020075 return -EIO;
20076 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053020077 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Jeff Johnsonb8944722017-09-03 09:03:19 -070020078 } else if (hdd_ctx->config->isCoalesingInIBSSAllowed == 0) {
20079 if (sme_cfg_set_int(hdd_ctx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020080 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020081 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020082 return -EIO;
20083 }
Jeff Johnsonb8944722017-09-03 09:03:19 -070020084 qdf_copy_macaddr(&bssid, &hdd_ctx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020085 }
20086 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
20087 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
Jeff Johnson5b34fce2017-10-13 13:24:51 -070020088 roam_profile->beaconInterval = params->beacon_interval;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020089 else {
Jeff Johnson5b34fce2017-10-13 13:24:51 -070020090 roam_profile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020091 hdd_debug("input beacon interval %d TU is invalid, use default %d TU",
Jeff Johnson5b34fce2017-10-13 13:24:51 -070020092 params->beacon_interval, roam_profile->beaconInterval);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020093 }
20094
20095 /* Set Channel */
20096 if (channelNum) {
20097 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020098 hdd_debug("set channel %d", channelNum);
Jeff Johnson5b34fce2017-10-13 13:24:51 -070020099 roam_profile->ChannelInfo.numOfChannels = 1;
Jeff Johnsond377dce2017-10-04 10:32:42 -070020100 sta_ctx->conn_info.operationChannel = channelNum;
Jeff Johnson5b34fce2017-10-13 13:24:51 -070020101 roam_profile->ChannelInfo.ChannelList =
Jeff Johnsond377dce2017-10-04 10:32:42 -070020102 &sta_ctx->conn_info.operationChannel;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020103 }
20104
20105 /* Initialize security parameters */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020106 status = wlan_hdd_cfg80211_set_privacy_ibss(adapter, params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020107 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020108 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020109 return status;
20110 }
20111
20112 /* Issue connect start */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020113 status = wlan_hdd_cfg80211_connect_start(adapter, params->ssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020114 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070020115 bssid.bytes, NULL,
Jeff Johnsond377dce2017-10-04 10:32:42 -070020116 sta_ctx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070020117 operationChannel,
20118 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020119
20120 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020121 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020122 return status;
20123 }
Dustin Browne74003f2018-03-14 12:51:58 -070020124 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020125 return 0;
20126}
20127
20128/**
20129 * wlan_hdd_cfg80211_join_ibss() - join ibss
20130 * @wiphy: Pointer to wiphy
20131 * @dev: Pointer to network device
20132 * @param: Pointer to IBSS join parameters
20133 *
20134 * This function is used to create/join an IBSS network
20135 *
20136 * Return: 0 for success, non-zero for failure
20137 */
20138static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
20139 struct net_device *dev,
20140 struct cfg80211_ibss_params *params)
20141{
20142 int ret = 0;
20143
20144 cds_ssr_protect(__func__);
20145 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
20146 cds_ssr_unprotect(__func__);
20147
20148 return ret;
20149}
20150
20151/**
20152 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
20153 * @wiphy: Pointer to wiphy
20154 * @dev: Pointer to network device
20155 *
20156 * This function is used to leave an IBSS network
20157 *
20158 * Return: 0 for success, non-zero for failure
20159 */
20160static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
20161 struct net_device *dev)
20162{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020163 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson61b5e982018-03-15 11:33:31 -070020164 struct csr_roam_profile *roam_profile;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020165 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020166 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020167 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053020168 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080020169 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020170
Dustin Brown491d54b2018-03-14 12:39:11 -070020171 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020172
Anurag Chouhan6d760662016-02-20 16:05:43 +053020173 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020174 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020175 return -EINVAL;
20176 }
20177
Jeff Johnson1b780e42017-10-31 14:11:45 -070020178 if (wlan_hdd_validate_session_id(adapter->session_id)) {
20179 hdd_err("Invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053020180 return -EINVAL;
20181 }
20182
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053020183 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020184 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
Jeff Johnson1b780e42017-10-31 14:11:45 -070020185 adapter->session_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020186 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
Jeff Johnsonb8944722017-09-03 09:03:19 -070020187 status = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053020188 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020189 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020190
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020191 hdd_debug("Device_mode %s(%d)",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020192 hdd_device_mode_to_string(adapter->device_mode),
20193 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020194
Jeff Johnson20227a92018-03-13 09:41:05 -070020195 roam_profile = hdd_roam_profile(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020196
20197 /* Issue disconnect only if interface type is set to IBSS */
Jeff Johnson5b34fce2017-10-13 13:24:51 -070020198 if (eCSR_BSS_TYPE_START_IBSS != roam_profile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020199 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020200 return -EINVAL;
20201 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080020202 /* Clearing add IE of beacon */
Jeff Johnson1e851a12017-10-28 14:36:12 -070020203 qdf_mem_copy(updateIE.bssid.bytes, adapter->mac_addr.bytes,
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080020204 sizeof(tSirMacAddr));
Jeff Johnson1b780e42017-10-31 14:11:45 -070020205 updateIE.smeSessionId = adapter->session_id;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080020206 updateIE.ieBufferlength = 0;
20207 updateIE.pAdditionIEBuffer = NULL;
20208 updateIE.append = true;
20209 updateIE.notify = true;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020210 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(adapter),
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080020211 &updateIE,
20212 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020213 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080020214 }
20215
20216 /* Reset WNI_CFG_PROBE_RSP Flags */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020217 wlan_hdd_reset_prob_rspies(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020218
20219 /* Issue Disconnect request */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020220 INIT_COMPLETION(adapter->disconnect_comp_var);
20221 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(adapter),
Jeff Johnson1b780e42017-10-31 14:11:45 -070020222 adapter->session_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020223 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020224 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020225 hdd_err("sme_roam_disconnect failed status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020226 hal_status);
20227 return -EAGAIN;
20228 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053020229
20230 /* wait for mc thread to cleanup and then return to upper stack
20231 * so by the time upper layer calls the change interface, we are
20232 * all set to proceed further
20233 */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020234 rc = wait_for_completion_timeout(&adapter->disconnect_comp_var,
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053020235 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
20236 if (!rc) {
20237 hdd_err("Failed to disconnect, timed out");
20238 return -ETIMEDOUT;
20239 }
20240
Dustin Browne74003f2018-03-14 12:51:58 -070020241 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020242 return 0;
20243}
20244
20245/**
20246 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
20247 * @wiphy: Pointer to wiphy
20248 * @dev: Pointer to network device
20249 *
20250 * This function is used to leave an IBSS network
20251 *
20252 * Return: 0 for success, non-zero for failure
20253 */
20254static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
20255 struct net_device *dev)
20256{
20257 int ret = 0;
20258
20259 cds_ssr_protect(__func__);
20260 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
20261 cds_ssr_unprotect(__func__);
20262
20263 return ret;
20264}
20265
20266/**
20267 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
20268 * @wiphy: Pointer to wiphy
20269 * @changed: Parameters changed
20270 *
20271 * This function is used to set the phy parameters. RTS Threshold/FRAG
20272 * Threshold/Retry Count etc.
20273 *
20274 * Return: 0 for success, non-zero for failure
20275 */
20276static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
20277 u32 changed)
20278{
Jeff Johnsonb8944722017-09-03 09:03:19 -070020279 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
20280 tHalHandle hHal = hdd_ctx->hHal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020281 int status;
20282
Dustin Brown491d54b2018-03-14 12:39:11 -070020283 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020284
Anurag Chouhan6d760662016-02-20 16:05:43 +053020285 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020286 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020287 return -EINVAL;
20288 }
20289
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053020290 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020291 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
20292 NO_SESSION, wiphy->rts_threshold));
Jeff Johnsonb8944722017-09-03 09:03:19 -070020293 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020294
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053020295 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020296 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020297
20298 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
20299 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
20300 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
20301
20302 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
20303 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020304 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020305 rts_threshold);
20306 return -EINVAL;
20307 }
20308
20309 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
20310 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020311 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020312 rts_threshold);
20313 return -EIO;
20314 }
20315
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020316 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020317 }
20318
20319 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
20320 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
20321 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
20322 wiphy->frag_threshold;
20323
20324 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
20325 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020326 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020327 frag_threshold);
20328 return -EINVAL;
20329 }
20330
20331 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
20332 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020333 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020334 frag_threshold);
20335 return -EIO;
20336 }
20337
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020338 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020339 }
20340
20341 if ((changed & WIPHY_PARAM_RETRY_SHORT)
20342 || (changed & WIPHY_PARAM_RETRY_LONG)) {
20343 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
20344 wiphy->retry_short : wiphy->retry_long;
20345
20346 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
20347 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020348 hdd_err("Invalid Retry count: %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020349 return -EINVAL;
20350 }
20351
Nachiket Kukade142e9962017-06-16 16:33:28 +053020352 if (changed & WIPHY_PARAM_RETRY_LONG) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020353 if (0 != sme_cfg_set_int(hHal,
20354 WNI_CFG_LONG_RETRY_LIMIT,
20355 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020356 hdd_err("sme_cfg_set_int failed for long retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020357 retry_value);
20358 return -EIO;
20359 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020360 hdd_debug("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020361 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
20362 if (0 != sme_cfg_set_int(hHal,
20363 WNI_CFG_SHORT_RETRY_LIMIT,
20364 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020365 hdd_err("sme_cfg_set_int failed for short retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020366 retry_value);
20367 return -EIO;
20368 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020369 hdd_debug("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020370 }
20371 }
Dustin Browne74003f2018-03-14 12:51:58 -070020372 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020373 return 0;
20374}
20375
20376/**
20377 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
20378 * @wiphy: Pointer to wiphy
20379 * @changed: Parameters changed
20380 *
20381 * Return: 0 for success, non-zero for failure
20382 */
20383static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
20384{
20385 int ret;
20386
20387 cds_ssr_protect(__func__);
20388 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
20389 cds_ssr_unprotect(__func__);
20390
20391 return ret;
20392}
20393
20394/**
20395 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
20396 * key
20397 * @wiphy: Pointer to wiphy
20398 * @dev: Pointer to network device
20399 * @key_index: Key index
20400 *
20401 * Return: 0
20402 */
20403static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
20404 struct net_device *netdev,
20405 u8 key_index)
20406{
Dustin Brown491d54b2018-03-14 12:39:11 -070020407 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020408 return 0;
20409}
20410
20411/**
20412 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
20413 * wlan_hdd_set_default_mgmt_key
20414 * @wiphy: pointer to wiphy
20415 * @netdev: pointer to net_device structure
20416 * @key_index: key index
20417 *
20418 * Return: 0 on success, error number on failure
20419 */
20420static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
20421 struct net_device *netdev,
20422 u8 key_index)
20423{
20424 int ret;
20425
20426 cds_ssr_protect(__func__);
20427 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
20428 cds_ssr_unprotect(__func__);
20429
20430 return ret;
20431}
20432
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020433/**
20434 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
20435 * @wiphy: Pointer to wiphy
20436 * @dev: Pointer to network device
20437 * @params: Pointer to tx queue parameters
20438 *
20439 * Return: 0
20440 */
20441static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
20442 struct net_device *dev,
20443 struct ieee80211_txq_params *params)
20444{
Dustin Brown491d54b2018-03-14 12:39:11 -070020445 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020446 return 0;
20447}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020448
20449/**
20450 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
20451 * @wiphy: pointer to wiphy
20452 * @netdev: pointer to net_device structure
20453 * @params: pointer to ieee80211_txq_params
20454 *
20455 * Return: 0 on success, error number on failure
20456 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020457static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
20458 struct net_device *dev,
20459 struct ieee80211_txq_params *params)
20460{
20461 int ret;
20462
20463 cds_ssr_protect(__func__);
20464 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
20465 cds_ssr_unprotect(__func__);
20466
20467 return ret;
20468}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020469
20470/**
20471 * __wlan_hdd_cfg80211_del_station() - delete station v2
20472 * @wiphy: Pointer to wiphy
20473 * @param: Pointer to delete station parameter
20474 *
20475 * Return: 0 for success, non-zero for failure
20476 */
20477static
20478int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
20479 struct net_device *dev,
Jeff Johnsone6bf7192017-11-07 15:16:09 -080020480 struct csr_del_sta_params *pDelStaParams)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020481{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020482 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070020483 struct hdd_context *hdd_ctx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053020484 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Jeff Johnsonca2530c2017-09-30 18:25:40 -070020485 struct hdd_hostapd_state *hapd_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020486 int status;
20487 uint8_t staId;
20488 uint8_t *mac;
20489
Dustin Brown491d54b2018-03-14 12:39:11 -070020490 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020491
Anurag Chouhan6d760662016-02-20 16:05:43 +053020492 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020493 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020494 return -EINVAL;
20495 }
20496
Jeff Johnson1b780e42017-10-31 14:11:45 -070020497 if (wlan_hdd_validate_session_id(adapter->session_id)) {
20498 hdd_err("Invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053020499 return -EINVAL;
20500 }
20501
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053020502 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020503 TRACE_CODE_HDD_CFG80211_DEL_STA,
Jeff Johnson1b780e42017-10-31 14:11:45 -070020504 adapter->session_id, adapter->device_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020505
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020506 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070020507 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020508
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053020509 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020510 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020511
20512 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
20513
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020514 if ((QDF_SAP_MODE == adapter->device_mode) ||
20515 (QDF_P2P_GO_MODE == adapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020516
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020517 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020518 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020519 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020520 return 0;
20521 }
20522
Anurag Chouhanc5548422016-02-24 18:33:27 +053020523 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020524 uint16_t i;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070020525
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020526 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -070020527 if ((adapter->sta_info[i].in_use) &&
20528 (!adapter->sta_info[i].
Jeff Johnsone4f5d932017-10-21 13:21:15 -070020529 is_deauth_in_progress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053020530 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020531 mac,
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -070020532 adapter->sta_info[i].
Jeff Johnsonf2356512017-10-21 16:04:12 -070020533 sta_mac.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053020534 QDF_MAC_ADDR_SIZE);
Yun Parka4bb37c2017-12-08 16:14:22 -080020535
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020536 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020537 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020538 MAC_ADDR_ARRAY(mac));
20539
Jeff Johnsonb8944722017-09-03 09:03:19 -070020540 if (hdd_ctx->dev_dfs_cac_status ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020541 DFS_CAC_IN_PROGRESS)
20542 goto fn_end;
20543
Wei Song2f76f642016-11-18 16:32:53 +080020544 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020545 hdd_softap_sta_disassoc(adapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053020546 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020547 qdf_status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020548 hdd_softap_sta_deauth(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020549 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020550 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -070020551 adapter->sta_info[i].
Jeff Johnsone4f5d932017-10-21 13:21:15 -070020552 is_deauth_in_progress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053020553 qdf_status =
Nachiket Kukade0396b732017-11-14 16:35:16 +053020554 qdf_wait_for_event_completion(
Naveen Rawatb56880c2016-12-13 17:56:03 -080020555 &hapd_state->
20556 qdf_sta_disassoc_event,
20557 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053020558 if (!QDF_IS_STATUS_SUCCESS(
20559 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020560 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020561 }
20562 }
20563 }
20564 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020565 qdf_status =
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020566 hdd_softap_get_sta_id(adapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053020567 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020568 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020569 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020570 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020571 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020572 MAC_ADDR_ARRAY(mac));
20573 return -ENOENT;
20574 }
20575
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -070020576 if (adapter->sta_info[staId].is_deauth_in_progress ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020577 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020578 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020579 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020580 MAC_ADDR_ARRAY(mac));
20581 return -ENOENT;
20582 }
20583
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -070020584 adapter->sta_info[staId].is_deauth_in_progress = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020585
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020586 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020587 MAC_ADDR_ARRAY(mac));
20588
20589 /* Case: SAP in ACS selected DFS ch and client connected
20590 * Now Radar detected. Then if random channel is another
20591 * DFS ch then new CAC is initiated and no TX allowed.
20592 * So do not send any mgmt frames as it will timeout
20593 * during CAC.
20594 */
20595
Jeff Johnsonb8944722017-09-03 09:03:19 -070020596 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020597 goto fn_end;
20598
Wei Song2f76f642016-11-18 16:32:53 +080020599 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053020600 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
Jeff Johnson1b780e42017-10-31 14:11:45 -070020601 (adapter), adapter->session_id,
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053020602 (uint8_t *)&pDelStaParams->peerMacAddr,
20603 pDelStaParams->reason_code, 0);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020604 qdf_status = hdd_softap_sta_deauth(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020605 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020606 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnsonbb8b56a2017-10-23 07:02:36 -070020607 adapter->sta_info[staId].is_deauth_in_progress =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020608 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020609 hdd_debug("STA removal failed for ::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020610 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020611 MAC_ADDR_ARRAY(mac));
20612 return -ENOENT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020613 }
Nachiket Kukade0396b732017-11-14 16:35:16 +053020614 qdf_status = qdf_wait_for_event_completion(
Srinivas Girigowda576b2352017-08-25 14:44:26 -070020615 &hapd_state->
20616 qdf_sta_disassoc_event,
20617 SME_CMD_TIMEOUT_VALUE);
20618 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
20619 hdd_warn("Deauth wait time expired");
Ashish Kumar Dhanotiya443d31f2017-10-13 12:41:19 +053020620
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020621 }
20622 }
20623
20624fn_end:
Dustin Browne74003f2018-03-14 12:51:58 -070020625 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020626 return 0;
20627}
20628
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080020629#if defined(USE_CFG80211_DEL_STA_V2)
20630/**
20631 * wlan_hdd_del_station() - delete station wrapper
20632 * @adapter: pointer to the hdd adapter
20633 *
20634 * Return: None
20635 */
Jeff Johnsone5006672017-08-29 14:39:02 -070020636void wlan_hdd_del_station(struct hdd_adapter *adapter)
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080020637{
20638 struct station_del_parameters del_sta;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070020639
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080020640 del_sta.mac = NULL;
20641 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
20642 del_sta.reason_code = eCsrForcedDeauthSta;
20643
20644 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
20645 &del_sta);
20646}
20647#else
Jeff Johnsone5006672017-08-29 14:39:02 -070020648void wlan_hdd_del_station(struct hdd_adapter *adapter)
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080020649{
20650 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
20651}
20652#endif
20653
20654#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020655/**
20656 * wlan_hdd_cfg80211_del_station() - delete station v2
20657 * @wiphy: Pointer to wiphy
20658 * @param: Pointer to delete station parameter
20659 *
20660 * Return: 0 for success, non-zero for failure
20661 */
20662int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
20663 struct net_device *dev,
20664 struct station_del_parameters *param)
20665#else
20666/**
20667 * wlan_hdd_cfg80211_del_station() - delete station
20668 * @wiphy: Pointer to wiphy
20669 * @mac: Pointer to station mac address
20670 *
20671 * Return: 0 for success, non-zero for failure
20672 */
20673#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
20674int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
20675 struct net_device *dev,
20676 const uint8_t *mac)
20677#else
20678int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
20679 struct net_device *dev,
20680 uint8_t *mac)
20681#endif
20682#endif
20683{
20684 int ret;
Jeff Johnsone6bf7192017-11-07 15:16:09 -080020685 struct csr_del_sta_params delStaParams;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020686
20687 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080020688#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020689 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080020690 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020691 return -EINVAL;
20692 }
20693 wlansap_populate_del_sta_params(param->mac, param->reason_code,
20694 param->subtype, &delStaParams);
20695#else
20696 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
20697 (SIR_MAC_MGMT_DEAUTH >> 4),
20698 &delStaParams);
20699#endif
20700 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
20701 cds_ssr_unprotect(__func__);
20702
20703 return ret;
20704}
20705
20706/**
20707 * __wlan_hdd_cfg80211_add_station() - add station
20708 * @wiphy: Pointer to wiphy
20709 * @mac: Pointer to station mac address
20710 * @pmksa: Pointer to add station parameter
20711 *
20712 * Return: 0 for success, non-zero for failure
20713 */
20714static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
20715 struct net_device *dev,
20716 const uint8_t *mac,
20717 struct station_parameters *params)
20718{
20719 int status = -EPERM;
20720#ifdef FEATURE_WLAN_TDLS
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020721 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070020722 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020723 u32 mask, set;
20724
Dustin Brown491d54b2018-03-14 12:39:11 -070020725 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020726
Anurag Chouhan6d760662016-02-20 16:05:43 +053020727 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020728 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020729 return -EINVAL;
20730 }
20731
Jeff Johnson1b780e42017-10-31 14:11:45 -070020732 if (wlan_hdd_validate_session_id(adapter->session_id)) {
20733 hdd_err("Invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053020734 return -EINVAL;
20735 }
20736
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053020737 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020738 TRACE_CODE_HDD_CFG80211_ADD_STA,
Jeff Johnson1b780e42017-10-31 14:11:45 -070020739 adapter->session_id, params->listen_interval));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020740
Jeff Johnsonb8944722017-09-03 09:03:19 -070020741 if (0 != wlan_hdd_validate_context(hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020742 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020743
20744 mask = params->sta_flags_mask;
20745
20746 set = params->sta_flags_set;
20747
Srinivas Girigowda13d39252017-03-06 16:12:15 -080020748 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020749 MAC_ADDR_ARRAY(mac));
20750
20751 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud1a28462017-09-06 22:55:48 +080020752 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER))
Jeff Johnsonb8944722017-09-03 09:03:19 -070020753 status = wlan_cfg80211_tdls_add_peer(hdd_ctx->hdd_pdev,
Frank Liud4b2fa02017-03-29 11:46:48 +080020754 dev, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020755 }
20756#endif
Dustin Browne74003f2018-03-14 12:51:58 -070020757 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020758 return status;
20759}
20760
20761/**
20762 * wlan_hdd_cfg80211_add_station() - add station
20763 * @wiphy: Pointer to wiphy
20764 * @mac: Pointer to station mac address
20765 * @pmksa: Pointer to add station parameter
20766 *
20767 * Return: 0 for success, non-zero for failure
20768 */
20769#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
20770static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
20771 struct net_device *dev,
20772 const uint8_t *mac,
20773 struct station_parameters *params)
20774#else
20775static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
20776 struct net_device *dev, uint8_t *mac,
20777 struct station_parameters *params)
20778#endif
20779{
20780 int ret;
20781
20782 cds_ssr_protect(__func__);
20783 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
20784 cds_ssr_unprotect(__func__);
20785
20786 return ret;
20787}
20788
Vignesh Viswanathan3fa1d382017-08-02 19:36:43 +053020789#if defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) || \
20790 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020791/*
20792 * wlan_hdd_is_pmksa_valid: API to validate pmksa
20793 * @pmksa: pointer to cfg80211_pmksa structure
20794 *
20795 * Return: True if valid else false
20796 */
20797static inline bool wlan_hdd_is_pmksa_valid(struct cfg80211_pmksa *pmksa)
20798{
20799 if (!pmksa->bssid) {
Vignesh Viswanathanfa90d622017-12-22 13:13:26 +053020800 hdd_warn("bssid (%pK) is NULL",
20801 pmksa->bssid);
20802 if (!pmksa->ssid || !pmksa->cache_id) {
20803 hdd_err("either ssid (%pK) or cache_id (%pK) are NULL",
20804 pmksa->ssid, pmksa->cache_id);
20805 return false;
20806 }
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020807 }
20808 return true;
20809}
20810
20811/*
20812 * hdd_fill_pmksa_info: API to update tPmkidCacheInfo from cfg80211_pmksa
20813 * @pmk_cache: pmksa from supplicant
20814 * @pmk_cache: pmk needs to be updated
20815 *
20816 * Return: None
20817 */
20818static void hdd_fill_pmksa_info(tPmkidCacheInfo *pmk_cache,
20819 struct cfg80211_pmksa *pmksa, bool is_delete)
20820{
20821 if (pmksa->bssid) {
20822 hdd_debug("%s PMKSA for " MAC_ADDRESS_STR,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053020823 is_delete ? "Delete" : "Set",
20824 MAC_ADDR_ARRAY(pmksa->bssid));
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020825 qdf_mem_copy(pmk_cache->BSSID.bytes,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053020826 pmksa->bssid, QDF_MAC_ADDR_SIZE);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020827 } else {
20828 qdf_mem_copy(pmk_cache->ssid, pmksa->ssid,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053020829 SIR_MAC_MAX_SSID_LENGTH);
20830 qdf_mem_copy(pmk_cache->cache_id, pmksa->cache_id,
20831 CACHE_ID_LEN);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020832 pmk_cache->ssid_len = pmksa->ssid_len;
20833 hdd_debug("%s PMKSA for ssid %*.*s cache_id %x %x",
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053020834 is_delete ? "Delete" : "Set",
20835 pmk_cache->ssid_len, pmk_cache->ssid_len,
20836 pmk_cache->ssid, pmk_cache->cache_id[0],
20837 pmk_cache->cache_id[1]);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020838 }
20839
20840 if (is_delete)
20841 return;
20842
20843 qdf_mem_copy(pmk_cache->PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
20844 if (pmksa->pmk_len && (pmksa->pmk_len <= CSR_RSN_MAX_PMK_LEN)) {
20845 qdf_mem_copy(pmk_cache->pmk, pmksa->pmk, pmksa->pmk_len);
20846 pmk_cache->pmk_len = pmksa->pmk_len;
20847 } else
Sridhar Selvaraj8c6f5e82017-08-21 14:53:46 +053020848 hdd_debug("pmk len is %zu", pmksa->pmk_len);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020849}
20850#else
20851/*
20852 * wlan_hdd_is_pmksa_valid: API to validate pmksa
20853 * @pmksa: pointer to cfg80211_pmksa structure
20854 *
20855 * Return: True if valid else false
20856 */
20857static inline bool wlan_hdd_is_pmksa_valid(struct cfg80211_pmksa *pmksa)
20858{
20859 if (!pmksa->bssid) {
Jeff Johnson36e74c42017-09-18 08:15:42 -070020860 hdd_err("both bssid is NULL %pK", pmksa->bssid);
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020861 return false;
20862 }
20863 return true;
20864}
20865
20866/*
20867 * hdd_fill_pmksa_info: API to update tPmkidCacheInfo from cfg80211_pmksa
20868 * @pmk_cache: pmksa from supplicant
20869 * @pmk_cache: pmk needs to be updated
20870 *
20871 * Return: None
20872 */
20873static void hdd_fill_pmksa_info(tPmkidCacheInfo *pmk_cache,
20874 struct cfg80211_pmksa *pmksa, bool is_delete)
20875{
20876 hdd_debug("%s PMKSA for " MAC_ADDRESS_STR, is_delete ? "Delete" : "Set",
20877 MAC_ADDR_ARRAY(pmksa->bssid));
20878 qdf_mem_copy(pmk_cache->BSSID.bytes,
20879 pmksa->bssid, QDF_MAC_ADDR_SIZE);
20880
20881 if (is_delete)
20882 return;
20883
20884 qdf_mem_copy(pmk_cache->PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
20885}
20886#endif
20887
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020888/**
20889 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
20890 * @wiphy: Pointer to wiphy
20891 * @dev: Pointer to network device
20892 * @pmksa: Pointer to set pmksa parameter
20893 *
20894 * Return: 0 for success, non-zero for failure
20895 */
20896static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
20897 struct net_device *dev,
20898 struct cfg80211_pmksa *pmksa)
20899{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020900 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
20901 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020902 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020903 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020904 int status;
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020905 tPmkidCacheInfo pmk_cache;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020906
Dustin Brown491d54b2018-03-14 12:39:11 -070020907 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053020908
Anurag Chouhan6d760662016-02-20 16:05:43 +053020909 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020910 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020911 return -EINVAL;
20912 }
20913
Jeff Johnson1b780e42017-10-31 14:11:45 -070020914 if (wlan_hdd_validate_session_id(adapter->session_id)) {
20915 hdd_err("Invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053020916 return -EINVAL;
20917 }
20918
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020919 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070020920 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020921 return -EINVAL;
20922 }
20923
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020924 if (!pmksa->pmkid) {
Jeff Johnson36e74c42017-09-18 08:15:42 -070020925 hdd_err("pmksa->pmkid(%pK) is NULL",
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020926 pmksa->pmkid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020927 return -EINVAL;
20928 }
20929
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020930 if (!wlan_hdd_is_pmksa_valid(pmksa))
20931 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020932
Jeff Johnsonb8944722017-09-03 09:03:19 -070020933 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020934
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053020935 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020936 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020937
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020938 halHandle = WLAN_HDD_GET_HAL_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020939
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020940 qdf_mem_zero(&pmk_cache, sizeof(pmk_cache));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020941
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020942 hdd_fill_pmksa_info(&pmk_cache, pmksa, false);
20943
20944 /*
20945 * Add to the PMKSA Cache in CSR
20946 * PMKSA cache will be having following
20947 * 1. pmkid id
20948 * 2. pmk
20949 * 3. bssid or cache identifier
20950 */
Jeff Johnson1b780e42017-10-31 14:11:45 -070020951 result = sme_roam_set_pmkid_cache(halHandle, adapter->session_id,
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053020952 &pmk_cache, 1, false);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020953
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053020954 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020955 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
Jeff Johnson1b780e42017-10-31 14:11:45 -070020956 adapter->session_id, result));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020957
Jeff Johnson1b780e42017-10-31 14:11:45 -070020958 sme_set_del_pmkid_cache(halHandle, adapter->session_id,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053020959 &pmk_cache, true);
20960
Dustin Browne74003f2018-03-14 12:51:58 -070020961 hdd_exit();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053020962 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080020963}
20964
20965/**
20966 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
20967 * @wiphy: Pointer to wiphy
20968 * @dev: Pointer to network device
20969 * @pmksa: Pointer to set pmksa parameter
20970 *
20971 * Return: 0 for success, non-zero for failure
20972 */
20973static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
20974 struct net_device *dev,
20975 struct cfg80211_pmksa *pmksa)
20976{
20977 int ret;
20978
20979 cds_ssr_protect(__func__);
20980 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
20981 cds_ssr_unprotect(__func__);
20982
20983 return ret;
20984}
20985
20986/**
20987 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
20988 * @wiphy: Pointer to wiphy
20989 * @dev: Pointer to network device
20990 * @pmksa: Pointer to pmksa parameter
20991 *
20992 * Return: 0 for success, non-zero for failure
20993 */
20994static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
20995 struct net_device *dev,
20996 struct cfg80211_pmksa *pmksa)
20997{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070020998 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
20999 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021000 tHalHandle halHandle;
21001 int status = 0;
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021002 tPmkidCacheInfo pmk_cache;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021003
Dustin Brown491d54b2018-03-14 12:39:11 -070021004 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021005
Anurag Chouhan6d760662016-02-20 16:05:43 +053021006 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021007 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021008 return -EINVAL;
21009 }
21010
Jeff Johnson1b780e42017-10-31 14:11:45 -070021011 if (wlan_hdd_validate_session_id(adapter->session_id)) {
21012 hdd_err("invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021013 return -EINVAL;
21014 }
21015
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021016 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021017 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021018 return -EINVAL;
21019 }
21020
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021021 if (!wlan_hdd_is_pmksa_valid(pmksa))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021022 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021023
Jeff Johnsonb8944722017-09-03 09:03:19 -070021024 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021025
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021026 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021027 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021028
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021029 halHandle = WLAN_HDD_GET_HAL_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021030
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053021031 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053021032 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
Jeff Johnson1b780e42017-10-31 14:11:45 -070021033 adapter->session_id, 0));
Sridhar Selvarajc3684c72017-08-21 14:32:47 +053021034
21035 qdf_mem_zero(&pmk_cache, sizeof(pmk_cache));
21036
21037 hdd_fill_pmksa_info(&pmk_cache, pmksa, true);
21038
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021039 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053021040 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021041 sme_roam_del_pmkid_from_cache(halHandle,
Jeff Johnson1b780e42017-10-31 14:11:45 -070021042 adapter->session_id, &pmk_cache,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021043 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021044 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021045 MAC_ADDR_ARRAY(pmksa->bssid));
21046 status = -EINVAL;
21047 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021048
Jeff Johnson1b780e42017-10-31 14:11:45 -070021049 sme_set_del_pmkid_cache(halHandle, adapter->session_id, &pmk_cache,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021050 false);
Dustin Browne74003f2018-03-14 12:51:58 -070021051 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021052 return status;
21053}
21054
21055/**
21056 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
21057 * @wiphy: Pointer to wiphy
21058 * @dev: Pointer to network device
21059 * @pmksa: Pointer to pmksa parameter
21060 *
21061 * Return: 0 for success, non-zero for failure
21062 */
21063static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
21064 struct net_device *dev,
21065 struct cfg80211_pmksa *pmksa)
21066{
21067 int ret;
21068
21069 cds_ssr_protect(__func__);
21070 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
21071 cds_ssr_unprotect(__func__);
21072
21073 return ret;
21074
21075}
21076
21077/**
21078 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
21079 * @wiphy: Pointer to wiphy
21080 * @dev: Pointer to network device
21081 *
21082 * Return: 0 for success, non-zero for failure
21083 */
21084static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
21085 struct net_device *dev)
21086{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021087 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
21088 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021089 tHalHandle halHandle;
21090 int status = 0;
21091
Dustin Brown491d54b2018-03-14 12:39:11 -070021092 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021093
Anurag Chouhan6d760662016-02-20 16:05:43 +053021094 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021095 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021096 return -EINVAL;
21097 }
21098
Jeff Johnson1b780e42017-10-31 14:11:45 -070021099 if (wlan_hdd_validate_session_id(adapter->session_id)) {
21100 hdd_err("invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021101 return -EINVAL;
21102 }
21103
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021104 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021105
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021106 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070021107 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021108
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021109 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021110 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021111
21112 /* Retrieve halHandle */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021113 halHandle = WLAN_HDD_GET_HAL_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021114
21115 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053021116 if (QDF_STATUS_SUCCESS !=
Jeff Johnson1b780e42017-10-31 14:11:45 -070021117 sme_roam_del_pmkid_from_cache(halHandle, adapter->session_id, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021118 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021119 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021120 status = -EINVAL;
21121 }
Vignesh Viswanathane8a26b22017-10-11 20:38:47 +053021122
Jeff Johnson1b780e42017-10-31 14:11:45 -070021123 sme_set_del_pmkid_cache(halHandle, adapter->session_id, NULL, false);
Dustin Browne74003f2018-03-14 12:51:58 -070021124 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021125 return status;
21126}
21127
21128/**
21129 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
21130 * @wiphy: Pointer to wiphy
21131 * @dev: Pointer to network device
21132 *
21133 * Return: 0 for success, non-zero for failure
21134 */
21135static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
21136 struct net_device *dev)
21137{
21138 int ret;
21139
21140 cds_ssr_protect(__func__);
21141 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
21142 cds_ssr_unprotect(__func__);
21143
21144 return ret;
21145}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021146
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080021147#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021148/**
21149 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
21150 * @wiphy: Pointer to wiphy
21151 * @dev: Pointer to network device
21152 * @ftie: Pointer to fast transition ie parameter
21153 *
21154 * Return: 0 for success, non-zero for failure
21155 */
21156static int
21157__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
21158 struct net_device *dev,
21159 struct cfg80211_update_ft_ies_params *ftie)
21160{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070021161 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021162 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsond377dce2017-10-04 10:32:42 -070021163 struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021164 int status;
21165
Dustin Brown491d54b2018-03-14 12:39:11 -070021166 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021167
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021168 status = wlan_hdd_validate_context(hdd_ctx);
21169 if (status)
21170 return status;
21171
Anurag Chouhan6d760662016-02-20 16:05:43 +053021172 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021173 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021174 return -EINVAL;
21175 }
21176
Jeff Johnson1b780e42017-10-31 14:11:45 -070021177 if (wlan_hdd_validate_session_id(adapter->session_id)) {
21178 hdd_err("invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021179 return -EINVAL;
21180 }
21181
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053021182 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021183 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
Jeff Johnson1b780e42017-10-31 14:11:45 -070021184 adapter->session_id, sta_ctx->conn_info.connState));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021185 /* Added for debug on reception of Re-assoc Req. */
Jeff Johnsond377dce2017-10-04 10:32:42 -070021186 if (eConnectionState_Associated != sta_ctx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021187 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021188 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021189 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021190 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021191 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021192 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021193
21194 /* Pass the received FT IEs to SME */
Jeff Johnson1b780e42017-10-31 14:11:45 -070021195 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(adapter), adapter->session_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021196 (const u8 *)ftie->ie, ftie->ie_len);
Dustin Browne74003f2018-03-14 12:51:58 -070021197 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021198 return 0;
21199}
21200
21201/**
21202 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
21203 * @wiphy: Pointer to wiphy
21204 * @dev: Pointer to network device
21205 * @ftie: Pointer to fast transition ie parameter
21206 *
21207 * Return: 0 for success, non-zero for failure
21208 */
21209static int
21210wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
21211 struct net_device *dev,
21212 struct cfg80211_update_ft_ies_params *ftie)
21213{
21214 int ret;
21215
21216 cds_ssr_protect(__func__);
21217 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
21218 cds_ssr_unprotect(__func__);
21219
21220 return ret;
21221}
21222#endif
21223
Ashish Kumar Dhanotiyacf11bae2017-04-04 03:29:47 +053021224void wlan_hdd_cfg80211_update_replay_counter_cb(
Mukul Sharma3d36c392017-01-18 18:39:12 +053021225 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
21226
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021227{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021228 struct hdd_adapter *adapter = (struct hdd_adapter *)cb_ctx;
Mukul Sharma3d36c392017-01-18 18:39:12 +053021229 uint8_t temp_replay_counter[8];
21230 int i;
21231 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021232
Dustin Brown491d54b2018-03-14 12:39:11 -070021233 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021234
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021235 if (!adapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021236 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053021237 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021238 }
21239
Mukul Sharma3d36c392017-01-18 18:39:12 +053021240 if (!gtk_rsp_param) {
21241 hdd_err("gtk_rsp_param is Null");
21242 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021243 }
21244
Mukul Sharma3d36c392017-01-18 18:39:12 +053021245 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021246 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053021247 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021248 }
21249
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021250 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053021251 gtk_rsp_param->replay_counter);
21252 /* convert little to big endian since supplicant works on big endian */
21253 p = (uint8_t *)&gtk_rsp_param->replay_counter;
21254 for (i = 0; i < 8; i++)
21255 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021256
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021257 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021258 /* Update replay counter to NL */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021259 cfg80211_gtk_rekey_notify(adapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053021260 gtk_rsp_param->bssid.bytes,
21261 temp_replay_counter, GFP_KERNEL);
21262out:
Dustin Browne74003f2018-03-14 12:51:58 -070021263 hdd_exit();
Mukul Sharma3d36c392017-01-18 18:39:12 +053021264
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021265}
21266
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021267/**
21268 * wlan_hdd_copy_gtk_kek - Copy the KEK from GTK rekey data to GTK request
21269 * @gtk_req: Pointer to GTK request
21270 * @data: Pointer to rekey data
21271 *
21272 * Return: none
21273 */
21274#ifdef CFG80211_REKEY_DATA_KEK_LEN
21275static
21276void wlan_hdd_copy_gtk_kek(struct pmo_gtk_req *gtk_req,
21277 struct cfg80211_gtk_rekey_data *data)
21278{
21279 qdf_mem_copy(gtk_req->kek, data->kek, data->kek_len);
21280 gtk_req->kek_len = data->kek_len;
21281}
21282#else
21283static
21284void wlan_hdd_copy_gtk_kek(struct pmo_gtk_req *gtk_req,
21285 struct cfg80211_gtk_rekey_data *data)
21286{
21287 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
21288 gtk_req->kek_len = NL80211_KEK_LEN;
21289}
21290#endif
21291
21292/**
21293 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
21294 * @wiphy: Pointer to wiphy
21295 * @dev: Pointer to network device
21296 * @data: Pointer to rekey data
21297 *
21298 * This function is used to offload GTK rekeying job to the firmware.
21299 *
21300 * Return: 0 for success, non-zero for failure
21301 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070021302static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021303int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053021304 struct net_device *dev,
21305 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021306{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021307 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053021308 int result, i;
21309 struct pmo_gtk_req *gtk_req = NULL;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021310 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Mukul Sharma3d36c392017-01-18 18:39:12 +053021311 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053021312 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021313
Dustin Brown491d54b2018-03-14 12:39:11 -070021314 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021315
Anurag Chouhan6d760662016-02-20 16:05:43 +053021316 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021317 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053021318 result = -EINVAL;
21319 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021320 }
21321
Jeff Johnson1b780e42017-10-31 14:11:45 -070021322 if (wlan_hdd_validate_session_id(adapter->session_id)) {
21323 hdd_err("invalid session id: %d", adapter->session_id);
Mukul Sharma3d36c392017-01-18 18:39:12 +053021324 result = -EINVAL;
21325 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021326 }
21327
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053021328 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021329 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
Jeff Johnson1b780e42017-10-31 14:11:45 -070021330 adapter->session_id, adapter->device_mode));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021331
Mukul Sharma3d36c392017-01-18 18:39:12 +053021332 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021333 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053021334 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021335
Mukul Sharma3d36c392017-01-18 18:39:12 +053021336 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
21337 if (!gtk_req) {
21338 hdd_err("cannot allocate gtk_req");
21339 result = -ENOMEM;
21340 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021341 }
21342
Mukul Sharma3d36c392017-01-18 18:39:12 +053021343 /* convert big to little endian since driver work on little endian */
21344 buf = (uint8_t *)&gtk_req->replay_counter;
21345 for (i = 0; i < 8; i++)
21346 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021347
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021348 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053021349 gtk_req->replay_counter);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053021350
21351 wlan_hdd_copy_gtk_kek(gtk_req, data);
Mukul Sharma3d36c392017-01-18 18:39:12 +053021352 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021353 status = pmo_ucfg_cache_gtk_offload_req(adapter->hdd_vdev, gtk_req);
Mukul Sharma3d36c392017-01-18 18:39:12 +053021354 if (status != QDF_STATUS_SUCCESS) {
21355 hdd_err("Failed to cache GTK Offload");
21356 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021357 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053021358out:
21359 if (gtk_req)
21360 qdf_mem_free(gtk_req);
Dustin Browne74003f2018-03-14 12:51:58 -070021361 hdd_exit();
Mukul Sharma3d36c392017-01-18 18:39:12 +053021362
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021363 return result;
21364}
21365
21366/**
21367 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
21368 * @wiphy: Pointer to wiphy
21369 * @dev: Pointer to network device
21370 * @data: Pointer to rekey data
21371 *
21372 * This function is used to offload GTK rekeying job to the firmware.
21373 *
21374 * Return: 0 for success, non-zero for failure
21375 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070021376static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021377int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
21378 struct net_device *dev,
21379 struct cfg80211_gtk_rekey_data *data)
21380{
21381 int ret;
21382
21383 cds_ssr_protect(__func__);
21384 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
21385 cds_ssr_unprotect(__func__);
21386
21387 return ret;
21388}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021389
21390/**
21391 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
21392 * @wiphy: Pointer to wiphy
21393 * @dev: Pointer to network device
21394 * @param: Pointer to access control parameter
21395 *
21396 * Return: 0 for success, non-zero for failure
21397 */
21398static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
21399 struct net_device *dev,
21400 const struct cfg80211_acl_data *params)
21401{
21402 int i;
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021403 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson5c19ade2017-10-04 09:52:12 -070021404 struct hdd_hostapd_state *hostapd_state;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021405 tsap_Config_t *pConfig;
Jeff Johnsonb8944722017-09-03 09:03:19 -070021406 struct hdd_context *hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021407 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053021408 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021409
Dustin Brown491d54b2018-03-14 12:39:11 -070021410 hdd_enter();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021411
Anurag Chouhan6d760662016-02-20 16:05:43 +053021412 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021413 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021414 return -EINVAL;
21415 }
21416
21417 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021418 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021419 return -EINVAL;
21420 }
21421
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021422 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070021423 status = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021424
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021425 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021426 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021427
Jeff Johnson5c19ade2017-10-04 09:52:12 -070021428 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021429
Jeff Johnson5c19ade2017-10-04 09:52:12 -070021430 if (NULL == hostapd_state) {
21431 hdd_err("hostapd_state is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021432 return -EINVAL;
21433 }
21434
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021435 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021436 params->n_acl_entries);
21437
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053021438 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053021439 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
Jeff Johnson1b780e42017-10-31 14:11:45 -070021440 adapter->session_id, adapter->device_mode));
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021441 if (QDF_SAP_MODE == adapter->device_mode) {
Jeff Johnsonb9424862017-10-30 08:49:35 -070021442 pConfig = &adapter->session.ap.sap_config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021443
21444 /* default value */
21445 pConfig->num_accept_mac = 0;
21446 pConfig->num_deny_mac = 0;
21447
21448 /**
21449 * access control policy
21450 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
21451 * listed in hostapd.deny file.
21452 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
21453 * listed in hostapd.accept file.
21454 */
21455 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
21456 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
21457 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
21458 params->acl_policy) {
21459 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
21460 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021461 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021462 params->acl_policy);
21463 return -ENOTSUPP;
21464 }
21465
21466 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
21467 pConfig->num_accept_mac = params->n_acl_entries;
21468 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021469 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021470 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021471 MAC_ADDR_ARRAY(
21472 params->mac_addrs[i].addr));
21473
Anurag Chouhan600c3a02016-03-01 10:33:54 +053021474 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021475 params->mac_addrs[i].addr,
21476 sizeof(qcmacaddr));
21477 }
21478 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
21479 pConfig->num_deny_mac = params->n_acl_entries;
21480 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021481 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021482 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021483 MAC_ADDR_ARRAY(
21484 params->mac_addrs[i].addr));
21485
Anurag Chouhan600c3a02016-03-01 10:33:54 +053021486 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021487 params->mac_addrs[i].addr,
21488 sizeof(qcmacaddr));
21489 }
21490 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070021491 qdf_status = wlansap_set_mac_acl(
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021492 WLAN_HDD_GET_SAP_CTX_PTR(adapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053021493 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021494 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021495 return -EINVAL;
21496 }
21497 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021498 hdd_debug("Invalid device_mode %s(%d)",
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021499 hdd_device_mode_to_string(adapter->device_mode),
21500 adapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021501 return -EINVAL;
21502 }
Dustin Browne74003f2018-03-14 12:51:58 -070021503 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021504 return 0;
21505}
21506
21507/**
21508 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
21509 * __wlan_hdd_cfg80211_set_mac_acl
21510 * @wiphy: pointer to wiphy structure
21511 * @dev: pointer to net_device
21512 * @params: pointer to cfg80211_acl_data
21513 *
21514 * Return; 0 on success, error number otherwise
21515 */
21516static int
21517wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
21518 struct net_device *dev,
21519 const struct cfg80211_acl_data *params)
21520{
21521 int ret;
21522
21523 cds_ssr_protect(__func__);
21524 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
21525 cds_ssr_unprotect(__func__);
21526
21527 return ret;
21528}
21529
21530#ifdef WLAN_NL80211_TESTMODE
21531#ifdef FEATURE_WLAN_LPHB
21532/**
21533 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
Jeff Johnsonb8944722017-09-03 09:03:19 -070021534 * @hdd_ctx: Pointer to hdd context
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021535 * @lphbInd: Pointer to low power heart beat indication parameter
21536 *
21537 * Return: none
21538 */
Jeff Johnsonb8944722017-09-03 09:03:19 -070021539static void wlan_hdd_cfg80211_lphb_ind_handler(void *hdd_ctx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053021540 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021541{
21542 struct sk_buff *skb;
21543
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021544 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021545
Jeff Johnsonb8944722017-09-03 09:03:19 -070021546 if (0 != wlan_hdd_validate_context((struct hdd_context *) hdd_ctx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021547 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021548
Mukul Sharmafcd57f52017-03-20 18:18:59 +053021549 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021550 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021551 return;
21552 }
21553
Jeff Johnsonb8944722017-09-03 09:03:19 -070021554 skb = cfg80211_testmode_alloc_event_skb(((struct hdd_context *) hdd_ctx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053021555 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021556 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021557 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021558 return;
21559 }
21560
21561 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021562 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021563 goto nla_put_failure;
21564 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053021565 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021566 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021567 goto nla_put_failure;
21568 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053021569 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
21570 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021571 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021572 goto nla_put_failure;
21573 }
21574 cfg80211_testmode_event(skb, GFP_ATOMIC);
21575 return;
21576
21577nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021578 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021579 kfree_skb(skb);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021580}
21581#endif /* FEATURE_WLAN_LPHB */
21582
21583/**
21584 * __wlan_hdd_cfg80211_testmode() - test mode
21585 * @wiphy: Pointer to wiphy
21586 * @data: Data pointer
21587 * @len: Data length
21588 *
21589 * Return: 0 for success, non-zero for failure
21590 */
21591static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
21592 void *data, int len)
21593{
21594 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
21595 int err;
Jeff Johnsonb8944722017-09-03 09:03:19 -070021596 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021597
Dustin Brown491d54b2018-03-14 12:39:11 -070021598 hdd_enter();
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053021599
Jeff Johnsonb8944722017-09-03 09:03:19 -070021600 err = wlan_hdd_validate_context(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021601 if (err)
21602 return err;
21603
Dustin Brown4ea21db2018-01-05 14:13:17 -080021604 err = wlan_cfg80211_nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
21605 len, wlan_hdd_tm_policy);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021606 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021607 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021608 return err;
21609 }
21610
21611 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021612 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021613 return -EINVAL;
21614 }
21615
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053021616 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053021617 TRACE_CODE_HDD_CFG80211_TESTMODE,
21618 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021619 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
21620#ifdef FEATURE_WLAN_LPHB
21621 /* Low Power Heartbeat configuration request */
21622 case WLAN_HDD_TM_CMD_WLAN_HB:
21623 {
21624 int buf_len;
21625 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053021626 struct pmo_lphb_req *hb_params = NULL;
21627 struct pmo_lphb_req *hb_params_temp = NULL;
21628 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021629
21630 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021631 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021632 return -EINVAL;
21633 }
21634
21635 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
21636 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
21637
Mukul Sharmafcd57f52017-03-20 18:18:59 +053021638 hb_params_temp = (struct pmo_lphb_req *) buf;
21639 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
21640 && (hb_params_temp->params.lphb_tcp_params.
21641 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021642 return -EINVAL;
21643
Manjeet Singh00b2a562017-01-03 12:08:10 +053021644 if (buf_len > sizeof(*hb_params)) {
21645 hdd_err("buf_len=%d exceeded hb_params size limit",
21646 buf_len);
21647 return -ERANGE;
21648 }
21649
Mukul Sharmafcd57f52017-03-20 18:18:59 +053021650 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
21651 sizeof(*hb_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021652 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021653 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021654 return -ENOMEM;
21655 }
21656
Ashish Kumar Dhanotiya0fa8ee02017-07-13 14:04:31 +053021657 qdf_mem_zero(hb_params, sizeof(*hb_params));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053021658 qdf_mem_copy(hb_params, buf, buf_len);
Jeff Johnsonb8944722017-09-03 09:03:19 -070021659 status = pmo_ucfg_lphb_config_req(hdd_ctx->hdd_psoc,
21660 hb_params, (void *)hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021661 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053021662 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021663 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053021664
21665 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021666 return 0;
21667 }
21668#endif /* FEATURE_WLAN_LPHB */
21669
21670#if defined(QCA_WIFI_FTM)
21671 case WLAN_HDD_TM_CMD_WLAN_FTM:
21672 {
Ryan Hsuc8b27a42018-01-02 13:57:56 -080021673 err = wlan_cfg80211_ftm_testmode_cmd(hdd_ctx->hdd_pdev,
21674 data, len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021675 break;
21676 }
21677#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021678 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021679 hdd_err("command: %d not supported",
Ryan Hsuc8b27a42018-01-02 13:57:56 -080021680 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021681 return -EOPNOTSUPP;
21682 }
Ryan Hsuc8b27a42018-01-02 13:57:56 -080021683
Dustin Browne74003f2018-03-14 12:51:58 -070021684 hdd_exit();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021685 return err;
21686}
21687
21688/**
21689 * wlan_hdd_cfg80211_testmode() - test mode
21690 * @wiphy: Pointer to wiphy
21691 * @dev: Pointer to network device
21692 * @data: Data pointer
21693 * @len: Data length
21694 *
21695 * Return: 0 for success, non-zero for failure
21696 */
21697static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
21698#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
21699 struct wireless_dev *wdev,
21700#endif
21701 void *data, int len)
21702{
21703 int ret;
21704
21705 cds_ssr_protect(__func__);
21706 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
21707 cds_ssr_unprotect(__func__);
21708
21709 return ret;
21710}
21711
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021712#endif /* CONFIG_NL80211_TESTMODE */
21713
21714#ifdef QCA_HT_2040_COEX
21715/**
21716 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
21717 * @wiphy: Pointer to wiphy
21718 * @dev: Pointer to network device
21719 * @chandef: Pointer to channel definition parameter
21720 *
21721 * Return: 0 for success, non-zero for failure
21722 */
21723static int
21724__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
21725 struct net_device *dev,
21726 struct cfg80211_chan_def *chandef)
21727{
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021728 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnsonb8944722017-09-03 09:03:19 -070021729 struct hdd_context *hdd_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053021730 QDF_STATUS status;
Sridhar Selvaraj48c47092017-07-31 18:18:14 +053021731 int retval = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021732
Anurag Chouhan6d760662016-02-20 16:05:43 +053021733 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070021734 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021735 return -EINVAL;
21736 }
21737
Jeff Johnson1b780e42017-10-31 14:11:45 -070021738 if (wlan_hdd_validate_session_id(adapter->session_id)) {
21739 hdd_err("invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021740 return -EINVAL;
21741 }
Abhishek Singh9d5f4582017-10-11 17:59:48 +053021742 if (!(adapter->device_mode == QDF_SAP_MODE ||
21743 adapter->device_mode == QDF_P2P_GO_MODE))
21744 return -EOPNOTSUPP;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021745
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021746 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Jeff Johnsonb8944722017-09-03 09:03:19 -070021747 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053021748 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021749 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021750
Abhishek Singh9d5f4582017-10-11 17:59:48 +053021751 hdd_debug("Channel width changed to %d ",
21752 cfg80211_get_chandef_type(chandef));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021753
21754 /* Change SAP ht2040 mode */
Jeff Johnsonce2ba702017-10-02 13:30:24 -070021755 status = hdd_set_sap_ht2040_mode(adapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021756 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053021757 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021758 hdd_err("Cannot set SAP HT20/40 mode!");
Sridhar Selvaraj48c47092017-07-31 18:18:14 +053021759 retval = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021760 }
21761
Sridhar Selvaraj48c47092017-07-31 18:18:14 +053021762 return retval;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021763}
21764
21765/**
21766 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
21767 * @wiphy: Pointer to wiphy
21768 * @dev: Pointer to network device
21769 * @chandef: Pointer to channel definition parameter
21770 *
21771 * Return: 0 for success, non-zero for failure
21772 */
21773static int
21774wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
21775 struct net_device *dev,
21776 struct cfg80211_chan_def *chandef)
21777{
21778 int ret;
21779
21780 cds_ssr_protect(__func__);
21781 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
21782 cds_ssr_unprotect(__func__);
21783
21784 return ret;
21785}
21786#endif
21787
Abhishek Singh1bdb1572015-10-16 16:24:19 +053021788#ifdef CHANNEL_SWITCH_SUPPORTED
21789/**
21790 * __wlan_hdd_cfg80211_channel_switch()- function to switch
21791 * channel in SAP/GO
21792 * @wiphy: wiphy pointer
21793 * @dev: dev pointer.
21794 * @csa_params: Change channel params
21795 *
21796 * This function is called to switch channel in SAP/GO
21797 *
21798 * Return: 0 if success else return non zero
21799 */
21800static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
21801 struct net_device *dev,
21802 struct cfg80211_csa_settings *csa_params)
21803{
Jeff Johnsone5006672017-08-29 14:39:02 -070021804 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070021805 struct hdd_context *hdd_ctx;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053021806 uint8_t channel;
21807 uint16_t freq;
21808 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080021809 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053021810
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021811 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053021812 csa_params->chandef.chan->center_freq);
21813
Jeff Johnson1b780e42017-10-31 14:11:45 -070021814 if (wlan_hdd_validate_session_id(adapter->session_id)) {
21815 hdd_err("invalid session id: %d", adapter->session_id);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053021816 return -EINVAL;
21817 }
21818
Abhishek Singh1bdb1572015-10-16 16:24:19 +053021819 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
21820 ret = wlan_hdd_validate_context(hdd_ctx);
21821
21822 if (0 != ret)
21823 return ret;
21824
Krunal Sonib4326f22016-03-10 13:05:51 -080021825 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
21826 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053021827 return -ENOTSUPP;
21828
21829 freq = csa_params->chandef.chan->center_freq;
21830 channel = cds_freq_to_chan(freq);
21831
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053021832 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
21833
Min Liu2fef5792018-01-19 17:59:42 +080021834 ret = hdd_softap_set_channel_change(dev, channel, ch_width, false);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053021835 return ret;
21836}
21837
21838/**
21839 * wlan_hdd_cfg80211_channel_switch()- function to switch
21840 * channel in SAP/GO
21841 * @wiphy: wiphy pointer
21842 * @dev: dev pointer.
21843 * @csa_params: Change channel params
21844 *
21845 * This function is called to switch channel in SAP/GO
21846 *
21847 * Return: 0 if success else return non zero
21848 */
21849static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
21850 struct net_device *dev,
21851 struct cfg80211_csa_settings *csa_params)
21852{
21853 int ret;
21854
21855 cds_ssr_protect(__func__);
21856 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
21857 cds_ssr_unprotect(__func__);
21858 return ret;
21859}
21860#endif
21861
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021862/**
21863 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
21864 * translation from NL to policy manager type
21865 * @type: Generic connection mode type defined in NL
21866 *
21867 *
21868 * This function provides the type translation
21869 *
21870 * Return: cds_con_mode enum
21871 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080021872enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021873 enum nl80211_iftype type)
21874{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080021875 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Srinivas Girigowda576b2352017-08-25 14:44:26 -070021876
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021877 switch (type) {
21878 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080021879 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021880 break;
21881 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080021882 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021883 break;
21884 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080021885 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021886 break;
21887 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080021888 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021889 break;
21890 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080021891 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021892 break;
21893 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021894 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021895 }
21896 return mode;
21897}
21898
Krunal Sonied3bc8e2018-01-26 12:13:34 -080021899int wlan_hdd_change_hw_mode_for_given_chnl(struct hdd_adapter *adapter,
21900 uint8_t channel,
21901 enum policy_mgr_conn_update_reason reason)
21902{
21903 QDF_STATUS status;
21904 struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
21905
Dustin Brown491d54b2018-03-14 12:39:11 -070021906 hdd_enter();
Krunal Sonied3bc8e2018-01-26 12:13:34 -080021907 if (0 != wlan_hdd_validate_context(hdd_ctx))
21908 return -EINVAL;
21909
21910 status = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
21911 if (!QDF_IS_STATUS_SUCCESS(status))
21912 hdd_err("clearing event failed");
21913
21914 status = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
21915 adapter->session_id, channel, reason);
21916 switch (status) {
21917 case QDF_STATUS_E_FAILURE:
21918 /*
21919 * QDF_STATUS_E_FAILURE indicates that some error has occured
21920 * while changing the hw mode
21921 */
21922 hdd_err("ERROR: connections update failed!!");
21923 return -EINVAL;
21924
21925 case QDF_STATUS_SUCCESS:
21926 /*
21927 * QDF_STATUS_SUCCESS indicates that HW mode change has been
21928 * triggered and wait for it to finish.
21929 */
21930 status = policy_mgr_wait_for_connection_update(
21931 hdd_ctx->hdd_psoc);
21932 if (!QDF_IS_STATUS_SUCCESS(status)) {
21933 hdd_err("ERROR: qdf wait for event failed!!");
21934 return -EINVAL;
21935 }
21936 if (QDF_MONITOR_MODE == adapter->device_mode)
21937 hdd_info("Monitor mode:channel:%d (SMM->DBS)", channel);
21938 break;
21939
21940 default:
21941 /*
21942 * QDF_STATUS_E_NOSUPPORT indicates that no HW mode change is
21943 * required, so caller can proceed further.
21944 */
21945 break;
21946
21947 }
Dustin Browne74003f2018-03-14 12:51:58 -070021948 hdd_exit();
Krunal Sonied3bc8e2018-01-26 12:13:34 -080021949
21950 return 0;
21951}
21952
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080021953/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070021954 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
21955 * @wiphy: Handle to struct wiphy to get handle to module context.
21956 * @chandef: Contains information about the capture channel to be set.
21957 *
21958 * This interface is called if and only if monitor mode interface alone is
21959 * active.
21960 *
21961 * Return: 0 success or error code on failure.
21962 */
21963static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
21964 struct cfg80211_chan_def *chandef)
21965{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070021966 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
Jeff Johnsone5006672017-08-29 14:39:02 -070021967 struct hdd_adapter *adapter;
Jeff Johnson40dae4e2017-08-29 14:00:25 -070021968 struct hdd_station_ctx *sta_ctx;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070021969 struct hdd_mon_set_ch_info *ch_info;
21970 QDF_STATUS status;
21971 tHalHandle hal_hdl;
21972 struct qdf_mac_addr bssid;
Jeff Johnson61b5e982018-03-15 11:33:31 -070021973 struct csr_roam_profile roam_profile;
Amar Singhal5cccafe2017-02-15 12:42:58 -080021974 struct ch_params ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070021975 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070021976 int ret;
21977 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
21978
Dustin Brown491d54b2018-03-14 12:39:11 -070021979 hdd_enter();
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070021980
21981 ret = wlan_hdd_validate_context(hdd_ctx);
21982 if (ret)
21983 return ret;
21984
21985 hal_hdl = hdd_ctx->hHal;
21986
21987 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
21988 if (!adapter)
21989 return -EIO;
21990
Srinivas Girigowda13d39252017-03-06 16:12:15 -080021991 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070021992 adapter->dev->name, chan_num, chandef->chan->center_freq);
21993
21994 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
21995 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070021996 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
21997 roam_profile.ChannelInfo.numOfChannels = 1;
21998 roam_profile.phyMode = ch_info->phy_mode;
Naveen Rawat3184dd82017-07-05 14:58:18 -070021999 roam_profile.ch_params.ch_width = hdd_map_nl_chan_width(chandef->width);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070022000 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022001
Jeff Johnson1e851a12017-10-28 14:36:12 -070022002 qdf_mem_copy(bssid.bytes, adapter->mac_addr.bytes,
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022003 QDF_MAC_ADDR_SIZE);
22004
Naveen Rawat3184dd82017-07-05 14:58:18 -070022005 ch_params.ch_width = hdd_map_nl_chan_width(chandef->width);
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070022006 /*
22007 * CDS api expects secondary channel for calculating
22008 * the channel params
22009 */
22010 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070022011 (WLAN_REG_IS_24GHZ_CH(chan_num))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070022012 if (chan_num >= 1 && chan_num <= 5)
22013 sec_ch = chan_num + 4;
22014 else if (chan_num >= 6 && chan_num <= 13)
22015 sec_ch = chan_num - 4;
22016 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070022017 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan_num,
22018 sec_ch, &ch_params);
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022019 if (wlan_hdd_change_hw_mode_for_given_chnl(adapter, chan_num,
22020 POLICY_MGR_UPDATE_REASON_SET_OPER_CHAN)) {
22021 hdd_err("Failed to change hw mode");
22022 return -EINVAL;
22023 }
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022024 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
22025 &roam_profile);
22026 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080022027 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022028 status);
22029 ret = qdf_status_to_os_return(status);
22030 return ret;
22031 }
Dustin Browne74003f2018-03-14 12:51:58 -070022032 hdd_exit();
Krunal Sonied3bc8e2018-01-26 12:13:34 -080022033
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022034 return 0;
22035}
22036
22037/**
22038 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
22039 * @wiphy: Handle to struct wiphy to get handle to module context.
22040 * @chandef: Contains information about the capture channel to be set.
22041 *
22042 * This interface is called if and only if monitor mode interface alone is
22043 * active.
22044 *
22045 * Return: 0 success or error code on failure.
22046 */
22047static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
22048 struct cfg80211_chan_def *chandef)
22049{
22050 int ret;
22051
22052 cds_ssr_protect(__func__);
22053 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
22054 cds_ssr_unprotect(__func__);
22055 return ret;
22056}
22057
22058/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053022059 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
22060 * @adapter: pointer to adapter
22061 *
22062 * Wrapper function to clear link layer stats.
22063 * return - void
22064 */
Jeff Johnsone5006672017-08-29 14:39:02 -070022065void wlan_hdd_clear_link_layer_stats(struct hdd_adapter *adapter)
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053022066{
22067 tSirLLStatsClearReq link_layer_stats_clear_req;
22068 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
22069
Mukul Sharma491021c2016-09-29 21:39:19 +053022070 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
22071 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053022072 link_layer_stats_clear_req.stopReq = 0;
22073 link_layer_stats_clear_req.reqId = 1;
Jeff Johnson1b780e42017-10-31 14:11:45 -070022074 link_layer_stats_clear_req.staId = adapter->session_id;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053022075 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053022076}
22077
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053022078#define CNT_DIFF(cur, prev) \
22079 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
22080#define MAX_COUNT 0xffffffff
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070022081static void hdd_update_chan_info(struct hdd_context *hdd_ctx,
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053022082 struct scan_chan_info *chan,
22083 struct scan_chan_info *info, uint32_t cmd_flag)
22084{
22085 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
22086 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
22087 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
22088
22089 mutex_lock(&hdd_ctx->chan_info_lock);
22090
22091 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
22092 qdf_mem_zero(chan, sizeof(*chan));
22093
22094 chan->freq = info->freq;
22095 chan->noise_floor = info->noise_floor;
22096 chan->clock_freq = info->clock_freq;
22097 chan->cmd_flag = info->cmd_flag;
22098 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
22099
22100 chan->rx_clear_count =
22101 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
22102
22103 chan->tx_frame_count =
22104 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
22105
22106 mutex_unlock(&hdd_ctx->chan_info_lock);
22107
22108}
22109#undef CNT_DIFF
22110#undef MAX_COUNT
22111
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022112#if defined(WLAN_FEATURE_FILS_SK) &&\
Sridhar Selvaraje5260442017-08-19 10:12:03 +053022113 defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) &&\
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022114 (defined(CFG80211_UPDATE_CONNECT_PARAMS) ||\
22115 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)))
22116
22117#ifndef UPDATE_FILS_ERP_INFO
22118#define UPDATE_FILS_ERP_INFO BIT(1)
22119#endif
22120
22121#ifndef UPDATE_FILS_AUTH_TYPE
22122#define UPDATE_FILS_AUTH_TYPE BIT(2)
22123#endif
22124
22125/**
22126 * __wlan_hdd_cfg80211_update_connect_params - update connect params
22127 * @wiphy: Handle to struct wiphy to get handle to module context.
22128 * @dev: Pointer to network device
22129 * @req: Pointer to connect params
22130 * @changed: Bitmap used to indicate the changed params
22131 *
22132 * Update the connect parameters while connected to a BSS. The updated
22133 * parameters can be used by driver/firmware for subsequent BSS selection
22134 * (roaming) decisions and to form the Authentication/(Re)Association
22135 * Request frames. This call does not request an immediate disassociation
22136 * or reassociation with the current BSS, i.e., this impacts only
22137 * subsequent (re)associations. The bits in changed are defined in enum
22138 * cfg80211_connect_params_changed
22139 *
22140 * Return: zero for success, non-zero for failure
22141 */
22142static int __wlan_hdd_cfg80211_update_connect_params(
22143 struct wiphy *wiphy, struct net_device *dev,
22144 struct cfg80211_connect_params *req, uint32_t changed)
22145{
Jeff Johnson61b5e982018-03-15 11:33:31 -070022146 struct csr_roam_profile *roam_profile;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022147 uint8_t *buf;
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070022148 int ret;
22149 enum eAniAuthType auth_type;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022150 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
22151 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
22152 QDF_STATUS status;
22153 struct cds_fils_connection_info *fils_info;
22154
Dustin Brownfdf17c12018-03-14 12:55:34 -070022155 hdd_enter_dev(dev);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022156
Jeff Johnson1b780e42017-10-31 14:11:45 -070022157 if (wlan_hdd_validate_session_id(adapter->session_id)) {
22158 hdd_err("invalid session id: %d", adapter->session_id);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022159 return -EINVAL;
22160 }
22161
22162 ret = wlan_hdd_validate_context(hdd_ctx);
22163 if (ret)
22164 return -EINVAL;
22165
Jeff Johnson20227a92018-03-13 09:41:05 -070022166 roam_profile = hdd_roam_profile(adapter);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022167 fils_info = roam_profile->fils_con_info;
22168
22169 if (!fils_info) {
22170 hdd_err("No valid FILS conn info");
22171 return -EINVAL;
22172 }
22173
22174 if (req->ie_len)
22175 wlan_hdd_cfg80211_set_ie(adapter, req->ie, req->ie_len);
22176
22177 if (changed)
22178 fils_info->is_fils_connection = true;
22179
22180 if (changed & UPDATE_FILS_ERP_INFO) {
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080022181 if (!wlan_hdd_fils_data_in_limits(req))
Jeff Johnsonb8adae42018-02-27 16:12:00 -080022182 return -EINVAL;
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022183 fils_info->key_nai_length = req->fils_erp_username_len +
22184 sizeof(char) +
22185 req->fils_erp_realm_len;
Dundi Raviteja170d2872018-03-23 15:49:54 +053022186 if (fils_info->key_nai_length >
22187 FILS_MAX_KEYNAME_NAI_LENGTH) {
22188 hdd_err("Key NAI Length %d",
22189 fils_info->key_nai_length);
22190 return -EINVAL;
22191 }
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022192 if (req->fils_erp_username_len && req->fils_erp_username) {
22193 buf = fils_info->keyname_nai;
22194 qdf_mem_copy(buf, req->fils_erp_username,
22195 req->fils_erp_username_len);
22196 buf += req->fils_erp_username_len;
22197 *buf++ = '@';
22198 qdf_mem_copy(buf, req->fils_erp_realm,
22199 req->fils_erp_realm_len);
22200 }
22201
22202 fils_info->sequence_number = req->fils_erp_next_seq_num;
22203 fils_info->r_rk_length = req->fils_erp_rrk_len;
22204
22205 if (req->fils_erp_rrk_len && req->fils_erp_rrk)
22206 qdf_mem_copy(fils_info->r_rk, req->fils_erp_rrk,
22207 fils_info->r_rk_length);
22208
22209 fils_info->realm_len = req->fils_erp_realm_len;
22210 if (req->fils_erp_realm_len && req->fils_erp_realm)
22211 qdf_mem_copy(fils_info->realm, req->fils_erp_realm,
22212 fils_info->realm_len);
22213 }
22214
22215 if (changed & UPDATE_FILS_AUTH_TYPE) {
22216 auth_type = wlan_hdd_get_fils_auth_type(req->auth_type);
Varun Reddy Yeturu5faa1772017-10-23 11:22:01 -070022217 if (auth_type == eSIR_DONOT_USE_AUTH_TYPE) {
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022218 hdd_err("invalid auth type for fils %d",
22219 req->auth_type);
22220 return -EINVAL;
22221 }
22222
22223 roam_profile->fils_con_info->auth_type = auth_type;
22224 }
22225
Varun Reddy Yeturu448cb9d2017-11-20 20:36:31 -080022226 hdd_debug("fils conn update: changed %x is_fils %d keyname nai len %d",
22227 changed, roam_profile->fils_con_info->is_fils_connection,
22228 roam_profile->fils_con_info->key_nai_length);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022229
Abhishek Singh1f217ec2017-12-22 11:48:27 +053022230 if (!hdd_ctx->is_fils_roaming_supported) {
22231 hdd_debug("FILS roaming support %d",
Vignesh Viswanathan731186f2017-09-18 13:47:37 +053022232 hdd_ctx->is_fils_roaming_supported);
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022233 return 0;
22234 }
22235
Jeff Johnson1b780e42017-10-31 14:11:45 -070022236 status = sme_update_fils_config(hdd_ctx->hHal, adapter->session_id,
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022237 roam_profile);
22238 if (QDF_IS_STATUS_ERROR(status))
22239 hdd_err("Update FILS connect params to Fw failed %d", status);
22240
22241 return 0;
22242}
22243
22244/**
22245 * wlan_hdd_cfg80211_update_connect_params - SSR wrapper for
22246 * __wlan_hdd_cfg80211_update_connect_params
22247 * @wiphy: Pointer to wiphy structure
22248 * @dev: Pointer to net_device
22249 * @req: Pointer to connect params
22250 * @changed: flags used to indicate the changed params
22251 *
22252 * Return: zero for success, non-zero for failure
22253 */
22254static int wlan_hdd_cfg80211_update_connect_params(struct wiphy *wiphy,
22255 struct net_device *dev,
22256 struct cfg80211_connect_params *req,
22257 uint32_t changed)
22258{
22259 int ret;
22260
22261 cds_ssr_protect(__func__);
22262 ret = __wlan_hdd_cfg80211_update_connect_params(wiphy, dev,
22263 req, changed);
22264 cds_ssr_unprotect(__func__);
22265
22266 return ret;
22267}
22268#endif
22269
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053022270#if defined(WLAN_FEATURE_SAE) && \
22271 defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
22272/**
22273 * __wlan_hdd_cfg80211_external_auth() - Handle external auth
22274 * @wiphy: Pointer to wireless phy
22275 * @dev: net device
22276 * @params: Pointer to external auth params
22277 *
22278 * Return: 0 on success, negative errno on failure
22279 */
22280static int
22281__wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
22282 struct net_device *dev,
22283 struct cfg80211_external_auth_params *params)
22284{
22285 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
22286 struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
22287 int ret;
22288
22289 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
22290 hdd_err("Command not allowed in FTM mode");
22291 return -EPERM;
22292 }
22293
22294 if (wlan_hdd_validate_session_id(adapter->session_id)) {
22295 hdd_err("invalid session id: %d", adapter->session_id);
22296 return -EINVAL;
22297 }
22298
22299 ret = wlan_hdd_validate_context(hdd_ctx);
22300 if (ret)
22301 return ret;
22302
22303
22304 hdd_debug("external_auth status: %d", params->status);
22305 sme_handle_sae_msg(hdd_ctx->hHal, adapter->session_id, params->status);
22306
22307 return ret;
22308}
22309
22310/**
22311 * wlan_hdd_cfg80211_external_auth() - Handle external auth
22312 * @wiphy: Pointer to wireless phy
22313 * @dev: net device
22314 * @params: Pointer to external auth params
22315 *
22316 * Return: 0 on success, negative errno on failure
22317 */
22318static int
22319wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
22320 struct net_device *dev,
22321 struct cfg80211_external_auth_params *params)
22322{
22323 int ret;
22324
22325 cds_ssr_protect(__func__);
22326 ret = __wlan_hdd_cfg80211_external_auth(wiphy, dev, params);
22327 cds_ssr_unprotect(__func__);
22328
22329 return ret;
22330}
22331#endif
22332
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053022333/**
22334 * wlan_hdd_chan_info_cb() - channel info callback
22335 * @chan_info: struct scan_chan_info
22336 *
22337 * Store channel info into HDD context
22338 *
22339 * Return: None.
22340 */
22341static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
22342{
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070022343 struct hdd_context *hdd_ctx;
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053022344 struct scan_chan_info *chan;
22345 uint8_t idx;
22346
Dustin Brown491d54b2018-03-14 12:39:11 -070022347 hdd_enter();
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053022348
22349 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
22350 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
22351 hdd_err("hdd_ctx is invalid");
22352 return;
22353 }
22354
22355 if (!hdd_ctx->chan_info) {
22356 hdd_err("chan_info is NULL");
22357 return;
22358 }
22359
22360 chan = hdd_ctx->chan_info;
22361 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
22362 if (chan[idx].freq == info->freq) {
22363 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
22364 info->cmd_flag);
22365 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
22366 chan[idx].cmd_flag, chan[idx].freq,
22367 chan[idx].noise_floor,
22368 chan[idx].cycle_count, chan[idx].rx_clear_count,
22369 chan[idx].clock_freq, chan[idx].cmd_flag,
22370 chan[idx].tx_frame_count, idx);
22371 if (chan[idx].freq == 0)
22372 break;
22373
22374 }
22375 }
22376
Dustin Browne74003f2018-03-14 12:51:58 -070022377 hdd_exit();
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053022378}
22379
22380/**
22381 * wlan_hdd_init_chan_info() - init chan info in hdd context
22382 * @hdd_ctx: HDD context pointer
22383 *
22384 * Return: none
22385 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070022386void wlan_hdd_init_chan_info(struct hdd_context *hdd_ctx)
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053022387{
22388 uint8_t num_2g, num_5g, index = 0;
22389
Kapil Gupta63e75282017-05-18 20:55:10 +053022390 hdd_ctx->chan_info = NULL;
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053022391 if (!hdd_ctx->config->fEnableSNRMonitoring) {
22392 hdd_info("SNR monitoring is disabled");
22393 return;
22394 }
22395
22396 hdd_ctx->chan_info =
22397 qdf_mem_malloc(sizeof(struct scan_chan_info)
22398 * QDF_MAX_NUM_CHAN);
22399 if (hdd_ctx->chan_info == NULL) {
22400 hdd_err("Failed to malloc for chan info");
22401 return;
22402 }
22403 mutex_init(&hdd_ctx->chan_info_lock);
22404
22405 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
22406 for (; index < num_2g; index++) {
22407 hdd_ctx->chan_info[index].freq =
22408 hdd_channels_2_4_ghz[index].center_freq;
22409 }
22410
22411 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
22412 for (; (index - num_2g) < num_5g; index++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070022413 if (WLAN_REG_IS_11P_CH(
22414 hdd_channels_5_ghz[index - num_2g].hw_value))
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053022415 continue;
22416 hdd_ctx->chan_info[index].freq =
22417 hdd_channels_5_ghz[index - num_2g].center_freq;
22418 }
22419 sme_set_chan_info_callback(hdd_ctx->hHal,
22420 &wlan_hdd_chan_info_cb);
22421}
22422
22423/**
22424 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
22425 * @hdd_ctx: hdd context pointer
22426 *
22427 * Return: none
22428 */
Jeff Johnson7aeb95b2017-08-28 12:06:33 -070022429void wlan_hdd_deinit_chan_info(struct hdd_context *hdd_ctx)
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053022430{
22431 struct scan_chan_info *chan;
22432
22433 chan = hdd_ctx->chan_info;
22434 hdd_ctx->chan_info = NULL;
22435 if (chan)
22436 qdf_mem_free(chan);
22437}
22438
Dustin Brown32cb4792017-06-15 15:33:42 -070022439#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) || defined(WITH_BACKPORTS)
22440static enum rate_info_bw hdd_map_hdd_bw_to_os(enum hdd_rate_info_bw hdd_bw)
22441{
22442 switch (hdd_bw) {
22443 case HDD_RATE_BW_5:
22444 return RATE_INFO_BW_5;
22445 case HDD_RATE_BW_10:
22446 return RATE_INFO_BW_10;
22447 case HDD_RATE_BW_20:
22448 return RATE_INFO_BW_20;
22449 case HDD_RATE_BW_40:
22450 return RATE_INFO_BW_40;
22451 case HDD_RATE_BW_80:
22452 return RATE_INFO_BW_80;
22453 case HDD_RATE_BW_160:
22454 return RATE_INFO_BW_160;
22455 }
22456
22457 hdd_err("Unhandled HDD_RATE_BW: %d", hdd_bw);
22458
22459 return RATE_INFO_BW_20;
22460}
22461
22462void hdd_set_rate_bw(struct rate_info *info, enum hdd_rate_info_bw hdd_bw)
22463{
22464 info->bw = hdd_map_hdd_bw_to_os(hdd_bw);
22465}
22466#else
22467static enum rate_info_flags hdd_map_hdd_bw_to_os(enum hdd_rate_info_bw hdd_bw)
22468{
22469 switch (hdd_bw) {
22470 case HDD_RATE_BW_5:
22471 case HDD_RATE_BW_10:
22472 case HDD_RATE_BW_20:
22473 return (enum rate_info_flags)0;
22474 case HDD_RATE_BW_40:
22475 return RATE_INFO_FLAGS_40_MHZ_WIDTH;
22476 case HDD_RATE_BW_80:
22477 return RATE_INFO_FLAGS_80_MHZ_WIDTH;
22478 case HDD_RATE_BW_160:
22479 return RATE_INFO_FLAGS_160_MHZ_WIDTH;
22480 }
22481
22482 hdd_err("Unhandled HDD_RATE_BW: %d", hdd_bw);
22483
22484 return (enum rate_info_flags)0;
22485}
22486
22487void hdd_set_rate_bw(struct rate_info *info, enum hdd_rate_info_bw hdd_bw)
22488{
22489 const enum rate_info_flags all_bws =
22490 RATE_INFO_FLAGS_40_MHZ_WIDTH |
22491 RATE_INFO_FLAGS_80_MHZ_WIDTH |
22492 RATE_INFO_FLAGS_80P80_MHZ_WIDTH |
22493 RATE_INFO_FLAGS_160_MHZ_WIDTH;
22494
22495 info->flags &= ~all_bws;
22496 info->flags |= hdd_map_hdd_bw_to_os(hdd_bw);
22497}
22498#endif
22499
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053022500/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022501 * struct cfg80211_ops - cfg80211_ops
22502 *
22503 * @add_virtual_intf: Add virtual interface
22504 * @del_virtual_intf: Delete virtual interface
22505 * @change_virtual_intf: Change virtual interface
22506 * @change_station: Change station
22507 * @add_beacon: Add beacon in sap mode
22508 * @del_beacon: Delete beacon in sap mode
22509 * @set_beacon: Set beacon in sap mode
22510 * @start_ap: Start ap
22511 * @change_beacon: Change beacon
22512 * @stop_ap: Stop ap
22513 * @change_bss: Change bss
22514 * @add_key: Add key
22515 * @get_key: Get key
22516 * @del_key: Delete key
22517 * @set_default_key: Set default key
22518 * @set_channel: Set channel
22519 * @scan: Scan
22520 * @connect: Connect
22521 * @disconnect: Disconnect
22522 * @join_ibss = Join ibss
22523 * @leave_ibss = Leave ibss
22524 * @set_wiphy_params = Set wiphy params
22525 * @set_tx_power = Set tx power
22526 * @get_tx_power = get tx power
22527 * @remain_on_channel = Remain on channel
22528 * @cancel_remain_on_channel = Cancel remain on channel
22529 * @mgmt_tx = Tx management frame
22530 * @mgmt_tx_cancel_wait = Cancel management tx wait
22531 * @set_default_mgmt_key = Set default management key
22532 * @set_txq_params = Set tx queue parameters
22533 * @get_station = Get station
22534 * @set_power_mgmt = Set power management
22535 * @del_station = Delete station
22536 * @add_station = Add station
22537 * @set_pmksa = Set pmksa
22538 * @del_pmksa = Delete pmksa
22539 * @flush_pmksa = Flush pmksa
22540 * @update_ft_ies = Update FT IEs
22541 * @tdls_mgmt = Tdls management
22542 * @tdls_oper = Tdls operation
22543 * @set_rekey_data = Set rekey data
22544 * @sched_scan_start = Scheduled scan start
22545 * @sched_scan_stop = Scheduled scan stop
22546 * @resume = Resume wlan
22547 * @suspend = Suspend wlan
22548 * @set_mac_acl = Set mac acl
22549 * @testmode_cmd = Test mode command
22550 * @set_ap_chanwidth = Set AP channel bandwidth
22551 * @dump_survey = Dump survey
22552 * @key_mgmt_set_pmk = Set pmk key management
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022553 * @update_connect_params = Update connect params
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022554 */
22555static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
22556 .add_virtual_intf = wlan_hdd_add_virtual_intf,
22557 .del_virtual_intf = wlan_hdd_del_virtual_intf,
22558 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
22559 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022560 .start_ap = wlan_hdd_cfg80211_start_ap,
22561 .change_beacon = wlan_hdd_cfg80211_change_beacon,
22562 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022563 .change_bss = wlan_hdd_cfg80211_change_bss,
22564 .add_key = wlan_hdd_cfg80211_add_key,
22565 .get_key = wlan_hdd_cfg80211_get_key,
22566 .del_key = wlan_hdd_cfg80211_del_key,
22567 .set_default_key = wlan_hdd_cfg80211_set_default_key,
22568 .scan = wlan_hdd_cfg80211_scan,
22569 .connect = wlan_hdd_cfg80211_connect,
22570 .disconnect = wlan_hdd_cfg80211_disconnect,
22571 .join_ibss = wlan_hdd_cfg80211_join_ibss,
22572 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
22573 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
22574 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
22575 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
22576 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
22577 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
22578 .mgmt_tx = wlan_hdd_mgmt_tx,
22579 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
22580 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
22581 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053022582 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022583 .get_station = wlan_hdd_cfg80211_get_station,
22584 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
22585 .del_station = wlan_hdd_cfg80211_del_station,
22586 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022587 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
22588 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
22589 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080022590#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022591 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
22592#endif
22593#ifdef FEATURE_WLAN_TDLS
22594 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
22595 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
22596#endif
22597#ifdef WLAN_FEATURE_GTK_OFFLOAD
22598 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
22599#endif /* WLAN_FEATURE_GTK_OFFLOAD */
22600#ifdef FEATURE_WLAN_SCAN_PNO
22601 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
22602 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
22603#endif /*FEATURE_WLAN_SCAN_PNO */
22604 .resume = wlan_hdd_cfg80211_resume_wlan,
22605 .suspend = wlan_hdd_cfg80211_suspend_wlan,
22606 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
22607#ifdef WLAN_NL80211_TESTMODE
22608 .testmode_cmd = wlan_hdd_cfg80211_testmode,
22609#endif
22610#ifdef QCA_HT_2040_COEX
22611 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
22612#endif
22613 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053022614#ifdef CHANNEL_SWITCH_SUPPORTED
22615 .channel_switch = wlan_hdd_cfg80211_channel_switch,
22616#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070022617 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053022618#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
Srinivas Girigowda576b2352017-08-25 14:44:26 -070022619 defined(CFG80211_ABORT_SCAN)
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053022620 .abort_scan = wlan_hdd_cfg80211_abort_scan,
22621#endif
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022622#if defined(WLAN_FEATURE_FILS_SK) &&\
Sridhar Selvaraje5260442017-08-19 10:12:03 +053022623 defined(CFG80211_FILS_SK_OFFLOAD_SUPPORT) &&\
Vignesh Viswanathanc6d1e1c2017-09-18 12:32:49 +053022624 (defined(CFG80211_UPDATE_CONNECT_PARAMS) ||\
22625 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)))
22626 .update_connect_params = wlan_hdd_cfg80211_update_connect_params,
22627#endif
Padma, Santhosh Kumareb90a552018-01-16 19:41:58 +053022628#if defined(WLAN_FEATURE_SAE) && \
22629 defined(CFG80211_EXTERNAL_AUTH_SUPPORT)
22630 .external_auth = wlan_hdd_cfg80211_external_auth,
22631#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080022632};