blob: b04dae2ca02921c66b01ce810e06f88fc96a77d6 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Paul Zhang3a210c52016-12-08 10:18:12 +08002 * Copyright (c) 2012-2017 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>
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053044#include <qdf_trace.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080045#include <wlan_hdd_wowl.h>
46#include <ani_global.h>
47#include "sir_params.h"
48#include "dot11f.h"
49#include "wlan_hdd_assoc.h"
50#include "wlan_hdd_wext.h"
51#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070052#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080053#include "wlan_hdd_p2p.h"
54#include "wlan_hdd_cfg80211.h"
55#include "wlan_hdd_hostapd.h"
56#include "wlan_hdd_softap_tx_rx.h"
57#include "wlan_hdd_main.h"
58#include "wlan_hdd_power.h"
59#include "wlan_hdd_trace.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053060#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053061#include "qdf_trace.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"
72#include <wlan_hdd_ipa.h>
73#include "wlan_logging_sock_svc.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053074#include "sap_api.h"
Agrawal Ashish21ba2572016-09-03 16:40:10 +053075#include "csr_api.h"
Agrawal Ashish467dde42016-09-08 18:44:22 +053076#include "pld_common.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>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080083
84#ifdef FEATURE_WLAN_EXTSCAN
85#include "wlan_hdd_ext_scan.h"
86#endif
87
88#ifdef WLAN_FEATURE_LINK_LAYER_STATS
89#include "wlan_hdd_stats.h"
90#endif
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080091#include "cds_api.h"
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080092#include "wlan_policy_mgr_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080093#include "qwlan_version.h"
94#include "wlan_hdd_memdump.h"
95
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"
Leo Changfdb45c32016-10-28 11:09:23 -0700113
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800114#define g_mode_rates_size (12)
115#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800116#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
117 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
118
119/*
120 * Android CTS verifier needs atleast this much wait time (in msec)
121 */
122#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
123
124/*
125 * Refer @tCfgProtection structure for definition of the bit map.
126 * below value is obtained by setting the following bit-fields.
127 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
128 */
129#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
130
131#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700132 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800133 .center_freq = (freq), \
134 .hw_value = (chan), \
135 .flags = (flag), \
136 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800137 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800138}
139
140#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700141 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800142 .center_freq = (freq), \
143 .hw_value = (chan), \
144 .flags = (flag), \
145 .max_antenna_gain = 0, \
Amar Singhal5cccafe2017-02-15 12:42:58 -0800146 .max_power = 0, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800147}
148
149#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
150 { \
151 .bitrate = rate, \
152 .hw_value = rate_id, \
153 .flags = flag, \
154 }
155
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800156#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
157#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800158
159#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800160
Agrawal Ashish65634612016-08-18 13:24:32 +0530161#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
162 mode <= DFS_MODE_DEPRIORITIZE))
163#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
164 || (channel >= 36 && channel <= 184))
165
Peng Xu4d67c8f2015-10-16 16:02:26 -0700166#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530167#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700168
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800169static const u32 hdd_cipher_suites[] = {
170 WLAN_CIPHER_SUITE_WEP40,
171 WLAN_CIPHER_SUITE_WEP104,
172 WLAN_CIPHER_SUITE_TKIP,
173#ifdef FEATURE_WLAN_ESE
174#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
175#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
176 WLAN_CIPHER_SUITE_BTK,
177 WLAN_CIPHER_SUITE_KRK,
178 WLAN_CIPHER_SUITE_CCMP,
179#else
180 WLAN_CIPHER_SUITE_CCMP,
181#endif
182#ifdef FEATURE_WLAN_WAPI
183 WLAN_CIPHER_SUITE_SMS4,
184#endif
185#ifdef WLAN_FEATURE_11W
186 WLAN_CIPHER_SUITE_AES_CMAC,
187#endif
188};
189
Abhishek Singhf512bf32016-05-04 16:47:46 +0530190static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800191 HDD2GHZCHAN(2412, 1, 0),
192 HDD2GHZCHAN(2417, 2, 0),
193 HDD2GHZCHAN(2422, 3, 0),
194 HDD2GHZCHAN(2427, 4, 0),
195 HDD2GHZCHAN(2432, 5, 0),
196 HDD2GHZCHAN(2437, 6, 0),
197 HDD2GHZCHAN(2442, 7, 0),
198 HDD2GHZCHAN(2447, 8, 0),
199 HDD2GHZCHAN(2452, 9, 0),
200 HDD2GHZCHAN(2457, 10, 0),
201 HDD2GHZCHAN(2462, 11, 0),
202 HDD2GHZCHAN(2467, 12, 0),
203 HDD2GHZCHAN(2472, 13, 0),
204 HDD2GHZCHAN(2484, 14, 0),
205};
206
Abhishek Singhf512bf32016-05-04 16:47:46 +0530207static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800208 HDD5GHZCHAN(5180, 36, 0),
209 HDD5GHZCHAN(5200, 40, 0),
210 HDD5GHZCHAN(5220, 44, 0),
211 HDD5GHZCHAN(5240, 48, 0),
212 HDD5GHZCHAN(5260, 52, 0),
213 HDD5GHZCHAN(5280, 56, 0),
214 HDD5GHZCHAN(5300, 60, 0),
215 HDD5GHZCHAN(5320, 64, 0),
216 HDD5GHZCHAN(5500, 100, 0),
217 HDD5GHZCHAN(5520, 104, 0),
218 HDD5GHZCHAN(5540, 108, 0),
219 HDD5GHZCHAN(5560, 112, 0),
220 HDD5GHZCHAN(5580, 116, 0),
221 HDD5GHZCHAN(5600, 120, 0),
222 HDD5GHZCHAN(5620, 124, 0),
223 HDD5GHZCHAN(5640, 128, 0),
224 HDD5GHZCHAN(5660, 132, 0),
225 HDD5GHZCHAN(5680, 136, 0),
226 HDD5GHZCHAN(5700, 140, 0),
227 HDD5GHZCHAN(5720, 144, 0),
228 HDD5GHZCHAN(5745, 149, 0),
229 HDD5GHZCHAN(5765, 153, 0),
230 HDD5GHZCHAN(5785, 157, 0),
231 HDD5GHZCHAN(5805, 161, 0),
232 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800233 HDD5GHZCHAN(5852, 170, 0),
234 HDD5GHZCHAN(5855, 171, 0),
235 HDD5GHZCHAN(5860, 172, 0),
236 HDD5GHZCHAN(5865, 173, 0),
237 HDD5GHZCHAN(5870, 174, 0),
238 HDD5GHZCHAN(5875, 175, 0),
239 HDD5GHZCHAN(5880, 176, 0),
240 HDD5GHZCHAN(5885, 177, 0),
241 HDD5GHZCHAN(5890, 178, 0),
242 HDD5GHZCHAN(5895, 179, 0),
243 HDD5GHZCHAN(5900, 180, 0),
244 HDD5GHZCHAN(5905, 181, 0),
245 HDD5GHZCHAN(5910, 182, 0),
246 HDD5GHZCHAN(5915, 183, 0),
247 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800248};
249
250static struct ieee80211_rate g_mode_rates[] = {
251 HDD_G_MODE_RATETAB(10, 0x1, 0),
252 HDD_G_MODE_RATETAB(20, 0x2, 0),
253 HDD_G_MODE_RATETAB(55, 0x4, 0),
254 HDD_G_MODE_RATETAB(110, 0x8, 0),
255 HDD_G_MODE_RATETAB(60, 0x10, 0),
256 HDD_G_MODE_RATETAB(90, 0x20, 0),
257 HDD_G_MODE_RATETAB(120, 0x40, 0),
258 HDD_G_MODE_RATETAB(180, 0x80, 0),
259 HDD_G_MODE_RATETAB(240, 0x100, 0),
260 HDD_G_MODE_RATETAB(360, 0x200, 0),
261 HDD_G_MODE_RATETAB(480, 0x400, 0),
262 HDD_G_MODE_RATETAB(540, 0x800, 0),
263};
264
265static struct ieee80211_rate a_mode_rates[] = {
266 HDD_G_MODE_RATETAB(60, 0x10, 0),
267 HDD_G_MODE_RATETAB(90, 0x20, 0),
268 HDD_G_MODE_RATETAB(120, 0x40, 0),
269 HDD_G_MODE_RATETAB(180, 0x80, 0),
270 HDD_G_MODE_RATETAB(240, 0x100, 0),
271 HDD_G_MODE_RATETAB(360, 0x200, 0),
272 HDD_G_MODE_RATETAB(480, 0x400, 0),
273 HDD_G_MODE_RATETAB(540, 0x800, 0),
274};
275
276static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530277 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800278 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700279 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800280 .bitrates = g_mode_rates,
281 .n_bitrates = g_mode_rates_size,
282 .ht_cap.ht_supported = 1,
283 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
284 | IEEE80211_HT_CAP_GRN_FLD
285 | IEEE80211_HT_CAP_DSSSCCK40
286 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
287 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
288 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
289 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
290 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
291 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
292 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
293};
294
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800295static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530296 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800297 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700298 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800299 .bitrates = a_mode_rates,
300 .n_bitrates = a_mode_rates_size,
301 .ht_cap.ht_supported = 1,
302 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
303 | IEEE80211_HT_CAP_GRN_FLD
304 | IEEE80211_HT_CAP_DSSSCCK40
305 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
306 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
307 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
308 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
309 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
310 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
311 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
312 .vht_cap.vht_supported = 1,
313};
314
315/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800316 * TX/RX direction for each kind of interface
317 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800318static const struct ieee80211_txrx_stypes
319 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
320 [NL80211_IFTYPE_STATION] = {
321 .tx = 0xffff,
322 .rx = BIT(SIR_MAC_MGMT_ACTION) |
323 BIT(SIR_MAC_MGMT_PROBE_REQ),
324 },
325 [NL80211_IFTYPE_AP] = {
326 .tx = 0xffff,
327 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
328 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
329 BIT(SIR_MAC_MGMT_PROBE_REQ) |
330 BIT(SIR_MAC_MGMT_DISASSOC) |
331 BIT(SIR_MAC_MGMT_AUTH) |
332 BIT(SIR_MAC_MGMT_DEAUTH) |
333 BIT(SIR_MAC_MGMT_ACTION),
334 },
335 [NL80211_IFTYPE_ADHOC] = {
336 .tx = 0xffff,
337 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
338 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
339 BIT(SIR_MAC_MGMT_PROBE_REQ) |
340 BIT(SIR_MAC_MGMT_DISASSOC) |
341 BIT(SIR_MAC_MGMT_AUTH) |
342 BIT(SIR_MAC_MGMT_DEAUTH) |
343 BIT(SIR_MAC_MGMT_ACTION),
344 },
345 [NL80211_IFTYPE_P2P_CLIENT] = {
346 .tx = 0xffff,
347 .rx = BIT(SIR_MAC_MGMT_ACTION) |
348 BIT(SIR_MAC_MGMT_PROBE_REQ),
349 },
350 [NL80211_IFTYPE_P2P_GO] = {
351 /* This is also same as for SoftAP */
352 .tx = 0xffff,
353 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
354 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
355 BIT(SIR_MAC_MGMT_PROBE_REQ) |
356 BIT(SIR_MAC_MGMT_DISASSOC) |
357 BIT(SIR_MAC_MGMT_AUTH) |
358 BIT(SIR_MAC_MGMT_DEAUTH) |
359 BIT(SIR_MAC_MGMT_ACTION),
360 },
361};
362
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800363/* Interface limits and combinations registered by the driver */
364
365/* STA ( + STA ) combination */
366static const struct ieee80211_iface_limit
367 wlan_hdd_sta_iface_limit[] = {
368 {
369 .max = 3, /* p2p0 is a STA as well */
370 .types = BIT(NL80211_IFTYPE_STATION),
371 },
372};
373
374/* ADHOC (IBSS) limit */
375static const struct ieee80211_iface_limit
376 wlan_hdd_adhoc_iface_limit[] = {
377 {
378 .max = 1,
379 .types = BIT(NL80211_IFTYPE_STATION),
380 },
381 {
382 .max = 1,
383 .types = BIT(NL80211_IFTYPE_ADHOC),
384 },
385};
386
387/* AP ( + AP ) combination */
388static const struct ieee80211_iface_limit
389 wlan_hdd_ap_iface_limit[] = {
390 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530391 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800392 .types = BIT(NL80211_IFTYPE_AP),
393 },
394};
395
396/* P2P limit */
397static const struct ieee80211_iface_limit
398 wlan_hdd_p2p_iface_limit[] = {
399 {
400 .max = 1,
401 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
402 },
403 {
404 .max = 1,
405 .types = BIT(NL80211_IFTYPE_P2P_GO),
406 },
407};
408
409static const struct ieee80211_iface_limit
410 wlan_hdd_sta_ap_iface_limit[] = {
411 {
412 /* We need 1 extra STA interface for OBSS scan when SAP starts
413 * with HT40 in STA+SAP concurrency mode
414 */
415 .max = (1 + SAP_MAX_OBSS_STA_CNT),
416 .types = BIT(NL80211_IFTYPE_STATION),
417 },
418 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530419 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800420 .types = BIT(NL80211_IFTYPE_AP),
421 },
422};
423
424/* STA + P2P combination */
425static const struct ieee80211_iface_limit
426 wlan_hdd_sta_p2p_iface_limit[] = {
427 {
428 /* One reserved for dedicated P2PDEV usage */
429 .max = 2,
430 .types = BIT(NL80211_IFTYPE_STATION)
431 },
432 {
433 /* Support for two identical (GO + GO or CLI + CLI)
434 * or dissimilar (GO + CLI) P2P interfaces
435 */
436 .max = 2,
437 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
438 },
439};
440
441/* STA + AP + P2PGO combination */
442static const struct ieee80211_iface_limit
443wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
444 /* Support for AP+P2PGO interfaces */
445 {
446 .max = 2,
447 .types = BIT(NL80211_IFTYPE_STATION)
448 },
449 {
450 .max = 1,
451 .types = BIT(NL80211_IFTYPE_P2P_GO)
452 },
453 {
454 .max = 1,
455 .types = BIT(NL80211_IFTYPE_AP)
456 }
457};
458
459/* SAP + P2P combination */
460static const struct ieee80211_iface_limit
461wlan_hdd_sap_p2p_iface_limit[] = {
462 {
463 /* 1 dedicated for p2p0 which is a STA type */
464 .max = 1,
465 .types = BIT(NL80211_IFTYPE_STATION)
466 },
467 {
468 /* The p2p interface in SAP+P2P can be GO/CLI.
469 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
470 */
471 .max = 1,
472 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
473 },
474 {
475 /* SAP+GO to support only one SAP interface */
476 .max = 1,
477 .types = BIT(NL80211_IFTYPE_AP)
478 }
479};
480
481/* P2P + P2P combination */
482static const struct ieee80211_iface_limit
483wlan_hdd_p2p_p2p_iface_limit[] = {
484 {
485 /* 1 dedicated for p2p0 which is a STA type */
486 .max = 1,
487 .types = BIT(NL80211_IFTYPE_STATION)
488 },
489 {
490 /* The p2p interface in P2P+P2P can be GO/CLI.
491 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
492 */
493 .max = 2,
494 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
495 },
496};
497
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700498static const struct ieee80211_iface_limit
499 wlan_hdd_mon_iface_limit[] = {
500 {
501 .max = 3, /* Monitor interface */
502 .types = BIT(NL80211_IFTYPE_MONITOR),
503 },
504};
505
506static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800507 wlan_hdd_iface_combination[] = {
508 /* STA */
509 {
510 .limits = wlan_hdd_sta_iface_limit,
511 .num_different_channels = 2,
512 .max_interfaces = 3,
513 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
514 },
515 /* ADHOC */
516 {
517 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700518 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800519 .max_interfaces = 2,
520 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
521 },
522 /* AP */
523 {
524 .limits = wlan_hdd_ap_iface_limit,
525 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530526 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800527 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
528 },
529 /* P2P */
530 {
531 .limits = wlan_hdd_p2p_iface_limit,
532 .num_different_channels = 2,
533 .max_interfaces = 2,
534 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
535 },
536 /* STA + AP */
537 {
538 .limits = wlan_hdd_sta_ap_iface_limit,
539 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530540 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800541 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
542 .beacon_int_infra_match = true,
543 },
544 /* STA + P2P */
545 {
546 .limits = wlan_hdd_sta_p2p_iface_limit,
547 .num_different_channels = 2,
548 /* one interface reserved for P2PDEV dedicated usage */
549 .max_interfaces = 4,
550 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
551 .beacon_int_infra_match = true,
552 },
553 /* STA + P2P GO + SAP */
554 {
555 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
556 /* we can allow 3 channels for three different persona
557 * but due to firmware limitation, allow max 2 concrnt channels.
558 */
559 .num_different_channels = 2,
560 /* one interface reserved for P2PDEV dedicated usage */
561 .max_interfaces = 4,
562 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
563 .beacon_int_infra_match = true,
564 },
565 /* SAP + P2P */
566 {
567 .limits = wlan_hdd_sap_p2p_iface_limit,
568 .num_different_channels = 2,
569 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
570 .max_interfaces = 3,
571 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
572 .beacon_int_infra_match = true,
573 },
574 /* P2P + P2P */
575 {
576 .limits = wlan_hdd_p2p_p2p_iface_limit,
577 .num_different_channels = 2,
578 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
579 .max_interfaces = 3,
580 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
581 .beacon_int_infra_match = true,
582 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530583 /* Monitor */
584 {
585 .limits = wlan_hdd_mon_iface_limit,
586 .max_interfaces = 3,
587 .num_different_channels = 2,
588 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
589 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800590};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800591
592static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800593
594#ifdef WLAN_NL80211_TESTMODE
595enum wlan_hdd_tm_attr {
596 WLAN_HDD_TM_ATTR_INVALID = 0,
597 WLAN_HDD_TM_ATTR_CMD = 1,
598 WLAN_HDD_TM_ATTR_DATA = 2,
599 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
600 WLAN_HDD_TM_ATTR_TYPE = 4,
601 /* keep last */
602 WLAN_HDD_TM_ATTR_AFTER_LAST,
603 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
604};
605
606enum wlan_hdd_tm_cmd {
607 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
608 WLAN_HDD_TM_CMD_WLAN_HB = 1,
609};
610
611#define WLAN_HDD_TM_DATA_MAX_LEN 5000
612
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530613enum wlan_hdd_vendor_ie_access_policy {
614 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
615 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
616};
617
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800618static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
619 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
620 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
621 .len = WLAN_HDD_TM_DATA_MAX_LEN},
622};
623#endif /* WLAN_NL80211_TESTMODE */
624
625#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
626static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
627 .flags = WIPHY_WOWLAN_MAGIC_PKT,
628 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
629 .pattern_min_len = 1,
630 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
631};
632#endif
633
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800634/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530635 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
636 * @flags: Pointer to the flags to Add channel switch flag.
637 *
638 * This Function adds Channel Switch support flag, if channel switch is
639 * supported by kernel.
640 * Return: void.
641 */
642#ifdef CHANNEL_SWITCH_SUPPORTED
643static inline void hdd_add_channel_switch_support(uint32_t *flags)
644{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800645 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530646 return;
647}
648#else
649static inline void hdd_add_channel_switch_support(uint32_t *flags)
650{
651 return;
652}
653#endif
654
Manikandan Mohan22b83722015-12-15 15:03:23 -0800655#ifdef FEATURE_WLAN_TDLS
656
657/* TDLS capabilities params */
658#define PARAM_MAX_TDLS_SESSION \
659 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
660#define PARAM_TDLS_FEATURE_SUPPORT \
661 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
662
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530663/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800664 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
665 * @wiphy: WIPHY structure pointer
666 * @wdev: Wireless device structure pointer
667 * @data: Pointer to the data received
668 * @data_len: Length of the data received
669 *
670 * This function provides TDLS capabilities
671 *
672 * Return: 0 on success and errno on failure
673 */
674static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
675 struct wireless_dev *wdev,
676 const void *data,
677 int data_len)
678{
679 int status;
680 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
681 struct sk_buff *skb;
682 uint32_t set = 0;
683
Jeff Johnson1f61b612016-02-12 16:28:33 -0800684 ENTER_DEV(wdev->netdev);
685
Anurag Chouhan6d760662016-02-20 16:05:43 +0530686 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800687 hdd_err("Command not allowed in FTM mode");
688 return -EPERM;
689 }
690
691 status = wlan_hdd_validate_context(hdd_ctx);
692 if (status)
693 return status;
694
695 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
696 NLMSG_HDRLEN);
697 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700698 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800699 goto fail;
700 }
701
702 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800703 hdd_debug("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800704 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
705 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700706 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800707 goto fail;
708 }
709 } else {
710 set = set | WIFI_TDLS_SUPPORT;
711 set = set | (hdd_ctx->config->fTDLSExternalControl ?
712 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
713 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
714 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800715 hdd_debug("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800716 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
717 hdd_ctx->max_num_tdls_sta) ||
718 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
719 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700720 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800721 goto fail;
722 }
723 }
724 return cfg80211_vendor_cmd_reply(skb);
725fail:
726 if (skb)
727 kfree_skb(skb);
728 return -EINVAL;
729}
730
731/**
732 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
733 * @wiphy: WIPHY structure pointer
734 * @wdev: Wireless device structure pointer
735 * @data: Pointer to the data received
736 * @data_len: Length of the data received
737 *
738 * This function provides TDLS capabilities
739 *
740 * Return: 0 on success and errno on failure
741 */
742static int
743wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
744 struct wireless_dev *wdev,
745 const void *data,
746 int data_len)
747{
748 int ret;
749
750 cds_ssr_protect(__func__);
751 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
752 data, data_len);
753 cds_ssr_unprotect(__func__);
754
755 return ret;
756}
757#endif
758
759#ifdef QCA_HT_2040_COEX
760static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
761#endif
762
763#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
764/*
765 * FUNCTION: wlan_hdd_send_avoid_freq_event
766 * This is called when wlan driver needs to send vendor specific
767 * avoid frequency range event to userspace
768 */
769int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
770 tHddAvoidFreqList *pAvoidFreqList)
771{
772 struct sk_buff *vendor_event;
773
774 ENTER();
775
776 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700777 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800778 return -EINVAL;
779 }
780
781 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700782 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800783 return -EINVAL;
784 }
785
786 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
787 NULL,
788 sizeof(tHddAvoidFreqList),
789 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
790 GFP_KERNEL);
791 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700792 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800793 return -EINVAL;
794 }
795
796 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
797 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
798
799 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
800
801 EXIT();
802 return 0;
803}
804#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
805
806/* vendor specific events */
807static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
808#ifdef FEATURE_WLAN_CH_AVOID
809 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
810 .vendor_id =
811 QCA_NL80211_VENDOR_ID,
812 .subcmd =
813 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
814 },
815#endif /* FEATURE_WLAN_CH_AVOID */
816
817#ifdef WLAN_FEATURE_NAN
818 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
819 .vendor_id =
820 QCA_NL80211_VENDOR_ID,
821 .subcmd =
822 QCA_NL80211_VENDOR_SUBCMD_NAN
823 },
824#endif
825
826#ifdef WLAN_FEATURE_STATS_EXT
827 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
828 .vendor_id =
829 QCA_NL80211_VENDOR_ID,
830 .subcmd =
831 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
832 },
833#endif /* WLAN_FEATURE_STATS_EXT */
834#ifdef FEATURE_WLAN_EXTSCAN
835 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
836 .vendor_id =
837 QCA_NL80211_VENDOR_ID,
838 .subcmd =
839 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
840 },
841 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
842 .vendor_id =
843 QCA_NL80211_VENDOR_ID,
844 .subcmd =
845 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
846 },
847 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
848 .
849 vendor_id
850 =
851 QCA_NL80211_VENDOR_ID,
852 .subcmd =
853 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
854 },
855 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
856 .
857 vendor_id
858 =
859 QCA_NL80211_VENDOR_ID,
860 .
861 subcmd =
862 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
863 },
864 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
865 .
866 vendor_id
867 =
868 QCA_NL80211_VENDOR_ID,
869 .
870 subcmd
871 =
872 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
873 },
874 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
875 .
876 vendor_id
877 =
878 QCA_NL80211_VENDOR_ID,
879 .subcmd =
880 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
881 },
882 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
883 .vendor_id =
884 QCA_NL80211_VENDOR_ID,
885 .subcmd =
886 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
887 },
888 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
889 .
890 vendor_id
891 =
892 QCA_NL80211_VENDOR_ID,
893 .subcmd =
894 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
895 },
896 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
897 .
898 vendor_id
899 =
900 QCA_NL80211_VENDOR_ID,
901 .subcmd =
902 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
903 },
904 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
905 .
906 vendor_id
907 =
908 QCA_NL80211_VENDOR_ID,
909 .
910 subcmd
911 =
912 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
913 },
914 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
915 .
916 vendor_id
917 =
918 QCA_NL80211_VENDOR_ID,
919 .
920 subcmd =
921 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
922 },
923 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
924 .
925 vendor_id
926 =
927 QCA_NL80211_VENDOR_ID,
928 .
929 subcmd
930 =
931 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
932 },
933 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
934 .
935 vendor_id
936 =
937 QCA_NL80211_VENDOR_ID,
938 .
939 subcmd
940 =
941 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
942 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800943#endif /* FEATURE_WLAN_EXTSCAN */
944
945#ifdef WLAN_FEATURE_LINK_LAYER_STATS
946 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
947 .vendor_id =
948 QCA_NL80211_VENDOR_ID,
949 .subcmd =
950 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
951 },
952 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
953 .vendor_id =
954 QCA_NL80211_VENDOR_ID,
955 .subcmd =
956 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
957 },
958 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
959 .vendor_id =
960 QCA_NL80211_VENDOR_ID,
961 .subcmd =
962 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
963 },
964 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
965 .vendor_id =
966 QCA_NL80211_VENDOR_ID,
967 .subcmd =
968 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
969 },
970 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
971 .vendor_id =
972 QCA_NL80211_VENDOR_ID,
973 .subcmd =
974 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
975 },
976 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
977 .vendor_id =
978 QCA_NL80211_VENDOR_ID,
979 .subcmd =
980 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
981 },
Zhang Qianca38fb12016-12-23 11:10:48 +0800982 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT_INDEX] = {
983 .vendor_id =
984 QCA_NL80211_VENDOR_ID,
985 .subcmd =
986 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT
987 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800988#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
989 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
990 .vendor_id =
991 QCA_NL80211_VENDOR_ID,
992 .subcmd =
993 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
994 },
995 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
996 .vendor_id = QCA_NL80211_VENDOR_ID,
997 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
998 },
999#ifdef WLAN_FEATURE_ROAM_OFFLOAD
1000 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
1001 .vendor_id =
1002 QCA_NL80211_VENDOR_ID,
1003 .subcmd =
1004 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1005 },
1006#endif
1007 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1008 .vendor_id =
1009 QCA_NL80211_VENDOR_ID,
1010 .subcmd =
1011 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1012 },
1013 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1014 .vendor_id =
1015 QCA_NL80211_VENDOR_ID,
1016 .subcmd =
1017 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1018 },
1019 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1020 .vendor_id =
1021 QCA_NL80211_VENDOR_ID,
1022 .subcmd =
1023 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1024 },
1025 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1026 .vendor_id =
1027 QCA_NL80211_VENDOR_ID,
1028 .subcmd =
1029 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1030 },
1031 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1032 .vendor_id =
1033 QCA_NL80211_VENDOR_ID,
1034 .subcmd =
1035 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1036 },
1037#ifdef FEATURE_WLAN_EXTSCAN
1038 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1039 .vendor_id = QCA_NL80211_VENDOR_ID,
1040 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1041 },
1042 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1043 .vendor_id = QCA_NL80211_VENDOR_ID,
1044 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1045 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001046 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1047 .vendor_id = QCA_NL80211_VENDOR_ID,
1048 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1049 },
1050#endif /* FEATURE_WLAN_EXTSCAN */
1051 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1052 .vendor_id = QCA_NL80211_VENDOR_ID,
1053 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1054 },
1055#ifdef WLAN_FEATURE_MEMDUMP
1056 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1057 .vendor_id = QCA_NL80211_VENDOR_ID,
1058 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1059 },
1060#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001061#ifdef WLAN_FEATURE_TSF
1062 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1063 .vendor_id = QCA_NL80211_VENDOR_ID,
1064 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1065 },
1066#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001067 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1068 .vendor_id = QCA_NL80211_VENDOR_ID,
1069 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1070 },
1071 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1072 .vendor_id = QCA_NL80211_VENDOR_ID,
1073 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1074 },
1075 /* OCB events */
1076 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1077 .vendor_id = QCA_NL80211_VENDOR_ID,
1078 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1079 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001080#ifdef FEATURE_LFR_SUBNET_DETECTION
1081 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1082 .vendor_id = QCA_NL80211_VENDOR_ID,
1083 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1084 },
1085#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001086
1087#ifdef WLAN_FEATURE_NAN_DATAPATH
1088 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1089 .vendor_id = QCA_NL80211_VENDOR_ID,
1090 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1091 },
1092#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001093
1094 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1095 .vendor_id = QCA_NL80211_VENDOR_ID,
1096 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1097 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301098 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1099 .vendor_id = QCA_NL80211_VENDOR_ID,
1100 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1101 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301102 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1103 .vendor_id = QCA_NL80211_VENDOR_ID,
1104 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1105 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001106#ifdef WLAN_UMAC_CONVERGENCE
1107 COMMON_VENDOR_EVENTS
1108#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001109};
1110
1111/**
1112 * __is_driver_dfs_capable() - get driver DFS capability
1113 * @wiphy: pointer to wireless wiphy structure.
1114 * @wdev: pointer to wireless_dev structure.
1115 * @data: Pointer to the data to be passed via vendor interface
1116 * @data_len:Length of the data to be passed
1117 *
1118 * This function is called by userspace to indicate whether or not
1119 * the driver supports DFS offload.
1120 *
1121 * Return: 0 on success, negative errno on failure
1122 */
1123static int __is_driver_dfs_capable(struct wiphy *wiphy,
1124 struct wireless_dev *wdev,
1125 const void *data,
1126 int data_len)
1127{
1128 u32 dfs_capability = 0;
1129 struct sk_buff *temp_skbuff;
1130 int ret_val;
1131 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1132
Jeff Johnson1f61b612016-02-12 16:28:33 -08001133 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001134
1135 ret_val = wlan_hdd_validate_context(hdd_ctx);
1136 if (ret_val)
1137 return ret_val;
1138
Anurag Chouhan6d760662016-02-20 16:05:43 +05301139 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001140 hdd_err("Command not allowed in FTM mode");
1141 return -EPERM;
1142 }
1143
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001144 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001145
1146 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1147 NLMSG_HDRLEN);
1148
1149 if (temp_skbuff != NULL) {
1150 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1151 dfs_capability);
1152 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001153 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001154 kfree_skb(temp_skbuff);
1155
1156 return ret_val;
1157 }
1158
1159 return cfg80211_vendor_cmd_reply(temp_skbuff);
1160 }
1161
Jeff Johnson020db452016-06-29 14:37:26 -07001162 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001163 return -ENOMEM;
1164}
1165
1166/**
1167 * is_driver_dfs_capable() - get driver DFS capability
1168 * @wiphy: pointer to wireless wiphy structure.
1169 * @wdev: pointer to wireless_dev structure.
1170 * @data: Pointer to the data to be passed via vendor interface
1171 * @data_len:Length of the data to be passed
1172 *
1173 * This function is called by userspace to indicate whether or not
1174 * the driver supports DFS offload. This is an SSR-protected
1175 * wrapper function.
1176 *
1177 * Return: 0 on success, negative errno on failure
1178 */
1179static int is_driver_dfs_capable(struct wiphy *wiphy,
1180 struct wireless_dev *wdev,
1181 const void *data,
1182 int data_len)
1183{
1184 int ret;
1185
1186 cds_ssr_protect(__func__);
1187 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1188 cds_ssr_unprotect(__func__);
1189
1190 return ret;
1191}
1192
1193/**
1194 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1195 *
1196 * @adapter: SAP adapter pointer
1197 *
1198 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1199 * radio. So in case of DFS MCC scenario override current SAP given config
1200 * to follow concurrent SAP DFS config
1201 *
1202 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1203 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001204int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1205{
1206 hdd_adapter_t *con_sap_adapter;
1207 tsap_Config_t *sap_config, *con_sap_config;
1208 int con_ch;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001209 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001210
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001211 if (!hdd_ctx) {
1212 hdd_err("hdd context is NULL");
1213 return 0;
1214 }
1215
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001216 /*
1217 * Check if AP+AP case, once primary AP chooses a DFS
1218 * channel secondary AP should always follow primary APs channel
1219 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001220 if (!policy_mgr_concurrent_beaconing_sessions_running(
1221 hdd_ctx->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001222 return 0;
1223
1224 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1225 if (!con_sap_adapter)
1226 return 0;
1227
1228 sap_config = &adapter->sessionCtx.ap.sapConfig;
1229 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1230 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1231
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001232 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, con_ch))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001233 return 0;
1234
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001235 hdd_debug("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001236 sap_config->channel, con_ch);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001237 hdd_debug("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001238 sap_config->channel = con_ch;
1239
1240 if (con_sap_config->acs_cfg.acs_mode == true) {
1241 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1242 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001243 hdd_err("Primary AP channel config error");
1244 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001245 con_ch, con_sap_config->acs_cfg.pri_ch,
1246 con_sap_config->acs_cfg.ht_sec_ch);
1247 return -EINVAL;
1248 }
1249 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1250 * MCC restriction. So free ch list allocated in do_acs
1251 * func for Sec AP and realloc for Pri AP ch list size
1252 */
1253 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301254 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001255
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301256 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001257 &con_sap_config->acs_cfg,
1258 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301259 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001260 sizeof(uint8_t) *
1261 con_sap_config->acs_cfg.ch_list_count);
1262 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001263 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001264 return -ENOMEM;
1265 }
1266
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301267 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001268 con_sap_config->acs_cfg.ch_list,
1269 con_sap_config->acs_cfg.ch_list_count);
1270
1271 } else {
1272 sap_config->acs_cfg.pri_ch = con_ch;
1273 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1274 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1275 }
1276
1277 return con_ch;
1278}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001279
1280/**
1281 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1282 * @sap_cfg: pointer to SAP config struct
1283 *
1284 * This function sets the default ACS start and end channel for the given band
1285 * and also parses the given ACS channel list.
1286 *
1287 * Return: None
1288 */
1289
1290static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1291 bool vht_enabled)
1292{
1293 int i;
1294 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1295 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001296 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1297 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001298 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1299 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001300 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1301 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001302 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1303 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001304 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_36);
1305 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001306 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1307 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001308 sap_cfg->acs_cfg.start_ch = WLAN_REG_CH_NUM(CHAN_ENUM_1);
1309 sap_cfg->acs_cfg.end_ch = WLAN_REG_CH_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001310 }
1311
1312 if (ht_enabled)
1313 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1314
1315 if (vht_enabled)
1316 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1317
1318
1319 /* Parse ACS Chan list from hostapd */
1320 if (!sap_cfg->acs_cfg.ch_list)
1321 return;
1322
1323 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1324 sap_cfg->acs_cfg.end_ch =
1325 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1326 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301327 /* avoid channel as start channel */
1328 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1329 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001330 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1331 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1332 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1333 }
1334}
1335
1336
1337static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1338
1339/**
1340 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1341 * @adapter: pointer to SAP adapter struct
1342 *
1343 * This function starts the ACS procedure if there are no
1344 * constraints like MBSSID DFS restrictions.
1345 *
1346 * Return: Status of ACS Start procedure
1347 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301348int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001349{
1350
1351 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1352 tsap_Config_t *sap_config;
1353 tpWLAN_SAPEventCB acs_event_callback;
1354 int status;
1355
1356 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301357 if (hdd_ctx->acs_policy.acs_channel)
1358 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1359 else
1360 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001361
1362 status = wlan_hdd_sap_cfg_dfs_override(adapter);
Jeff Johnson68755312017-02-10 11:46:55 -08001363 if (status < 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001364 return status;
Jeff Johnson68755312017-02-10 11:46:55 -08001365
1366 if (status > 0) {
1367 /*notify hostapd about channel override */
1368 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1369 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1370 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001371 }
Jeff Johnson68755312017-02-10 11:46:55 -08001372
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001373 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1374 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001375 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001376 return -EINVAL;
1377 }
1378
1379 acs_event_callback = hdd_hostapd_sap_event_cb;
1380
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301381 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301382 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Kapil Gupta8878ad92017-02-13 11:56:04 +05301383 hdd_notice("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001384 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001385 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001386 acs_event_callback, sap_config, adapter->dev);
1387
1388
1389 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001390 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001391 return -EINVAL;
1392 }
bings394afdd2017-01-09 11:22:38 +08001393 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1394 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001395 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1396
1397 return 0;
1398}
1399
1400/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05301401 * wlan_hdd_sap_get_nol() - Get SAPs NOL
1402 * @ap_adapter: AP adapter
1403 * @nol: Non-occupancy list
1404 * @nol_len: Length of NOL
1405 *
1406 * Get the NOL for SAP
1407 *
1408 * Return: Zero on success, non-zero on failure
1409 */
1410static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
1411 uint32_t *nol_len)
1412{
1413 QDF_STATUS ret;
1414
1415 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
1416 nol, nol_len);
1417 if (QDF_IS_STATUS_ERROR(ret))
1418 return -EINVAL;
1419
1420 return 0;
1421}
1422
1423/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301424 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1425 * @hdd_ctx: hdd context
1426 * @acs_chan_params: external acs channel params
1427 * @sap_config: SAP config
1428 *
1429 * This API provides unsorted pcl list.
1430 * this list is a subset of the valid channel list given by hostapd.
1431 * if channel is not present in pcl, weightage will be given as zero
1432 *
1433 * Return: Zero on success, non-zero on failure
1434 */
1435static void hdd_update_vendor_pcl_list(hdd_context_t *hdd_ctx,
1436 struct hdd_vendor_acs_chan_params *acs_chan_params,
1437 tsap_Config_t *sap_config)
1438{
1439 int i, j;
1440
1441 for (i = 0; i < acs_chan_params->channel_count; i++) {
1442 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1443 if (acs_chan_params->channel_list[i] ==
1444 sap_config->acs_cfg.pcl_channels[j]) {
1445 acs_chan_params->vendor_pcl_list[i] =
1446 sap_config->acs_cfg.pcl_channels[j];
1447 acs_chan_params->vendor_weight_list[i] =
1448 sap_config->acs_cfg.
1449 pcl_channels_weight_list[j];
1450 break;
1451 } else {
1452 acs_chan_params->vendor_pcl_list[i] =
1453 acs_chan_params->channel_list[i];
1454 acs_chan_params->vendor_weight_list[i] = 0;
1455 }
1456 }
1457 }
1458 if (hdd_ctx->unsafe_channel_count == 0)
1459 return;
1460 /* Update unsafe channel weight as zero */
1461 for (i = 0; i < acs_chan_params->channel_count; i++) {
1462 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
1463 if (acs_chan_params->channel_list[i] ==
1464 hdd_ctx->unsafe_channel_list[j]) {
1465 acs_chan_params->vendor_weight_list[i] = 0;
1466 }
1467 }
1468 }
1469}
1470
1471/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301472 * hdd_update_reg_chan_info : This API contructs channel info
1473 * for all the given channel
1474 * @adapter: pointer to SAP adapter struct
1475 * @channel_count: channel count
1476 * @channel_list: channel list
1477 *
1478 * Return: Status of of channel information updation
1479 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301480static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301481 uint32_t channel_count,
1482 uint8_t *channel_list)
1483{
1484 int i;
1485 struct hdd_channel_info *icv;
Amar Singhal5cccafe2017-02-15 12:42:58 -08001486 struct ch_params ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301487 uint8_t bw_offset = 0, chan = 0;
1488 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1489 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1490
1491 /* memory allocation */
1492 sap_config->channel_info = qdf_mem_malloc(
1493 sizeof(struct hdd_channel_info) *
1494 channel_count);
1495 if (!sap_config->channel_info) {
1496 hdd_err("memory allocation failed");
1497 return -ENOMEM;
1498
1499 }
1500 for (i = 0; i < channel_count; i++) {
1501 icv = &sap_config->channel_info[i];
1502 chan = channel_list[i];
1503
1504 if (chan == 0)
1505 continue;
1506
1507 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1508 bw_offset = 1 << BW_40_OFFSET_BIT;
1509 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1510 bw_offset = 1 << BW_20_OFFSET_BIT;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001511 icv->freq = wlan_reg_get_channel_freq(hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301512 icv->ieee_chan_number = chan;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001513 icv->max_reg_power = wlan_reg_get_channel_reg_power(
1514 hdd_ctx->hdd_pdev, chan);
Kapil Gupta086c6202016-12-11 18:17:06 +05301515
1516 /* filling demo values */
1517 icv->max_radio_power = HDD_MAX_TX_POWER;
1518 icv->min_radio_power = HDD_MIN_TX_POWER;
1519 /* not supported in current driver */
1520 icv->max_antenna_gain = 0;
1521
1522 icv->reg_class_id = wlan_hdd_find_opclass(
1523 WLAN_HDD_GET_HAL_CTX(adapter),
1524 chan, bw_offset);
1525
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001526 if (WLAN_REG_IS_5GHZ_CH(chan)) {
Kapil Gupta086c6202016-12-11 18:17:06 +05301527 ch_params.ch_width = sap_config->acs_cfg.ch_width;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001528 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan,
1529 0, &ch_params);
Kapil Gupta086c6202016-12-11 18:17:06 +05301530 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1531 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1532 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001533
Kapil Gupta086c6202016-12-11 18:17:06 +05301534 icv->flags = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07001535 icv->flags = cds_get_vendor_reg_flags(hdd_ctx->hdd_pdev, chan,
Kapil Gupta086c6202016-12-11 18:17:06 +05301536 sap_config->acs_cfg.ch_width,
1537 sap_config->acs_cfg.is_ht_enabled,
1538 sap_config->acs_cfg.is_vht_enabled,
1539 hdd_ctx->config->enable_sub_20_channel_width);
1540
1541 hdd_info("freq %d flags %d flagext %d ieee %d maxreg %d maxpw %d minpw %d regClass %d antenna %d seg0 %d seg1 %d",
1542 icv->freq, icv->flags,
1543 icv->flagext, icv->ieee_chan_number,
1544 icv->max_reg_power, icv->max_radio_power,
1545 icv->min_radio_power, icv->reg_class_id,
1546 icv->max_antenna_gain, icv->vht_center_freq_seg0,
1547 icv->vht_center_freq_seg1);
1548 }
1549 return 0;
1550}
1551
1552/* Short name for QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO event */
1553#define CHAN_INFO_ATTR_FLAGS \
1554 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS
1555#define CHAN_INFO_ATTR_FLAG_EXT \
1556 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT
1557#define CHAN_INFO_ATTR_FREQ \
1558 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ
1559#define CHAN_INFO_ATTR_MAX_REG_POWER \
1560 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER
1561#define CHAN_INFO_ATTR_MAX_POWER \
1562 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER
1563#define CHAN_INFO_ATTR_MIN_POWER \
1564 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER
1565#define CHAN_INFO_ATTR_REG_CLASS_ID \
1566 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID
1567#define CHAN_INFO_ATTR_ANTENNA_GAIN \
1568 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN
1569#define CHAN_INFO_ATTR_VHT_SEG_0 \
1570 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0
1571#define CHAN_INFO_ATTR_VHT_SEG_1 \
1572 QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1
1573
1574/**
1575 * hdd_cfg80211_update_channel_info() - add channel info attributes
1576 * @skb: pointer to sk buff
1577 * @hdd_ctx: pointer to hdd station context
1578 * @idx: attribute index
1579 *
1580 * Return: Success(0) or reason code for failure
1581 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301582static int32_t
Kapil Gupta086c6202016-12-11 18:17:06 +05301583hdd_cfg80211_update_channel_info(struct sk_buff *skb,
1584 tsap_Config_t *sap_config, int idx)
1585{
1586 struct nlattr *nla_attr, *channel;
1587 struct hdd_channel_info *icv;
1588 int i;
1589
1590 nla_attr = nla_nest_start(skb, idx);
1591 if (!nla_attr)
1592 goto fail;
1593
1594 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++) {
1595 channel = nla_nest_start(skb, i);
1596 if (!channel)
1597 goto fail;
1598
1599 icv = &sap_config->channel_info[i];
1600 if (!icv) {
1601 hdd_err("channel info not found");
1602 goto fail;
1603 }
1604 if (nla_put_u16(skb, CHAN_INFO_ATTR_FREQ,
1605 icv->freq) ||
1606 nla_put_u32(skb, CHAN_INFO_ATTR_FLAGS,
1607 icv->flags) ||
1608 nla_put_u16(skb, CHAN_INFO_ATTR_FLAG_EXT,
1609 icv->flagext) ||
1610 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_REG_POWER,
1611 icv->max_reg_power) ||
1612 nla_put_u8(skb, CHAN_INFO_ATTR_MAX_POWER,
1613 icv->max_radio_power) ||
1614 nla_put_u8(skb, CHAN_INFO_ATTR_MIN_POWER,
1615 icv->min_radio_power) ||
1616 nla_put_u8(skb, CHAN_INFO_ATTR_REG_CLASS_ID,
1617 icv->reg_class_id) ||
1618 nla_put_u8(skb, CHAN_INFO_ATTR_ANTENNA_GAIN,
1619 icv->max_antenna_gain) ||
1620 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_0,
1621 icv->vht_center_freq_seg0) ||
1622 nla_put_u8(skb, CHAN_INFO_ATTR_VHT_SEG_1,
1623 icv->vht_center_freq_seg1)) {
1624 hdd_err("put fail");
1625 goto fail;
1626 }
1627 nla_nest_end(skb, channel);
1628 }
1629 nla_nest_end(skb, nla_attr);
1630 return 0;
1631fail:
1632 hdd_err("nl channel update failed");
1633 return -EINVAL;
1634}
1635#undef CHAN_INFO_ATTR_FLAGS
1636#undef CHAN_INFO_ATTR_FLAG_EXT
1637#undef CHAN_INFO_ATTR_FREQ
1638#undef CHAN_INFO_ATTR_MAX_REG_POWER
1639#undef CHAN_INFO_ATTR_MAX_POWER
1640#undef CHAN_INFO_ATTR_MIN_POWER
1641#undef CHAN_INFO_ATTR_REG_CLASS_ID
1642#undef CHAN_INFO_ATTR_ANTENNA_GAIN
1643#undef CHAN_INFO_ATTR_VHT_SEG_0
1644#undef CHAN_INFO_ATTR_VHT_SEG_1
1645
1646/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301647 * hdd_cfg80211_update_pcl() - add pcl info attributes
1648 * @skb: pointer to sk buff
1649 * @hdd_ctx: pointer to hdd station context
1650 * @idx: attribute index
1651 * @vendor_pcl_list: PCL list
1652 * @vendor_weight_list: PCL weights
1653 *
1654 * Return: Success(0) or reason code for failure
1655 */
1656static int32_t
1657hdd_cfg80211_update_pcl(struct sk_buff *skb,
1658 uint8_t ch_list_count, int idx,
1659 uint8_t *vendor_pcl_list, uint8_t *vendor_weight_list)
1660{
1661 struct nlattr *nla_attr, *channel;
1662 int i;
1663
1664 nla_attr = nla_nest_start(skb, idx);
1665
1666 if (!nla_attr)
1667 goto fail;
1668
1669 for (i = 0; i < ch_list_count; i++) {
1670 channel = nla_nest_start(skb, i);
1671 if (!channel)
1672 goto fail;
1673 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_CHANNEL,
1674 vendor_pcl_list[i]) ||
1675 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_PCL_CONFIG_WEIGHT,
1676 vendor_weight_list[i])) {
1677 hdd_err("put fail");
1678 goto fail;
1679 }
1680 nla_nest_end(skb, channel);
1681 }
1682 nla_nest_end(skb, nla_attr);
1683
1684 return 0;
1685fail:
1686 hdd_err("updating pcl list failed");
1687 return -EINVAL;
1688}
1689
1690static void hdd_get_scan_band(tsap_Config_t *sap_config, eCsrBand *band)
1691{
1692 /* Get scan band */
1693 if ((sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) ||
1694 (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G)) {
1695 *band = eCSR_BAND_24;
1696 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1697 *band = eCSR_BAND_5G;
1698 } else if (sap_config->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1699 *band = eCSR_BAND_ALL;
1700 }
1701 /* Auto is not supported currently */
1702 if (!((*band == eCSR_BAND_24) || (eCSR_BAND_5G == *band))) {
1703 hdd_err("invalid band");
1704 *band = eCSR_BAND_24;
1705 }
1706}
1707
1708void hdd_cfg80211_update_acs_config(hdd_adapter_t *adapter,
1709 uint8_t reason)
1710{
1711 struct sk_buff *skb;
1712 tsap_Config_t *sap_config;
1713 uint32_t channel_count = 0, status;
1714 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
1715 uint8_t vendor_pcl_list[QDF_MAX_NUM_CHAN] = {0};
1716 uint8_t vendor_weight_list[QDF_MAX_NUM_CHAN] = {0};
1717 struct hdd_vendor_acs_chan_params acs_chan_params;
1718 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1719 eCsrBand band = eCSR_BAND_24;
1720 eCsrPhyMode phy_mode;
1721
1722 if (!hdd_ctx) {
1723 hdd_err("HDD context is NULL");
1724 return;
1725 }
1726
1727 ENTER();
1728 sap_config = &adapter->sessionCtx.ap.sapConfig;
1729
1730 /* Get valid channels for SAP */
1731 wlan_hdd_sap_get_valid_channellist(adapter,
1732 &channel_count, channel_list);
1733
1734 hdd_update_reg_chan_info(adapter, channel_count, channel_list);
1735 hdd_get_scan_band(&adapter->sessionCtx.ap.sapConfig, &band);
1736 /* Get phymode */
1737 phy_mode = sme_get_phy_mode(WLAN_HDD_GET_HAL_CTX(adapter));
1738
1739 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
1740 &(adapter->wdev),
1741 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
1742 QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG,
1743 GFP_KERNEL);
1744
1745 if (!skb) {
1746 hdd_err("cfg80211_vendor_event_alloc failed");
1747 return;
1748 }
1749 /*
1750 * Application expects pcl to be a subset of channel list
1751 * Remove all channels which are not in channel list from pcl
1752 * and add weight as zero
1753 */
1754 acs_chan_params.channel_count = channel_count;
1755 acs_chan_params.channel_list = channel_list;
1756 acs_chan_params.vendor_pcl_list = vendor_pcl_list;
1757 acs_chan_params.vendor_weight_list = vendor_weight_list;
1758
1759 hdd_update_vendor_pcl_list(hdd_ctx, &acs_chan_params,
1760 sap_config);
1761 /* Update values in NL buffer */
1762 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON,
1763 reason) ||
1764 nla_put_u8(skb,
1765 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED,
1766 false) ||
1767 nla_put_u8(skb,
1768 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED,
1769 true) ||
1770 nla_put_u8(skb,
1771 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT,
1772 true) ||
1773 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH,
1774 sap_config->acs_cfg.ch_width) ||
1775 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_MAC_ADDR,
1776 QDF_MAC_ADDR_SIZE, adapter->macAddressCurrent.bytes) ||
1777 nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND,
1778 band) ||
1779 nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE,
1780 phy_mode) ||
1781 nla_put(skb, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHANLIST,
1782 channel_count, channel_list)) {
1783 hdd_err("nla put fail");
1784 goto fail;
1785 }
1786 status = hdd_cfg80211_update_pcl(skb, channel_count,
1787 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL,
1788 vendor_pcl_list, vendor_weight_list);
1789
1790 if (status != 0)
1791 goto fail;
1792
1793 status = hdd_cfg80211_update_channel_info(skb, sap_config,
1794 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO);
1795
1796 if (status != 0)
1797 goto fail;
1798
1799 cfg80211_vendor_event(skb, GFP_KERNEL);
1800 return;
1801fail:
1802 if (skb)
1803 kfree_skb(skb);
1804}
1805
1806static int hdd_create_acs_timer(hdd_adapter_t *adapter)
1807{
1808 struct hdd_external_acs_timer_context *timer_context;
1809
1810 if (adapter->sessionCtx.ap.vendor_acs_timer_initialized)
1811 return 0;
1812
1813 hdd_notice("Starting vendor app based ACS");
1814 timer_context = qdf_mem_malloc(sizeof(*timer_context));
1815 timer_context->adapter = adapter;
1816
1817 set_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
1818 qdf_mc_timer_init(&adapter->sessionCtx.ap.vendor_acs_timer,
1819 QDF_TIMER_TYPE_SW,
1820 hdd_acs_response_timeout_handler, timer_context);
1821 adapter->sessionCtx.ap.vendor_acs_timer_initialized = true;
1822 return 0;
1823}
1824
1825/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001826 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1827 * @wiphy: Linux wiphy struct pointer
1828 * @wdev: Linux wireless device struct pointer
1829 * @data: ACS information from hostapd
1830 * @data_len: ACS information length
1831 *
1832 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1833 * and starts ACS procedure.
1834 *
1835 * Return: ACS procedure start status
1836 */
1837
1838static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1839 struct wireless_dev *wdev,
1840 const void *data, int data_len)
1841{
1842 struct net_device *ndev = wdev->netdev;
1843 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1844 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1845 tsap_Config_t *sap_config;
1846 struct sk_buff *temp_skbuff;
1847 int status = -EINVAL, i = 0;
1848 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1849 bool ht_enabled, ht40_enabled, vht_enabled;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301850 uint8_t ch_width, hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001851
1852 /* ***Note*** Donot set SME config related to ACS operation here because
1853 * ACS operation is not synchronouse and ACS for Second AP may come when
1854 * ACS operation for first AP is going on. So only do_acs is split to
1855 * seperate start_acs routine. Also SME-PMAC struct that is used to
1856 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1857 * config shall be set only from start_acs.
1858 */
1859
1860 /* nla_policy Policy template. Policy not applied as some attributes are
1861 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1862 *
1863 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1864 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1865 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1866 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1867 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1868 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1869 */
1870
Jeff Johnson1f61b612016-02-12 16:28:33 -08001871 ENTER_DEV(ndev);
1872
Anurag Chouhan6d760662016-02-20 16:05:43 +05301873 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001874 hdd_err("Command not allowed in FTM mode");
1875 return -EPERM;
1876 }
1877
Kapil Gupta8878ad92017-02-13 11:56:04 +05301878 if (hdd_ctx->config->force_sap_acs &&
1879 !hdd_ctx->config->vendor_acs_support) {
Jeff Johnson020db452016-06-29 14:37:26 -07001880 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001881 return -EPERM;
1882 }
1883
1884 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301885 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001886 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301887
Naveen Rawat64e477e2016-05-20 10:34:56 -07001888 if (cds_is_sub_20_mhz_enabled()) {
1889 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1890 status = -EINVAL;
1891 goto out;
1892 }
1893
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001894 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301895 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001896
1897 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1898 NULL);
1899 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001900 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001901 goto out;
1902 }
1903
1904 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001905 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001906 goto out;
1907 }
Kapil Gupta8878ad92017-02-13 11:56:04 +05301908 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1909 sap_config->acs_cfg.hw_mode = hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001910
1911 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1912 ht_enabled =
1913 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1914 else
1915 ht_enabled = 0;
1916
1917 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1918 ht40_enabled =
1919 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1920 else
1921 ht40_enabled = 0;
1922
1923 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1924 vht_enabled =
1925 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1926 else
1927 vht_enabled = 0;
1928
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301929 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1930 vht_enabled = 0;
1931 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1932 }
1933
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001934 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1935 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1936 } else {
1937 if (ht_enabled && ht40_enabled)
1938 ch_width = 40;
1939 else
1940 ch_width = 20;
1941 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301942
1943 /* this may be possible, when sap_force_11n_for_11ac is set */
1944 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1945 if (ht_enabled && ht40_enabled)
1946 ch_width = 40;
1947 else
1948 ch_width = 20;
1949 }
1950
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001951 if (ch_width == 80)
1952 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1953 else if (ch_width == 40)
1954 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1955 else
1956 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1957
1958 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1959 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1960 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1961 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1962 * since it contains the frequency values of the channels in
1963 * the channel list.
1964 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1965 * is present
1966 */
1967 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1968 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1969 sap_config->acs_cfg.ch_list_count = nla_len(
1970 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1971 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301972 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001973 sizeof(uint8_t) *
1974 sap_config->acs_cfg.ch_list_count);
1975 if (sap_config->acs_cfg.ch_list == NULL)
1976 goto out;
1977
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301978 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001979 sap_config->acs_cfg.ch_list_count);
1980 }
1981 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1982 uint32_t *freq =
1983 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1984 sap_config->acs_cfg.ch_list_count = nla_len(
1985 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1986 sizeof(uint32_t);
1987 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301988 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001989 sap_config->acs_cfg.ch_list_count);
1990 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001991 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001992 status = -ENOMEM;
1993 goto out;
1994 }
1995
1996 /* convert frequency to channel */
1997 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1998 sap_config->acs_cfg.ch_list[i] =
1999 ieee80211_frequency_to_channel(freq[i]);
2000 }
2001 }
2002
2003 hdd_debug("get pcl for DO_ACS vendor command");
2004
2005 /* consult policy manager to get PCL */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002006 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc, PM_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05302007 sap_config->acs_cfg.pcl_channels,
2008 &sap_config->acs_cfg.pcl_ch_count,
Kapil Gupta8878ad92017-02-13 11:56:04 +05302009 sap_config->acs_cfg.pcl_channels_weight_list,
2010 QDF_MAX_NUM_CHAN);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302011 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07002012 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002013
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002014 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05302015 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
2016 !hdd_ctx->config->sap_force_11n_for_11ac) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002017 hdd_debug("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002018 vht_enabled = 1;
2019 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
2020 sap_config->acs_cfg.ch_width =
2021 hdd_ctx->config->vhtChannelWidth;
2022 /* No VHT80 in 2.4G so perform ACS accordingly */
2023 if (sap_config->acs_cfg.end_ch <= 14 &&
Kapil Gupta8878ad92017-02-13 11:56:04 +05302024 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002025 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
Kapil Gupta8878ad92017-02-13 11:56:04 +05302026 ch_width = 40;
2027 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002028 }
2029
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05302030 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
2031
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002032 hdd_debug("ACS Config for wlan%d: HW_MODE: %d ACS_BW: %d HT: %d VHT: %d START_CH: %d END_CH: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002033 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
2034 ch_width, ht_enabled, vht_enabled,
2035 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
2036
Kapil Gupta8878ad92017-02-13 11:56:04 +05302037 sap_config->acs_cfg.is_ht_enabled = ht_enabled;
2038 sap_config->acs_cfg.is_vht_enabled = vht_enabled;
2039
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002040 if (sap_config->acs_cfg.ch_list_count) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002041 hdd_debug("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002042 sap_config->acs_cfg.ch_list_count);
2043 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002044 hdd_debug("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002045 }
2046 sap_config->acs_cfg.acs_mode = true;
2047 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002048 /* ***Note*** Completion variable usage is not allowed
2049 * here since ACS scan operation may take max 2.2 sec
2050 * for 5G band:
2051 * 9 Active channel X 40 ms active scan time +
2052 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002053 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
2054 * for this long. So we split up the scanning part.
2055 */
2056 set_bit(ACS_PENDING, &adapter->event_flags);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002057 hdd_debug("ACS Pending for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002058 status = 0;
2059 } else {
Kapil Gupta8878ad92017-02-13 11:56:04 +05302060 /* Check if vendor specific acs is enabled */
2061 if (hdd_ctx->config->vendor_acs_support) {
2062 sap_config->acs_cfg.hw_mode = hw_mode;
2063 hdd_create_acs_timer(adapter);
2064 hdd_update_acs_timer_reason(adapter,
2065 QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT);
2066 if (hdd_ctx->config->acs_support_for_dfs_ltecoex)
2067 wlan_sap_set_vendor_acs(
2068 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2069 true);
2070 else
2071 wlan_sap_set_vendor_acs(
2072 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
2073 false);
2074
2075 } else
2076 status = wlan_hdd_cfg80211_start_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002077 }
2078
2079out:
2080 if (0 == status) {
2081 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
2082 NLMSG_HDRLEN);
2083 if (temp_skbuff != NULL)
2084 return cfg80211_vendor_cmd_reply(temp_skbuff);
2085 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002086 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002087 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
2088
2089 return status;
2090}
2091
Jeff Johnsonf3826e12017-01-12 09:49:40 -08002092/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002093 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
2094 * @wiphy: Linux wiphy struct pointer
2095 * @wdev: Linux wireless device struct pointer
2096 * @data: ACS information from hostapd
2097 * @data_len: ACS information len
2098 *
2099 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
2100 * and starts ACS procedure.
2101 *
2102 * Return: ACS procedure start status
2103 */
2104
2105static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
2106 struct wireless_dev *wdev,
2107 const void *data, int data_len)
2108{
2109 int ret;
2110
2111 cds_ssr_protect(__func__);
2112 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
2113 cds_ssr_unprotect(__func__);
2114
2115 return ret;
2116}
2117
2118/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04002119 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
2120 * @adapter: Pointer to adapter struct
2121 *
2122 * This function handle cleanup of what was done in DO_ACS, including free
2123 * memory.
2124 *
2125 * Return: void
2126 */
2127
2128void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
2129{
2130 if (adapter == NULL)
2131 return;
2132 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
2133 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
2134 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
2135 }
2136}
2137
2138/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002139 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
2140 * @work: Linux workqueue struct pointer for ACS work
2141 *
2142 * This function starts the ACS procedure which was marked pending when an ACS
2143 * procedure was in progress for a concurrent SAP interface.
2144 *
2145 * Return: None
2146 */
2147
2148static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
2149{
2150 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
2151 acs_pending_work.work);
2152 wlan_hdd_cfg80211_start_acs(adapter);
2153}
2154
2155/**
2156 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
2157 * @adapter: Pointer to SAP adapter struct
2158 * @pri_channel: SAP ACS procedure selected Primary channel
2159 * @sec_channel: SAP ACS procedure selected secondary channel
2160 *
2161 * This is a callback function from SAP module on ACS procedure is completed.
2162 * This function send the ACS selected channel information to hostapd
2163 *
2164 * Return: None
2165 */
2166
2167void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
2168{
2169 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
2170 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
2171 struct sk_buff *vendor_event;
2172 int ret_val;
2173 hdd_adapter_t *con_sap_adapter;
2174 uint16_t ch_width;
2175
2176 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08002177 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002178 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
2179 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
2180 GFP_KERNEL);
2181
2182 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002183 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002184 return;
2185 }
2186
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002187 ret_val = nla_put_u8(vendor_event,
2188 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
2189 sap_cfg->acs_cfg.pri_ch);
2190 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002191 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002192 kfree_skb(vendor_event);
2193 return;
2194 }
2195
2196 ret_val = nla_put_u8(vendor_event,
2197 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
2198 sap_cfg->acs_cfg.ht_sec_ch);
2199 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002200 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002201 kfree_skb(vendor_event);
2202 return;
2203 }
2204
2205 ret_val = nla_put_u8(vendor_event,
2206 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
2207 sap_cfg->acs_cfg.vht_seg0_center_ch);
2208 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002209 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002210 kfree_skb(vendor_event);
2211 return;
2212 }
2213
2214 ret_val = nla_put_u8(vendor_event,
2215 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
2216 sap_cfg->acs_cfg.vht_seg1_center_ch);
2217 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002218 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002219 kfree_skb(vendor_event);
2220 return;
2221 }
2222
2223 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
2224 ch_width = 80;
2225 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
2226 ch_width = 40;
2227 else
2228 ch_width = 20;
2229
2230 ret_val = nla_put_u16(vendor_event,
2231 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
2232 ch_width);
2233 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002234 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002235 kfree_skb(vendor_event);
2236 return;
2237 }
2238 if (sap_cfg->acs_cfg.pri_ch > 14)
2239 ret_val = nla_put_u8(vendor_event,
2240 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2241 QCA_ACS_MODE_IEEE80211A);
2242 else
2243 ret_val = nla_put_u8(vendor_event,
2244 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
2245 QCA_ACS_MODE_IEEE80211G);
2246
2247 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07002248 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002249 kfree_skb(vendor_event);
2250 return;
2251 }
2252
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002253 hdd_debug("ACS result for wlan%d: PRI_CH: %d SEC_CH: %d VHT_SEG0: %d VHT_SEG1: %d ACS_BW: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002254 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
2255 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
2256 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
2257
2258 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
2259 /* ***Note*** As already mentioned Completion variable usage is not
2260 * allowed here since ACS scan operation may take max 2.2 sec.
2261 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
2262 * operation.
2263 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
2264 * when Primary AP ACS is complete and secondary AP ACS is started here
2265 * immediately, Primary AP start_bss may come inbetween ACS operation
2266 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
2267 * delay. This path and below constraint will be removed on sessionizing
2268 * SAP acs parameters and decoupling SAP from PMAC (WIP).
2269 * As per design constraint user space control application must take
2270 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
2271 * this code path. Sec AP hostapd should be started after Primary AP
2272 * start beaconing which can be confirmed by getchannel iwpriv command
2273 */
2274
2275 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
2276 if (con_sap_adapter &&
2277 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002278 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
2279 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002280 /* Lets give 500ms for OBSS + START_BSS to complete */
2281 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
2282 msecs_to_jiffies(500));
2283 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
2284 }
2285
2286 return;
2287}
2288
2289static int
2290__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2291 struct wireless_dev *wdev,
2292 const void *data,
2293 int data_len)
2294{
2295 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2296 struct sk_buff *skb = NULL;
2297 uint32_t fset = 0;
2298 int ret;
2299
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07002300 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302301
Anurag Chouhan6d760662016-02-20 16:05:43 +05302302 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002303 hdd_err("Command not allowed in FTM mode");
2304 return -EPERM;
2305 }
2306
2307 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302308 if (ret)
2309 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002310
2311 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002312 hdd_debug("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002313 fset |= WIFI_FEATURE_INFRA;
2314 }
2315 if (true == hdd_is_5g_supported(pHddCtx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002316 hdd_debug("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002317 fset |= WIFI_FEATURE_INFRA_5G;
2318 }
2319#ifdef WLAN_FEATURE_P2P
2320 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
2321 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002322 hdd_debug("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002323 fset |= WIFI_FEATURE_P2P;
2324 }
2325#endif
2326 fset |= WIFI_FEATURE_SOFT_AP;
2327
2328 /* HOTSPOT is a supplicant feature, enable it by default */
2329 fset |= WIFI_FEATURE_HOTSPOT;
2330
2331#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05302332 if (pHddCtx->config->extscan_enabled &&
2333 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002334 hdd_debug("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002335 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
2336 }
2337#endif
2338 if (wlan_hdd_nan_is_supported()) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002339 hdd_debug("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002340 fset |= WIFI_FEATURE_NAN;
2341 }
2342 if (sme_is_feature_supported_by_fw(RTT)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002343 hdd_debug("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002344 fset |= WIFI_FEATURE_D2D_RTT;
2345 fset |= WIFI_FEATURE_D2AP_RTT;
2346 }
2347#ifdef FEATURE_WLAN_SCAN_PNO
2348 if (pHddCtx->config->configPNOScanSupport &&
2349 sme_is_feature_supported_by_fw(PNO)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002350 hdd_debug("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002351 fset |= WIFI_FEATURE_PNO;
2352 }
2353#endif
2354 fset |= WIFI_FEATURE_ADDITIONAL_STA;
2355#ifdef FEATURE_WLAN_TDLS
2356 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
2357 sme_is_feature_supported_by_fw(TDLS)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002358 hdd_debug("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002359 fset |= WIFI_FEATURE_TDLS;
2360 }
2361 if (sme_is_feature_supported_by_fw(TDLS) &&
2362 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
2363 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002364 hdd_debug("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002365 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
2366 }
2367#endif
2368#ifdef WLAN_AP_STA_CONCURRENCY
2369 fset |= WIFI_FEATURE_AP_STA;
2370#endif
2371 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07002372 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002373
2374 if (hdd_link_layer_stats_supported())
2375 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
2376
2377 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
2378 NLMSG_HDRLEN);
2379 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002380 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002381 return -EINVAL;
2382 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002383 hdd_debug("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002384 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002385 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002386 goto nla_put_failure;
2387 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302388 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05302389 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002390nla_put_failure:
2391 kfree_skb(skb);
2392 return -EINVAL;
2393}
2394
2395/**
2396 * wlan_hdd_cfg80211_get_supported_features() - get supported features
2397 * @wiphy: pointer to wireless wiphy structure.
2398 * @wdev: pointer to wireless_dev structure.
2399 * @data: Pointer to the data to be passed via vendor interface
2400 * @data_len:Length of the data to be passed
2401 *
2402 * Return: Return the Success or Failure code.
2403 */
2404static int
2405wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
2406 struct wireless_dev *wdev,
2407 const void *data, int data_len)
2408{
2409 int ret = 0;
2410
2411 cds_ssr_protect(__func__);
2412 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
2413 data, data_len);
2414 cds_ssr_unprotect(__func__);
2415
2416 return ret;
2417}
2418
2419/**
2420 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2421 * @wiphy: pointer to wireless wiphy structure.
2422 * @wdev: pointer to wireless_dev structure.
2423 * @data: Pointer to the data to be passed via vendor interface
2424 * @data_len:Length of the data to be passed
2425 *
2426 * Set the MAC address that is to be used for scanning.
2427 *
2428 * Return: Return the Success or Failure code.
2429 */
2430static int
2431__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2432 struct wireless_dev *wdev,
2433 const void *data,
2434 int data_len)
2435{
2436 tpSirScanMacOui pReqMsg = NULL;
2437 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2438 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302439 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002440 int ret;
2441
Jeff Johnson1f61b612016-02-12 16:28:33 -08002442 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002443
Anurag Chouhan6d760662016-02-20 16:05:43 +05302444 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002445 hdd_err("Command not allowed in FTM mode");
2446 return -EPERM;
2447 }
2448
2449 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302450 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002451 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002452
2453 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002454 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002455 return -ENOTSUPP;
2456 }
2457
2458 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2459 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002460 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002461 return -EINVAL;
2462 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302463 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002464 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002465 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002466 return -ENOMEM;
2467 }
2468 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002469 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002470 goto fail;
2471 }
2472 nla_memcpy(&pReqMsg->oui[0],
2473 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2474 sizeof(pReqMsg->oui));
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002475 hdd_debug("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002476 pReqMsg->oui[1], pReqMsg->oui[2]);
2477 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302478 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002479 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002480 goto fail;
2481 }
2482 return 0;
2483fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302484 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002485 return -EINVAL;
2486}
2487
2488/**
2489 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2490 * @wiphy: pointer to wireless wiphy structure.
2491 * @wdev: pointer to wireless_dev structure.
2492 * @data: Pointer to the data to be passed via vendor interface
2493 * @data_len:Length of the data to be passed
2494 *
2495 * Set the MAC address that is to be used for scanning. This is an
2496 * SSR-protecting wrapper function.
2497 *
2498 * Return: Return the Success or Failure code.
2499 */
2500static int
2501wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2502 struct wireless_dev *wdev,
2503 const void *data,
2504 int data_len)
2505{
2506 int ret;
2507
2508 cds_ssr_protect(__func__);
2509 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2510 data, data_len);
2511 cds_ssr_unprotect(__func__);
2512
2513 return ret;
2514}
2515
2516/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302517 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2518 * @wiphy: pointer phy adapter
2519 * @wdev: pointer to wireless device structure
2520 * @data: pointer to data buffer
2521 * @data_len: length of data
2522 *
2523 * This routine will give concurrency matrix
2524 *
2525 * Return: int status code
2526 */
2527static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2528 struct wireless_dev *wdev,
2529 const void *data,
2530 int data_len)
2531{
2532 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2533 uint8_t i, feature_sets, max_feature_sets;
2534 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2535 struct sk_buff *reply_skb;
2536 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2537 int ret;
2538
2539 ENTER_DEV(wdev->netdev);
2540
2541 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2542 hdd_err("Command not allowed in FTM mode");
2543 return -EPERM;
2544 }
2545
2546 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302547 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302548 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302549
2550 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2551 data, data_len, NULL)) {
2552 hdd_err("Invalid ATTR");
2553 return -EINVAL;
2554 }
2555
2556 /* Parse and fetch max feature set */
2557 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2558 hdd_err("Attr max feature set size failed");
2559 return -EINVAL;
2560 }
2561 max_feature_sets = nla_get_u32(tb[
2562 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002563 hdd_debug("Max feature set size: %d", max_feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302564
2565 /* Fill feature combination matrix */
2566 feature_sets = 0;
2567 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002568 WIFI_FEATURE_P2P;
2569 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2570 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302571 /* Add more feature combinations here */
2572
2573 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002574 hdd_debug("Number of feature sets: %d", feature_sets);
2575 hdd_debug("Feature set matrix");
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302576 for (i = 0; i < feature_sets; i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002577 hdd_debug("[%d] 0x%02X", i, feature_set_matrix[i]);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302578
2579 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2580 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2581 if (!reply_skb) {
2582 hdd_err("Feature set matrix: buffer alloc fail");
2583 return -ENOMEM;
2584 }
2585
2586 if (nla_put_u32(reply_skb,
2587 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2588 feature_sets) ||
2589 nla_put(reply_skb,
2590 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2591 sizeof(u32) * feature_sets,
2592 feature_set_matrix)) {
2593 hdd_err("nla put fail");
2594 kfree_skb(reply_skb);
2595 return -EINVAL;
2596 }
2597 return cfg80211_vendor_cmd_reply(reply_skb);
2598}
2599
2600/**
2601 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2602 * @wiphy: pointer to wireless wiphy structure.
2603 * @wdev: pointer to wireless_dev structure.
2604 * @data: Pointer to the data to be passed via vendor interface
2605 * @data_len:Length of the data to be passed
2606 *
2607 * Retrieves the concurrency feature set matrix
2608 *
2609 * Return: 0 on success, negative errno on failure
2610 */
2611static int
2612wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2613 struct wireless_dev *wdev,
2614 const void *data,
2615 int data_len)
2616{
2617 int ret;
2618
2619 cds_ssr_protect(__func__);
2620 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2621 data, data_len);
2622 cds_ssr_unprotect(__func__);
2623
2624 return ret;
2625}
2626
2627/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002628 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2629 * @feature_flags: pointer to the byte array of features.
2630 * @feature: Feature to be turned ON in the byte array.
2631 *
2632 * Return: None
2633 *
2634 * This is called to turn ON or SET the feature flag for the requested feature.
2635 **/
2636#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002637static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2638 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002639{
2640 uint32_t index;
2641 uint8_t bit_mask;
2642
2643 index = feature / NUM_BITS_IN_BYTE;
2644 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2645 feature_flags[index] |= bit_mask;
2646}
2647
2648/**
2649 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2650 * @wiphy: pointer to wireless wiphy structure.
2651 * @wdev: pointer to wireless_dev structure.
2652 * @data: Pointer to the data to be passed via vendor interface
2653 * @data_len:Length of the data to be passed
2654 *
2655 * This is called when wlan driver needs to send supported feature set to
2656 * supplicant upon a request/query from the supplicant.
2657 *
2658 * Return: Return the Success or Failure code.
2659 **/
2660#define MAX_CONCURRENT_CHAN_ON_24G 2
2661#define MAX_CONCURRENT_CHAN_ON_5G 2
2662static int
2663__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2664 struct wireless_dev *wdev,
2665 const void *data, int data_len)
2666{
2667 struct sk_buff *skb = NULL;
2668 uint32_t dbs_capability = 0;
2669 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302670 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002671 int ret_val;
2672
2673 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2674 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2675
Jeff Johnson1f61b612016-02-12 16:28:33 -08002676 ENTER_DEV(wdev->netdev);
2677
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002678 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2679 if (ret_val)
2680 return ret_val;
2681
Anurag Chouhan6d760662016-02-20 16:05:43 +05302682 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002683 hdd_err("Command not allowed in FTM mode");
2684 return -EPERM;
2685 }
2686
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002687 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002688 hdd_debug("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002689 wlan_hdd_cfg80211_set_feature(feature_flags,
2690 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2691 }
2692
2693 wlan_hdd_cfg80211_set_feature(feature_flags,
2694 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002695 if (policy_mgr_is_scan_simultaneous_capable(hdd_ctx_ptr->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002696 wlan_hdd_cfg80211_set_feature(feature_flags,
2697 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002698
2699 if (wma_is_p2p_lo_capable())
2700 wlan_hdd_cfg80211_set_feature(feature_flags,
2701 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2702
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002703 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2704 NLMSG_HDRLEN);
2705
2706 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002707 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002708 return -ENOMEM;
2709 }
2710
2711 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2712 sizeof(feature_flags), feature_flags))
2713 goto nla_put_failure;
2714
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08002715 ret = policy_mgr_get_dbs_hw_modes(hdd_ctx_ptr->hdd_psoc,
2716 &one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302717 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002718 if (one_by_one_dbs)
2719 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2720
2721 if (two_by_two_dbs)
2722 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2723
2724 if (!one_by_one_dbs && !two_by_two_dbs)
2725 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2726 } else {
2727 hdd_err("wma_get_dbs_hw_mode failed");
2728 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2729 }
2730
Srinivas Girigowda13d39252017-03-06 16:12:15 -08002731 hdd_debug("dbs_capability is %d", dbs_capability);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002732
2733 if (nla_put_u32(skb,
2734 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2735 MAX_CONCURRENT_CHAN_ON_24G))
2736 goto nla_put_failure;
2737
2738 if (nla_put_u32(skb,
2739 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2740 MAX_CONCURRENT_CHAN_ON_5G))
2741 goto nla_put_failure;
2742
2743 return cfg80211_vendor_cmd_reply(skb);
2744
2745nla_put_failure:
2746 kfree_skb(skb);
2747 return -EINVAL;
2748}
2749
2750/**
2751 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2752 * @wiphy: pointer to wireless wiphy structure.
2753 * @wdev: pointer to wireless_dev structure.
2754 * @data: Pointer to the data to be passed via vendor interface
2755 * @data_len:Length of the data to be passed
2756 *
2757 * This is called when wlan driver needs to send supported feature set to
2758 * supplicant upon a request/query from the supplicant.
2759 *
2760 * Return: Return the Success or Failure code.
2761 */
2762static int
2763wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2764 struct wireless_dev *wdev,
2765 const void *data, int data_len)
2766{
2767 int ret;
2768
2769 cds_ssr_protect(__func__);
2770 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2771 data, data_len);
2772 cds_ssr_unprotect(__func__);
2773
2774 return ret;
2775}
2776
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302777#define PARAM_NUM_NW \
2778 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS
2779#define PARAM_SET_BSSID \
2780 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID
2781#define PRAM_SSID_LIST QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST
2782#define PARAM_LIST_SSID QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002783
2784/**
2785 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2786 * @wiphy: The wiphy structure
2787 * @wdev: The wireless device
2788 * @data: Data passed by framework
2789 * @data_len: Parameters to be configured passed as data
2790 *
2791 * The roaming related parameters are configured by the framework
2792 * using this interface.
2793 *
2794 * Return: Return either success or failure code.
2795 */
2796static int
2797__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2798 struct wireless_dev *wdev, const void *data, int data_len)
2799{
2800 struct net_device *dev = wdev->netdev;
2801 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2802 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2803 uint8_t session_id;
2804 struct roam_ext_params roam_params;
2805 uint32_t cmd_type, req_id;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302806 struct nlattr *curr_attr = NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002807 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2808 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2809 int rem, i;
2810 uint32_t buf_len = 0;
Prakash Dhavali075334e2016-11-29 07:22:08 -08002811 uint32_t count;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002812 int ret;
2813
Jeff Johnson1f61b612016-02-12 16:28:33 -08002814 ENTER_DEV(dev);
2815
Anurag Chouhan6d760662016-02-20 16:05:43 +05302816 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002817 hdd_err("Command not allowed in FTM mode");
2818 return -EPERM;
2819 }
2820
2821 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302822 if (ret)
2823 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002824
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05302825 if (pHddCtx->driver_status == DRIVER_MODULES_CLOSED) {
2826 hdd_err("Driver Modules are closed");
2827 return -EINVAL;
2828 }
2829
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002830 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2831 data, data_len,
2832 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002833 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002834 return -EINVAL;
2835 }
2836 /* Parse and fetch Command Type*/
2837 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002838 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002839 goto fail;
2840 }
2841 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302842 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002843 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2844 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002845 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002846 goto fail;
2847 }
2848 req_id = nla_get_u32(
2849 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002850 hdd_debug("Req Id (%d)", req_id);
2851 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002852 switch (cmd_type) {
2853 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2854 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302855 if (tb[PARAM_NUM_NW]) {
2856 count = nla_get_u32(
2857 tb[PARAM_NUM_NW]);
2858 } else {
2859 hdd_err("Number of networks is not provided");
2860 goto fail;
2861 }
2862
2863 if (count &&
2864 tb[PRAM_SSID_LIST]) {
2865 nla_for_each_nested(curr_attr,
2866 tb[PRAM_SSID_LIST], rem) {
2867 if (nla_parse(tb2,
2868 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2869 nla_data(curr_attr), nla_len(curr_attr),
2870 NULL)) {
2871 hdd_err("nla_parse failed");
2872 goto fail;
2873 }
2874 /* Parse and Fetch allowed SSID list*/
2875 if (!tb2[PARAM_LIST_SSID]) {
2876 hdd_err("attr allowed ssid failed");
2877 goto fail;
2878 }
2879 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
2880 /*
2881 * Upper Layers include a null termination
2882 * character. Check for the actual permissible
2883 * length of SSID and also ensure not to copy
2884 * the NULL termination character to the driver
2885 * buffer.
2886 */
2887 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2888 ((buf_len - 1) <=
2889 SIR_MAC_MAX_SSID_LENGTH)) {
2890 nla_memcpy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002891 roam_params.ssid_allowed_list[i].ssId,
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302892 tb2[PARAM_LIST_SSID], buf_len - 1);
2893 roam_params.ssid_allowed_list[i].length
2894 = buf_len - 1;
2895 hdd_debug("SSID[%d]: %.*s,length = %d",
2896 i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002897 roam_params.ssid_allowed_list[i].length,
2898 roam_params.ssid_allowed_list[i].ssId,
2899 roam_params.ssid_allowed_list[i].length);
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302900 i++;
2901 } else {
2902 hdd_err("Invalid buffer length");
2903 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002904 }
2905 }
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302906 if (i != count) {
2907 hdd_err("Invalid number of SSIDs i = %d, count = %d",
2908 i, count);
2909 goto fail;
2910 }
2911
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002912 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002913 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002914 roam_params.num_ssid_allowed_list);
2915 sme_update_roam_params(pHddCtx->hHal, session_id,
2916 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2917 break;
2918 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2919 /* Parse and fetch 5G Boost Threshold */
2920 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002921 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002922 goto fail;
2923 }
2924 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2925 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002926 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002927 roam_params.raise_rssi_thresh_5g);
2928 /* Parse and fetch 5G Penalty Threshold */
2929 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002930 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002931 goto fail;
2932 }
2933 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2934 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002935 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002936 roam_params.drop_rssi_thresh_5g);
2937 /* Parse and fetch 5G Boost Factor */
2938 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002939 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002940 goto fail;
2941 }
2942 roam_params.raise_factor_5g = nla_get_u32(
2943 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002944 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002945 roam_params.raise_factor_5g);
2946 /* Parse and fetch 5G Penalty factor */
2947 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002948 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002949 goto fail;
2950 }
2951 roam_params.drop_factor_5g = nla_get_u32(
2952 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002953 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002954 roam_params.drop_factor_5g);
2955 /* Parse and fetch 5G Max Boost */
2956 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002957 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002958 goto fail;
2959 }
2960 roam_params.max_raise_rssi_5g = nla_get_u32(
2961 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002962 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002963 roam_params.max_raise_rssi_5g);
2964 /* Parse and fetch Rssi Diff */
2965 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002966 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002967 goto fail;
2968 }
2969 roam_params.rssi_diff = nla_get_s32(
2970 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002971 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002972 roam_params.rssi_diff);
2973 /* Parse and fetch Alert Rssi Threshold */
2974 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002975 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002976 goto fail;
2977 }
2978 roam_params.alert_rssi_threshold = nla_get_u32(
2979 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002980 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002981 roam_params.alert_rssi_threshold);
2982 sme_update_roam_params(pHddCtx->hHal, session_id,
2983 roam_params,
2984 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2985 break;
2986 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2987 /* Parse and fetch Activate Good Rssi Roam */
2988 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002989 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002990 goto fail;
2991 }
2992 roam_params.good_rssi_roam = nla_get_s32(
2993 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002994 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002995 roam_params.good_rssi_roam);
2996 sme_update_roam_params(pHddCtx->hHal, session_id,
2997 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2998 break;
2999 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
3000 /* Parse and fetch number of preferred BSSID */
3001 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003002 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003003 goto fail;
3004 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003005 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003006 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003007 if (count > MAX_BSSID_FAVORED) {
3008 hdd_err("Preferred BSSID count %u exceeds max %u",
3009 count, MAX_BSSID_FAVORED);
3010 goto fail;
3011 }
3012 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003013 i = 0;
3014 nla_for_each_nested(curr_attr,
3015 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
3016 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003017
3018 if (i == count) {
3019 hdd_warn("Ignoring excess Preferred BSSID");
3020 break;
3021 }
3022
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003023 if (nla_parse(tb2,
3024 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3025 nla_data(curr_attr), nla_len(curr_attr),
3026 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003027 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003028 goto fail;
3029 }
3030 /* Parse and fetch MAC address */
3031 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003032 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003033 goto fail;
3034 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003035 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003036 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303037 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003038 hdd_debug(MAC_ADDRESS_STR,
3039 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003040 /* Parse and fetch preference factor*/
3041 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003042 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003043 goto fail;
3044 }
3045 roam_params.bssid_favored_factor[i] = nla_get_u32(
3046 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003047 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003048 roam_params.bssid_favored_factor[i]);
3049 i++;
3050 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003051 if (i < count)
3052 hdd_warn("Num Preferred BSSID %u less than expected %u",
3053 i, count);
3054 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003055 sme_update_roam_params(pHddCtx->hHal, session_id,
3056 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3057 break;
3058 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3059 /* Parse and fetch number of blacklist BSSID */
3060 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003061 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003062 goto fail;
3063 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003064 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003065 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003066 if (count > MAX_BSSID_AVOID_LIST) {
3067 hdd_err("Blacklist BSSID count %u exceeds max %u",
3068 count, MAX_BSSID_AVOID_LIST);
3069 goto fail;
3070 }
3071 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003072 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303073
3074 if (count &&
3075 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS]) {
3076 nla_for_each_nested(curr_attr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003077 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
3078 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003079
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303080 if (i == count) {
3081 hdd_warn("Ignoring excess Blacklist BSSID");
3082 break;
3083 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003084
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303085 if (nla_parse(tb2,
3086 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3087 nla_data(curr_attr), nla_len(curr_attr),
3088 NULL)) {
3089 hdd_err("nla_parse failed");
3090 goto fail;
3091 }
3092 /* Parse and fetch MAC address */
3093 if (!tb2[PARAM_SET_BSSID]) {
3094 hdd_err("attr blacklist addr failed");
3095 goto fail;
3096 }
3097 nla_memcpy(
3098 roam_params.bssid_avoid_list[i].bytes,
3099 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3100 hdd_debug(MAC_ADDRESS_STR,
3101 MAC_ADDR_ARRAY(
3102 roam_params.bssid_avoid_list[i].bytes));
3103 i++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003104 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003105 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003106 if (i < count)
3107 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3108 i, count);
3109 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003110 sme_update_roam_params(pHddCtx->hHal, session_id,
3111 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3112 break;
3113 }
3114 return 0;
3115fail:
3116 return -EINVAL;
3117}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303118#undef PARAM_NUM_NW
3119#undef PARAM_SET_BSSID
3120#undef PRAM_SSID_LIST
3121#undef PARAM_LIST_SSID
3122
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003123
3124/**
3125 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3126 * @wiphy: pointer to wireless wiphy structure.
3127 * @wdev: pointer to wireless_dev structure.
3128 * @data: Pointer to the data to be passed via vendor interface
3129 * @data_len:Length of the data to be passed
3130 *
3131 * Return: Return the Success or Failure code.
3132 */
3133static int
3134wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3135 struct wireless_dev *wdev,
3136 const void *data,
3137 int data_len)
3138{
3139 int ret;
3140
3141 cds_ssr_protect(__func__);
3142 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3143 data, data_len);
3144 cds_ssr_unprotect(__func__);
3145
3146 return ret;
3147}
3148
3149static const struct nla_policy
3150wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
3151 +1] = {
3152 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
3153};
3154
3155/**
3156 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
3157 * @hdd_ctx: HDD context
3158 * @device_mode: device mode
3159 * Return: bool
3160 */
3161static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08003162 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003163{
3164 hdd_adapter_t *adapter;
3165 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3166 hdd_ap_ctx_t *ap_ctx;
3167 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303168 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003169
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303170 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003171 &adapter_node);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003172 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303173 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003174 adapter = adapter_node->pAdapter;
3175
3176 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003177 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003178 ap_ctx =
3179 WLAN_HDD_GET_AP_CTX_PTR(adapter);
3180
3181 /*
3182 * if there is SAP already running on DFS channel,
3183 * do not disable scan on dfs channels. Note that
3184 * with SAP on DFS, there cannot be conurrency on
3185 * single radio. But then we can have multiple
3186 * radios !!
3187 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003188 if (CHANNEL_STATE_DFS == wlan_reg_get_channel_state(
3189 hdd_ctx->hdd_pdev,
3190 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003191 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003192 return true;
3193 }
3194 }
3195
3196 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003197 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003198 sta_ctx =
3199 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3200
3201 /*
3202 * if STA is already connected on DFS channel,
3203 * do not disable scan on dfs channels
3204 */
3205 if (hdd_conn_is_connected(sta_ctx) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07003206 (CHANNEL_STATE_DFS ==
3207 wlan_reg_get_channel_state(hdd_ctx->hdd_pdev,
3208 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07003209 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003210 return true;
3211 }
3212 }
3213
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303214 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003215 adapter_node,
3216 &next);
3217 adapter_node = next;
3218 }
3219
3220 return false;
3221}
3222
3223/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003224 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
3225 * @hdd_ctx: HDD context within host driver
3226 * @adapter: Adapter pointer
3227 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
3228 *
3229 * Loops through devices to see who is operating on DFS channels
3230 * and then disables/enables DFS channels by calling SME API.
3231 * Fails the disable request if any device is active on a DFS channel.
3232 *
3233 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003234 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003235
3236int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
3237 hdd_adapter_t *adapter,
3238 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003239{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003240 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303241 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003242 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003243
3244 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
3245 if (no_dfs_flag) {
3246 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003247 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003248
3249 if (true == status)
3250 return -EOPNOTSUPP;
3251
3252 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003253 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003254
3255 if (true == status)
3256 return -EOPNOTSUPP;
3257 }
3258
3259 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
3260
3261 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3262
3263 /*
3264 * call the SME API to tunnel down the new channel list
3265 * to the firmware
3266 */
3267 status = sme_handle_dfs_chan_scan(
3268 h_hal, hdd_ctx->config->enableDFSChnlScan);
3269
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303270 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003271 ret_val = 0;
3272
3273 /*
3274 * Clear the SME scan cache also. Note that the
3275 * clearing of scan results is independent of session;
3276 * so no need to iterate over
3277 * all sessions
3278 */
3279 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303280 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003281 ret_val = -EPERM;
3282 }
3283
3284 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003285 hdd_debug(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003286 ret_val = 0;
3287 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003288 return ret_val;
3289}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003290
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003291/**
3292 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
3293 * @wiphy: corestack handler
3294 * @wdev: wireless device
3295 * @data: data
3296 * @data_len: data length
3297 * Return: success(0) or reason code for failure
3298 */
3299static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3300 struct wireless_dev *wdev,
3301 const void *data,
3302 int data_len)
3303{
3304 struct net_device *dev = wdev->netdev;
3305 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3306 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3307 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
3308 int ret_val;
3309 uint32_t no_dfs_flag = 0;
3310
Jeff Johnson1f61b612016-02-12 16:28:33 -08003311 ENTER_DEV(dev);
3312
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003313 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303314 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003315 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003316
3317 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
3318 data, data_len,
3319 wlan_hdd_set_no_dfs_flag_config_policy)) {
3320 hdd_err("invalid attr");
3321 return -EINVAL;
3322 }
3323
3324 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3325 hdd_err("attr dfs flag failed");
3326 return -EINVAL;
3327 }
3328
3329 no_dfs_flag = nla_get_u32(
3330 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3331
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003332 hdd_debug("DFS flag: %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003333
3334 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003335 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003336 return -EINVAL;
3337 }
3338
3339 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
3340 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003341 return ret_val;
3342}
3343
3344/**
3345 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3346 *
3347 * @wiphy: wiphy device pointer
3348 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003349 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003350 * @data_len: Buffer length
3351 *
3352 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3353 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3354 *
3355 * Return: EOK or other error codes.
3356 */
3357
3358static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3359 struct wireless_dev *wdev,
3360 const void *data,
3361 int data_len)
3362{
3363 int ret;
3364
3365 cds_ssr_protect(__func__);
3366 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3367 data, data_len);
3368 cds_ssr_unprotect(__func__);
3369
3370 return ret;
3371}
3372
Manikandan Mohan80dea792016-04-28 16:36:48 -07003373static const struct nla_policy
3374wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3375 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3376};
3377
3378/**
3379 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3380 * @wiphy: wiphy device pointer
3381 * @wdev: wireless device pointer
3382 * @data: Vendor command data buffer
3383 * @data_len: Buffer length
3384 *
3385 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3386 * setup WISA Mode features.
3387 *
3388 * Return: Success(0) or reason code for failure
3389 */
3390static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3391 struct wireless_dev *wdev, const void *data, int data_len)
3392{
3393 struct net_device *dev = wdev->netdev;
3394 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3395 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3396 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3397 struct sir_wisa_params wisa;
3398 int ret_val;
3399 QDF_STATUS status;
3400 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003401 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3402 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003403
3404 ENTER_DEV(dev);
3405 ret_val = wlan_hdd_validate_context(hdd_ctx);
3406 if (ret_val)
3407 goto err;
3408
3409 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3410 hdd_err("Command not allowed in FTM mode");
3411 return -EPERM;
3412 }
3413
3414 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3415 wlan_hdd_wisa_cmd_policy)) {
3416 hdd_err("Invalid WISA cmd attributes");
3417 ret_val = -EINVAL;
3418 goto err;
3419 }
3420 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3421 hdd_err("Invalid WISA mode");
3422 ret_val = -EINVAL;
3423 goto err;
3424 }
3425
3426 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003427 hdd_debug("WISA Mode: %d", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003428 wisa.mode = wisa_mode;
3429 wisa.vdev_id = adapter->sessionId;
3430 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003431 if (!QDF_IS_STATUS_SUCCESS(status)) {
3432 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003433 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003434 }
3435 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003436 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003437 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
3438 (struct cdp_pdev *)pdev,
Leo Changfdb45c32016-10-28 11:09:23 -07003439 adapter->sessionId),
3440 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003441err:
3442 EXIT();
3443 return ret_val;
3444}
3445
3446/**
3447 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3448 * @wiphy: corestack handler
3449 * @wdev: wireless device
3450 * @data: data
3451 * @data_len: data length
3452 *
3453 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3454 * setup WISA mode features.
3455 *
3456 * Return: Success(0) or reason code for failure
3457 */
3458static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3459 struct wireless_dev *wdev,
3460 const void *data,
3461 int data_len)
3462{
3463 int ret;
3464
3465 cds_ssr_protect(__func__);
3466 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3467 cds_ssr_unprotect(__func__);
3468
3469 return ret;
3470}
3471
Anurag Chouhan96919482016-07-13 16:36:57 +05303472/*
3473 * define short names for the global vendor params
3474 * used by __wlan_hdd_cfg80211_get_station_cmd()
3475 */
3476#define STATION_INVALID \
3477 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3478#define STATION_INFO \
3479 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3480#define STATION_ASSOC_FAIL_REASON \
3481 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3482#define STATION_MAX \
3483 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3484
3485static const struct nla_policy
3486hdd_get_station_policy[STATION_MAX + 1] = {
3487 [STATION_INFO] = {.type = NLA_FLAG},
3488 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3489};
3490
3491/**
3492 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3493 * @hdd_ctx: HDD context within host driver
3494 * @wdev: wireless device
3495 *
3496 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3497 * Validate cmd attributes and send the station info to upper layers.
3498 *
3499 * Return: Success(0) or reason code for failure
3500 */
3501static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3502 hdd_adapter_t *adapter)
3503{
3504 struct sk_buff *skb = NULL;
3505 uint32_t nl_buf_len;
3506 hdd_station_ctx_t *hdd_sta_ctx;
3507
3508 nl_buf_len = NLMSG_HDRLEN;
3509 nl_buf_len += sizeof(uint32_t);
3510 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3511
3512 if (!skb) {
3513 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3514 return -ENOMEM;
3515 }
3516
3517 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3518
3519 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3520 hdd_sta_ctx->conn_info.assoc_status_code)) {
3521 hdd_err("put fail");
3522 goto fail;
3523 }
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05303524
3525 hdd_info("congestion:%d", hdd_sta_ctx->conn_info.cca);
3526 if (nla_put_u32(skb, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
3527 hdd_sta_ctx->conn_info.cca)) {
3528 hdd_err("put fail");
3529 goto fail;
3530 }
3531
Anurag Chouhan96919482016-07-13 16:36:57 +05303532 return cfg80211_vendor_cmd_reply(skb);
3533fail:
3534 if (skb)
3535 kfree_skb(skb);
3536 return -EINVAL;
3537}
3538
3539/**
3540 * hdd_map_auth_type() - transform auth type specific to
3541 * vendor command
3542 * @auth_type: csr auth type
3543 *
3544 * Return: Success(0) or reason code for failure
3545 */
3546static int hdd_convert_auth_type(uint32_t auth_type)
3547{
3548 uint32_t ret_val;
3549
3550 switch (auth_type) {
3551 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3552 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3553 break;
3554 case eCSR_AUTH_TYPE_SHARED_KEY:
3555 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3556 break;
3557 case eCSR_AUTH_TYPE_WPA:
3558 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3559 break;
3560 case eCSR_AUTH_TYPE_WPA_PSK:
3561 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3562 break;
3563 case eCSR_AUTH_TYPE_AUTOSWITCH:
3564 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3565 break;
3566 case eCSR_AUTH_TYPE_WPA_NONE:
3567 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3568 break;
3569 case eCSR_AUTH_TYPE_RSN:
3570 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3571 break;
3572 case eCSR_AUTH_TYPE_RSN_PSK:
3573 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3574 break;
3575 case eCSR_AUTH_TYPE_FT_RSN:
3576 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3577 break;
3578 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3579 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3580 break;
3581 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3582 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3583 break;
3584 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3585 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3586 break;
3587 case eCSR_AUTH_TYPE_CCKM_WPA:
3588 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3589 break;
3590 case eCSR_AUTH_TYPE_CCKM_RSN:
3591 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3592 break;
3593 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3594 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3595 break;
3596 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3597 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3598 break;
3599 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3600 case eCSR_AUTH_TYPE_FAILED:
3601 case eCSR_AUTH_TYPE_NONE:
3602 default:
3603 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3604 break;
3605 }
3606 return ret_val;
3607}
3608
3609/**
3610 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3611 * vendor command
3612 * @dot11mode: dot11mode
3613 *
3614 * Return: Success(0) or reason code for failure
3615 */
3616static int hdd_convert_dot11mode(uint32_t dot11mode)
3617{
3618 uint32_t ret_val;
3619
3620 switch (dot11mode) {
3621 case eCSR_CFG_DOT11_MODE_11A:
3622 ret_val = QCA_WLAN_802_11_MODE_11A;
3623 break;
3624 case eCSR_CFG_DOT11_MODE_11B:
3625 ret_val = QCA_WLAN_802_11_MODE_11B;
3626 break;
3627 case eCSR_CFG_DOT11_MODE_11G:
3628 ret_val = QCA_WLAN_802_11_MODE_11G;
3629 break;
3630 case eCSR_CFG_DOT11_MODE_11N:
3631 ret_val = QCA_WLAN_802_11_MODE_11N;
3632 break;
3633 case eCSR_CFG_DOT11_MODE_11AC:
3634 ret_val = QCA_WLAN_802_11_MODE_11AC;
3635 break;
3636 case eCSR_CFG_DOT11_MODE_AUTO:
3637 case eCSR_CFG_DOT11_MODE_ABG:
3638 default:
3639 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3640 }
3641 return ret_val;
3642}
3643
3644/**
3645 * hdd_add_tx_bitrate() - add tx bitrate attribute
3646 * @skb: pointer to sk buff
3647 * @hdd_sta_ctx: pointer to hdd station context
3648 * @idx: attribute index
3649 *
3650 * Return: Success(0) or reason code for failure
3651 */
3652static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3653 hdd_station_ctx_t *hdd_sta_ctx,
3654 int idx)
3655{
3656 struct nlattr *nla_attr;
3657 uint32_t bitrate, bitrate_compat;
3658
3659 nla_attr = nla_nest_start(skb, idx);
3660 if (!nla_attr)
3661 goto fail;
3662 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3663 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3664
3665 /* report 16-bit bitrate only if we can */
3666 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3667 if (bitrate > 0 &&
3668 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3669 hdd_err("put fail");
3670 goto fail;
3671 }
3672 if (bitrate_compat > 0 &&
3673 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3674 hdd_err("put fail");
3675 goto fail;
3676 }
3677 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3678 hdd_sta_ctx->conn_info.txrate.nss)) {
3679 hdd_err("put fail");
3680 goto fail;
3681 }
3682 nla_nest_end(skb, nla_attr);
3683 return 0;
3684fail:
3685 return -EINVAL;
3686}
3687
3688/**
3689 * hdd_add_sta_info() - add station info attribute
3690 * @skb: pointer to sk buff
3691 * @hdd_sta_ctx: pointer to hdd station context
3692 * @idx: attribute index
3693 *
3694 * Return: Success(0) or reason code for failure
3695 */
3696static int32_t hdd_add_sta_info(struct sk_buff *skb,
3697 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3698{
3699 struct nlattr *nla_attr;
3700
3701 nla_attr = nla_nest_start(skb, idx);
3702 if (!nla_attr)
3703 goto fail;
3704 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3705 (hdd_sta_ctx->conn_info.signal + 100))) {
3706 hdd_err("put fail");
3707 goto fail;
3708 }
3709 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3710 goto fail;
3711 nla_nest_end(skb, nla_attr);
3712 return 0;
3713fail:
3714 return -EINVAL;
3715}
3716
3717/**
3718 * hdd_add_survey_info() - add survey info attribute
3719 * @skb: pointer to sk buff
3720 * @hdd_sta_ctx: pointer to hdd station context
3721 * @idx: attribute index
3722 *
3723 * Return: Success(0) or reason code for failure
3724 */
3725static int32_t hdd_add_survey_info(struct sk_buff *skb,
3726 hdd_station_ctx_t *hdd_sta_ctx,
3727 int idx)
3728{
3729 struct nlattr *nla_attr;
3730
3731 nla_attr = nla_nest_start(skb, idx);
3732 if (!nla_attr)
3733 goto fail;
3734 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3735 hdd_sta_ctx->conn_info.freq) ||
3736 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3737 (hdd_sta_ctx->conn_info.noise + 100))) {
3738 hdd_err("put fail");
3739 goto fail;
3740 }
3741 nla_nest_end(skb, nla_attr);
3742 return 0;
3743fail:
3744 return -EINVAL;
3745}
3746
3747/**
3748 * hdd_add_link_standard_info() - add link info attribute
3749 * @skb: pointer to sk buff
3750 * @hdd_sta_ctx: pointer to hdd station context
3751 * @idx: attribute index
3752 *
3753 * Return: Success(0) or reason code for failure
3754 */
3755static int32_t
3756hdd_add_link_standard_info(struct sk_buff *skb,
3757 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3758{
3759 struct nlattr *nla_attr;
3760
3761 nla_attr = nla_nest_start(skb, idx);
3762 if (!nla_attr)
3763 goto fail;
3764 if (nla_put(skb,
3765 NL80211_ATTR_SSID,
3766 hdd_sta_ctx->conn_info.SSID.SSID.length,
3767 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3768 hdd_err("put fail");
3769 goto fail;
3770 }
3771 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3772 goto fail;
3773 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3774 goto fail;
3775 nla_nest_end(skb, nla_attr);
3776 return 0;
3777fail:
3778 return -EINVAL;
3779}
3780
3781/**
3782 * hdd_add_ap_standard_info() - add ap info attribute
3783 * @skb: pointer to sk buff
3784 * @hdd_sta_ctx: pointer to hdd station context
3785 * @idx: attribute index
3786 *
3787 * Return: Success(0) or reason code for failure
3788 */
3789static int32_t
3790hdd_add_ap_standard_info(struct sk_buff *skb,
3791 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3792{
3793 struct nlattr *nla_attr;
3794
3795 nla_attr = nla_nest_start(skb, idx);
3796 if (!nla_attr)
3797 goto fail;
3798 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3799 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3800 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3801 &hdd_sta_ctx->conn_info.vht_caps)) {
3802 hdd_err("put fail");
3803 goto fail;
3804 }
3805 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3806 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3807 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3808 &hdd_sta_ctx->conn_info.ht_caps)) {
3809 hdd_err("put fail");
3810 goto fail;
3811 }
3812 nla_nest_end(skb, nla_attr);
3813 return 0;
3814fail:
3815 return -EINVAL;
3816}
3817
3818/**
3819 * hdd_get_station_info() - send BSS information to supplicant
3820 * @hdd_ctx: pointer to hdd context
3821 * @adapter: pointer to adapter
3822 *
3823 * Return: 0 if success else error status
3824 */
3825static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3826 hdd_adapter_t *adapter)
3827{
3828 struct sk_buff *skb = NULL;
3829 uint8_t *tmp_hs20 = NULL;
3830 uint32_t nl_buf_len;
3831 hdd_station_ctx_t *hdd_sta_ctx;
3832
3833 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3834
3835 nl_buf_len = NLMSG_HDRLEN;
3836 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3837 sizeof(hdd_sta_ctx->conn_info.freq) +
3838 sizeof(hdd_sta_ctx->conn_info.noise) +
3839 sizeof(hdd_sta_ctx->conn_info.signal) +
3840 (sizeof(uint32_t) * 2) +
3841 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3842 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3843 sizeof(hdd_sta_ctx->conn_info.authType) +
3844 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3845 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3846 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3847 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3848 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3849 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3850 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3851 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3852 1);
3853 }
3854 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3855 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3856 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3857 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3858
3859
3860 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3861 if (!skb) {
3862 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3863 return -ENOMEM;
3864 }
3865
3866 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3867 LINK_INFO_STANDARD_NL80211_ATTR)) {
3868 hdd_err("put fail");
3869 goto fail;
3870 }
3871 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3872 AP_INFO_STANDARD_NL80211_ATTR)) {
3873 hdd_err("put fail");
3874 goto fail;
3875 }
3876 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3877 hdd_sta_ctx->conn_info.roam_count) ||
3878 nla_put_u32(skb, INFO_AKM,
3879 hdd_convert_auth_type(
3880 hdd_sta_ctx->conn_info.authType)) ||
3881 nla_put_u32(skb, WLAN802_11_MODE,
3882 hdd_convert_dot11mode(
3883 hdd_sta_ctx->conn_info.dot11Mode))) {
3884 hdd_err("put fail");
3885 goto fail;
3886 }
3887 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3888 if (nla_put(skb, HT_OPERATION,
3889 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3890 &hdd_sta_ctx->conn_info.ht_operation)) {
3891 hdd_err("put fail");
3892 goto fail;
3893 }
3894 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3895 if (nla_put(skb, VHT_OPERATION,
3896 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3897 &hdd_sta_ctx->conn_info.vht_operation)) {
3898 hdd_err("put fail");
3899 goto fail;
3900 }
3901 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3902 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3903 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3904 tmp_hs20 + 1)) {
3905 hdd_err("put fail");
3906 goto fail;
3907 }
3908
3909 return cfg80211_vendor_cmd_reply(skb);
3910fail:
3911 if (skb)
3912 kfree_skb(skb);
3913 return -EINVAL;
3914}
3915
3916/**
3917 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3918 * @wiphy: corestack handler
3919 * @wdev: wireless device
3920 * @data: data
3921 * @data_len: data length
3922 *
3923 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3924 * Validate cmd attributes and send the station info to upper layers.
3925 *
3926 * Return: Success(0) or reason code for failure
3927 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303928static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303929__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3930 struct wireless_dev *wdev,
3931 const void *data,
3932 int data_len)
3933{
3934 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3935 struct net_device *dev = wdev->netdev;
3936 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3937 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3938 int32_t status;
3939
3940 ENTER_DEV(dev);
3941 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3942 hdd_err("Command not allowed in FTM mode");
3943 status = -EPERM;
3944 goto out;
3945 }
3946
3947 status = wlan_hdd_validate_context(hdd_ctx);
3948 if (0 != status)
3949 goto out;
3950
3951
3952 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3953 data, data_len, NULL);
3954 if (status) {
3955 hdd_err("Invalid ATTR");
3956 goto out;
3957 }
3958
3959 /* Parse and fetch Command Type*/
3960 if (tb[STATION_INFO]) {
3961 status = hdd_get_station_info(hdd_ctx, adapter);
3962 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3963 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3964 } else {
3965 hdd_err("get station info cmd type failed");
3966 status = -EINVAL;
3967 goto out;
3968 }
3969 EXIT();
3970out:
3971 return status;
3972}
3973
3974/**
3975 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3976 * @wiphy: corestack handler
3977 * @wdev: wireless device
3978 * @data: data
3979 * @data_len: data length
3980 *
3981 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3982 * Validate cmd attributes and send the station info to upper layers.
3983 *
3984 * Return: Success(0) or reason code for failure
3985 */
3986static int32_t
3987hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3988 struct wireless_dev *wdev,
3989 const void *data,
3990 int data_len)
3991{
3992 int ret;
3993
3994 cds_ssr_protect(__func__);
3995 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3996 cds_ssr_unprotect(__func__);
3997
3998 return ret;
3999}
4000
4001/*
4002 * undef short names defined for get station command
4003 * used by __wlan_hdd_cfg80211_get_station_cmd()
4004 */
4005#undef STATION_INVALID
4006#undef STATION_INFO
4007#undef STATION_ASSOC_FAIL_REASON
4008#undef STATION_MAX
4009
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004010#ifdef WLAN_FEATURE_ROAM_OFFLOAD
4011/**
4012 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4013 * @wiphy: pointer to wireless wiphy structure.
4014 * @wdev: pointer to wireless_dev structure.
4015 * @data: Pointer to the Key data
4016 * @data_len:Length of the data passed
4017 *
4018 * This is called when wlan driver needs to save the keys received via
4019 * vendor specific command.
4020 *
4021 * Return: Return the Success or Failure code.
4022 */
4023static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4024 struct wireless_dev *wdev,
4025 const void *data, int data_len)
4026{
4027 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
4028 struct net_device *dev = wdev->netdev;
4029 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
4030 hdd_context_t *hdd_ctx_ptr;
4031 int status;
4032
Jeff Johnson1f61b612016-02-12 16:28:33 -08004033 ENTER_DEV(dev);
4034
Anurag Chouhan6d760662016-02-20 16:05:43 +05304035 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004036 hdd_err("Command not allowed in FTM mode");
4037 return -EPERM;
4038 }
4039
4040 if ((data == NULL) || (data_len == 0) ||
4041 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004042 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004043 return -EINVAL;
4044 }
4045
4046 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
4047 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07004048 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004049 return -EINVAL;
4050 }
4051
4052 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304053 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004054 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004055 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4056 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004057 true,
4058 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304059 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4060 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004061 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4062 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4063 return 0;
4064}
4065
4066/**
4067 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4068 * @wiphy: pointer to wireless wiphy structure.
4069 * @wdev: pointer to wireless_dev structure.
4070 * @data: Pointer to the Key data
4071 * @data_len:Length of the data passed
4072 *
4073 * This is called when wlan driver needs to save the keys received via
4074 * vendor specific command.
4075 *
4076 * Return: Return the Success or Failure code.
4077 */
4078static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4079 struct wireless_dev *wdev,
4080 const void *data, int data_len)
4081{
4082 int ret;
4083
4084 cds_ssr_protect(__func__);
4085 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4086 cds_ssr_unprotect(__func__);
4087
4088 return ret;
4089}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004090#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004091
4092static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4093 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4094 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4095 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004096 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004097};
4098
4099/**
4100 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4101 * @wiphy: pointer to wireless wiphy structure.
4102 * @wdev: pointer to wireless_dev structure.
4103 * @data: Pointer to the data to be passed via vendor interface
4104 * @data_len:Length of the data to be passed
4105 *
4106 * This is called when wlan driver needs to send wifi driver related info
4107 * (driver/fw version) to the user space application upon request.
4108 *
4109 * Return: Return the Success or Failure code.
4110 */
4111static int
4112__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4113 struct wireless_dev *wdev,
4114 const void *data, int data_len)
4115{
4116 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4117 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004118 tSirVersionString driver_version;
4119 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004120 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004121 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004122 struct sk_buff *reply_skb;
4123 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004124
Jeff Johnson1f61b612016-02-12 16:28:33 -08004125 ENTER_DEV(wdev->netdev);
4126
Anurag Chouhan6d760662016-02-20 16:05:43 +05304127 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004128 hdd_err("Command not allowed in FTM mode");
4129 return -EPERM;
4130 }
4131
4132 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304133 if (status)
4134 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004135
4136 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4137 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004138 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004139 return -EINVAL;
4140 }
4141
4142 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08004143 hdd_debug("Rcvd req for Driver version");
Ryan Hsu7ac88852016-04-28 10:20:34 -07004144 strlcpy(driver_version, QWLAN_VERSIONSTR,
4145 sizeof(driver_version));
4146 skb_len += strlen(driver_version) + 1;
4147 count++;
4148 }
4149
4150 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004151 hdd_debug("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004152 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4153 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004154 snprintf(firmware_version, sizeof(firmware_version),
4155 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
4156 skb_len += strlen(firmware_version) + 1;
4157 count++;
4158 }
4159
4160 if (count == 0) {
4161 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004162 return -EINVAL;
4163 }
4164
Ryan Hsu7ac88852016-04-28 10:20:34 -07004165 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4166 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4167
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004168 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004169 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004170 return -ENOMEM;
4171 }
4172
Ryan Hsu7ac88852016-04-28 10:20:34 -07004173 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4174 if (nla_put_string(reply_skb,
4175 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4176 driver_version))
4177 goto error_nla_fail;
4178 }
4179
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304180 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004181 if (nla_put_string(reply_skb,
4182 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4183 firmware_version))
4184 goto error_nla_fail;
4185 }
4186
4187 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4188 if (nla_put_u32(reply_skb,
4189 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4190 hdd_ctx->radio_index))
4191 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004192 }
4193
4194 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004195
4196error_nla_fail:
4197 hdd_err("nla put fail");
4198 kfree_skb(reply_skb);
4199 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004200}
4201
4202/**
4203 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4204 * @wiphy: pointer to wireless wiphy structure.
4205 * @wdev: pointer to wireless_dev structure.
4206 * @data: Pointer to the data to be passed via vendor interface
4207 * @data_len:Length of the data to be passed
4208 *
4209 * This is called when wlan driver needs to send wifi driver related info
4210 * (driver/fw version) to the user space application upon request.
4211 *
4212 * Return: Return the Success or Failure code.
4213 */
4214static int
4215wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4216 struct wireless_dev *wdev,
4217 const void *data, int data_len)
4218{
4219 int ret;
4220
4221 cds_ssr_protect(__func__);
4222 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4223 cds_ssr_unprotect(__func__);
4224
4225 return ret;
4226}
4227
4228/**
4229 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4230 * @wiphy: pointer to wireless wiphy structure.
4231 * @wdev: pointer to wireless_dev structure.
4232 * @data: Pointer to the data to be passed via vendor interface
4233 * @data_len:Length of the data to be passed
4234 *
4235 * This is called by userspace to know the supported logger features
4236 *
4237 * Return: Return the Success or Failure code.
4238 */
4239static int
4240__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4241 struct wireless_dev *wdev,
4242 const void *data, int data_len)
4243{
4244 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4245 int status;
4246 uint32_t features;
4247 struct sk_buff *reply_skb = NULL;
4248
Jeff Johnson1f61b612016-02-12 16:28:33 -08004249 ENTER_DEV(wdev->netdev);
4250
Anurag Chouhan6d760662016-02-20 16:05:43 +05304251 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004252 hdd_err("Command not allowed in FTM mode");
4253 return -EPERM;
4254 }
4255
4256 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304257 if (status)
4258 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004259
4260 features = 0;
4261
4262 if (hdd_is_memdump_supported())
4263 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4264 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4265 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4266 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4267
4268 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4269 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4270 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004271 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004272 return -ENOMEM;
4273 }
4274
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004275 hdd_debug("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004276 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4277 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004278 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004279 kfree_skb(reply_skb);
4280 return -EINVAL;
4281 }
4282
4283 return cfg80211_vendor_cmd_reply(reply_skb);
4284}
4285
4286/**
4287 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4288 * @wiphy: pointer to wireless wiphy structure.
4289 * @wdev: pointer to wireless_dev structure.
4290 * @data: Pointer to the data to be passed via vendor interface
4291 * @data_len:Length of the data to be passed
4292 *
4293 * This is called by userspace to know the supported logger features
4294 *
4295 * Return: Return the Success or Failure code.
4296 */
4297static int
4298wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4299 struct wireless_dev *wdev,
4300 const void *data, int data_len)
4301{
4302 int ret;
4303
4304 cds_ssr_protect(__func__);
4305 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4306 data, data_len);
4307 cds_ssr_unprotect(__func__);
4308
4309 return ret;
4310}
4311
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004312#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004313/**
4314 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304315 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004316 * @bssid: pointer to bssid of roamed AP.
4317 * @req_rsn_ie: Pointer to request RSN IE
4318 * @req_rsn_len: Length of the request RSN IE
4319 * @rsp_rsn_ie: Pointer to response RSN IE
4320 * @rsp_rsn_len: Length of the response RSN IE
4321 * @roam_info_ptr: Pointer to the roaming related information
4322 *
4323 * This is called when wlan driver needs to send the roaming and
4324 * authorization information after roaming.
4325 *
4326 * The information that would be sent is the request RSN IE, response
4327 * RSN IE and BSSID of the newly roamed AP.
4328 *
4329 * If the Authorized status is authenticated, then additional parameters
4330 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4331 * supplicant.
4332 *
4333 * The supplicant upon receiving this event would ignore the legacy
4334 * cfg80211_roamed call and use the entire information from this event.
4335 * The cfg80211_roamed should still co-exist since the kernel will
4336 * make use of the parameters even if the supplicant ignores it.
4337 *
4338 * Return: Return the Success or Failure code.
4339 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304340int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004341 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4342 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4343{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304344 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004345 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004346 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004347 ENTER();
4348
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304349 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004350 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004351
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004352 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004353 !roam_info_ptr->roamSynchInProgress)
4354 return 0;
4355
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004356 /*
4357 * The user space has issued a disconnect when roaming is in
4358 * progress. The disconnect should be honored gracefully.
4359 * If the roaming is complete and the roam event is sent
4360 * back to the user space, it will get confused as it is
4361 * expecting a disconnect event. So, do not send the event
4362 * and handle the disconnect later.
4363 */
4364 if (adapter->defer_disconnect) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004365 hdd_debug("LFR3:Do not send roam auth event");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004366 return 0;
4367 }
4368
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004369 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304370 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004371 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4372 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4373 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004374 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004375 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4376 GFP_KERNEL);
4377
4378 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004379 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004380 return -EINVAL;
4381 }
4382
4383 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4384 ETH_ALEN, bssid) ||
4385 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4386 req_rsn_len, req_rsn_ie) ||
4387 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4388 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004389 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004390 goto nla_put_failure;
4391 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004392 if (roam_info_ptr->synchAuthStatus ==
4393 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004394 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004395 if (nla_put_u8(skb,
4396 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4397 hdd_err("nla put fail");
4398 goto nla_put_failure;
4399 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004400 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4401 /* if FT or CCKM connection: dont send replay counter */
4402 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4403 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4404 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4405 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4406 nla_put(skb,
4407 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4408 SIR_REPLAY_CTR_LEN,
4409 roam_info_ptr->replay_ctr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004410 hdd_err("non FT/non CCKM connection");
4411 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08004412 goto nla_put_failure;
4413 }
4414 if (nla_put(skb,
4415 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4416 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4417 nla_put(skb,
4418 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4419 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4420 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004421 goto nla_put_failure;
4422 }
4423 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004424 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004425 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4426 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004427 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004428 goto nla_put_failure;
4429 }
4430 }
4431
Selvaraj, Sridhard1225e62017-03-17 12:56:58 +05304432 hdd_debug("Auth Status = %d Subnet Change Status = %d",
4433 roam_info_ptr->synchAuthStatus,
4434 roam_info_ptr->subnet_change_status);
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004435
4436 /*
4437 * Add subnet change status if subnet has changed
4438 * 0 = unchanged
4439 * 1 = changed
4440 * 2 = unknown
4441 */
4442 if (roam_info_ptr->subnet_change_status) {
4443 if (nla_put_u8(skb,
4444 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4445 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004446 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004447 goto nla_put_failure;
4448 }
4449 }
4450
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004451 cfg80211_vendor_event(skb, GFP_KERNEL);
4452 return 0;
4453
4454nla_put_failure:
4455 kfree_skb(skb);
4456 return -EINVAL;
4457}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004458#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004459
4460static const struct nla_policy
4461wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4462
4463 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4464 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4465 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304466 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304467 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4468 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004469 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4470 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4471 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4472 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4473 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304474 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004475};
4476
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004477/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304478 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4479 *
4480 * @adapter: Pointer to HDD adapter
4481 * @ie_data: Pointer to Scan IEs buffer
4482 * @ie_len: Length of Scan IEs
4483 *
4484 * Return: 0 on success; error number otherwise
4485 */
4486static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
4487 uint8_t *ie_data, uint8_t ie_len)
4488{
4489 hdd_scaninfo_t *scan_info = NULL;
4490 scan_info = &adapter->scan_info;
4491
4492 if (scan_info->default_scan_ies) {
4493 qdf_mem_free(scan_info->default_scan_ies);
4494 scan_info->default_scan_ies = NULL;
4495 }
4496
4497 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
4498 if (!scan_info->default_scan_ies)
4499 return -ENOMEM;
4500
4501 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
4502 scan_info->default_scan_ies_len = ie_len;
4503 return 0;
4504}
4505
4506/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004507 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4508 * vendor command
4509 *
4510 * @wiphy: wiphy device pointer
4511 * @wdev: wireless device pointer
4512 * @data: Vendor command data buffer
4513 * @data_len: Buffer length
4514 *
4515 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4516 *
4517 * Return: Error code.
4518 */
4519static int
4520__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4521 struct wireless_dev *wdev,
4522 const void *data,
4523 int data_len)
4524{
4525 struct net_device *dev = wdev->netdev;
4526 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4527 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4528 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4529 int ret_val = 0;
4530 u32 modulated_dtim;
4531 u16 stats_avg_factor;
4532 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304533 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004534 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004535 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304536 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304537 int attr_len;
4538 int access_policy = 0;
4539 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4540 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304541 uint16_t scan_ie_len = 0;
4542 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304543 struct sir_set_tx_rx_aggregation_size request;
4544 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004545 uint8_t retry, delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004546 uint32_t abs_delay;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004547 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304548 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304549
Jeff Johnson1f61b612016-02-12 16:28:33 -08004550 ENTER_DEV(dev);
4551
Anurag Chouhan6d760662016-02-20 16:05:43 +05304552 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004553 hdd_err("Command not allowed in FTM mode");
4554 return -EPERM;
4555 }
4556
4557 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304558 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004559 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004560
4561 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4562 data, data_len,
4563 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004564 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004565 return -EINVAL;
4566 }
4567
Krunal Sonie3531942016-04-12 17:43:53 -07004568 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4569 ftm_capab = nla_get_u32(tb[
4570 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4571 hdd_ctx->config->fine_time_meas_cap =
4572 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4573 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304574 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004575 hdd_ctx->config->fine_time_meas_cap);
Naveen Rawat5f040ba2017-03-06 12:20:25 -08004576 os_if_wifi_pos_set_ftm_cap(hdd_ctx->hdd_psoc,
4577 hdd_ctx->config->fine_time_meas_cap);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004578 hdd_debug("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
Krunal Sonie3531942016-04-12 17:43:53 -07004579 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4580 hdd_ctx->config->fine_time_meas_cap);
4581 }
4582
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004583 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4584 modulated_dtim = nla_get_u32(
4585 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4586
4587 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4588 adapter->sessionId,
4589 modulated_dtim);
4590
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304591 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004592 ret_val = -EPERM;
4593 }
4594
Kapil Gupta6213c012016-09-02 19:39:09 +05304595 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4596 qpower = nla_get_u8(
4597 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4598 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4599 ret_val = -EINVAL;
4600 }
4601
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004602 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4603 stats_avg_factor = nla_get_u16(
4604 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4605 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4606 adapter->sessionId,
4607 stats_avg_factor);
4608
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304609 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004610 ret_val = -EPERM;
4611 }
4612
4613
4614 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4615 guard_time = nla_get_u32(
4616 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4617 status = sme_configure_guard_time(hdd_ctx->hHal,
4618 adapter->sessionId,
4619 guard_time);
4620
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304621 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004622 ret_val = -EPERM;
4623 }
4624
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304625 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4626 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4627 attr_len = nla_len(
4628 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4629 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004630 hdd_err("Invalid value. attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304631 attr_len);
4632 return -EINVAL;
4633 }
4634
4635 nla_memcpy(&vendor_ie,
4636 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4637 attr_len);
4638 vendor_ie_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004639 hdd_debug("Access policy vendor ie present.attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304640 attr_len);
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304641 }
4642
4643 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4644 access_policy = (int) nla_get_u32(
4645 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4646 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4647 (access_policy >
4648 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004649 hdd_err("Invalid value. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304650 access_policy);
4651 return -EINVAL;
4652 }
4653 access_policy_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004654 hdd_debug("Access policy present. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304655 access_policy);
4656 }
4657
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004658 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4659 retry = nla_get_u8(tb[
4660 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4661 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4662 CFG_NON_AGG_RETRY_MAX : retry;
4663 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4664 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4665 retry, PDEV_CMD);
4666 }
4667
4668 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4669 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4670 retry = retry > CFG_AGG_RETRY_MAX ?
4671 CFG_AGG_RETRY_MAX : retry;
4672
4673 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4674 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4675 CFG_AGG_RETRY_MIN : retry;
4676 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4677 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4678 retry, PDEV_CMD);
4679 }
4680
4681 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4682 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4683 retry = retry > CFG_MGMT_RETRY_MAX ?
4684 CFG_MGMT_RETRY_MAX : retry;
4685 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4686 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4687 retry, PDEV_CMD);
4688 }
4689
4690 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4691 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4692 retry = retry > CFG_CTRL_RETRY_MAX ?
4693 CFG_CTRL_RETRY_MAX : retry;
4694 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4695 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4696 retry, PDEV_CMD);
4697 }
4698
4699 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4700 delay = nla_get_u8(tb[
4701 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4702 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4703 CFG_PROPAGATION_DELAY_MAX : delay;
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004704 abs_delay = delay + CFG_PROPAGATION_DELAY_BASE;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004705 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4706 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
Zhang Qiane9fd14b2017-03-08 11:29:00 +08004707 abs_delay, PDEV_CMD);
4708 }
4709
4710 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]) {
4711 abs_delay = nla_get_u8(tb[
4712 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY]);
4713 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4714 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4715 abs_delay, PDEV_CMD);
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004716 }
4717
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304718 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4719 tx_fail_count = nla_get_u32(
4720 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4721 if (tx_fail_count) {
4722 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4723 adapter->sessionId, tx_fail_count);
4724 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004725 hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304726 status);
4727 return -EINVAL;
4728 }
4729 }
4730 }
4731
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304732 if (vendor_ie_present && access_policy_present) {
4733 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4734 access_policy =
4735 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304736 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304737 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304738 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304739
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004740 hdd_debug("calling sme_update_access_policy_vendor_ie");
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304741 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4742 adapter->sessionId, &vendor_ie[0],
4743 access_policy);
4744 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004745 hdd_err("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304746 return -EINVAL;
4747 }
4748 }
4749
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304750 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4751 set_value = nla_get_u8(
4752 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004753 hdd_debug("set_value: %d", set_value);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304754 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4755 }
4756
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304757 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4758 scan_ie_len = nla_len(
4759 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004760 hdd_debug("Received default scan IE of len %d session %d device mode %d",
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304761 scan_ie_len, adapter->sessionId,
4762 adapter->device_mode);
4763 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4764 scan_ie = (uint8_t *) nla_data(tb
4765 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304766
4767 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4768 scan_ie_len))
4769 hdd_err("Failed to save default scan IEs");
4770
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304771 if (adapter->device_mode == QDF_STA_MODE) {
4772 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4773 adapter->sessionId, scan_ie,
4774 scan_ie_len);
4775 if (QDF_STATUS_SUCCESS != status)
4776 ret_val = -EPERM;
4777 }
4778 } else
4779 ret_val = -EPERM;
4780 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304781
4782 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4783 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4784 /* if one is specified, both must be specified */
4785 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4786 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4787 hdd_err("Both TX and RX MPDU Aggregation required");
4788 return -EINVAL;
4789 }
4790
4791 request.tx_aggregation_size = nla_get_u8(
4792 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4793 request.rx_aggregation_size = nla_get_u8(
4794 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4795 request.vdev_id = adapter->sessionId;
4796
4797 if (request.tx_aggregation_size >=
4798 CFG_TX_AGGREGATION_SIZE_MIN &&
4799 request.tx_aggregation_size <=
4800 CFG_TX_AGGREGATION_SIZE_MAX &&
4801 request.rx_aggregation_size >=
4802 CFG_RX_AGGREGATION_SIZE_MIN &&
4803 request.rx_aggregation_size <=
4804 CFG_RX_AGGREGATION_SIZE_MAX) {
4805 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4806 if (qdf_status != QDF_STATUS_SUCCESS) {
4807 hdd_err("failed to set aggr sizes err %d",
4808 qdf_status);
4809 ret_val = -EPERM;
4810 }
4811 } else {
4812 hdd_err("TX %d RX %d MPDU aggr size not in range",
4813 request.tx_aggregation_size,
4814 request.rx_aggregation_size);
4815 ret_val = -EINVAL;
4816 }
4817 }
4818
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304819 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4820 uint8_t ignore_assoc_disallowed;
4821
4822 ignore_assoc_disallowed
4823 = nla_get_u8(tb[
4824 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004825 hdd_debug("Set ignore_assoc_disallowed value - %d",
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304826 ignore_assoc_disallowed);
4827 if ((ignore_assoc_disallowed <
4828 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4829 (ignore_assoc_disallowed >
4830 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4831 return -EPERM;
4832
4833 sme_update_session_param(hdd_ctx->hHal,
4834 adapter->sessionId,
4835 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4836 ignore_assoc_disallowed);
4837 }
4838
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004839 return ret_val;
4840}
4841
4842/**
4843 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4844 * vendor command
4845 *
4846 * @wiphy: wiphy device pointer
4847 * @wdev: wireless device pointer
4848 * @data: Vendor command data buffer
4849 * @data_len: Buffer length
4850 *
4851 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4852 *
4853 * Return: EOK or other error codes.
4854 */
4855static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4856 struct wireless_dev *wdev,
4857 const void *data,
4858 int data_len)
4859{
4860 int ret;
4861
4862 cds_ssr_protect(__func__);
4863 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4864 data, data_len);
4865 cds_ssr_unprotect(__func__);
4866
4867 return ret;
4868}
4869
4870static const struct
4871nla_policy
4872qca_wlan_vendor_wifi_logger_start_policy
4873[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4874 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4875 = {.type = NLA_U32 },
4876 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4877 = {.type = NLA_U32 },
4878 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4879 = {.type = NLA_U32 },
4880};
4881
4882/**
4883 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4884 * or disable the collection of packet statistics from the firmware
4885 * @wiphy: WIPHY structure pointer
4886 * @wdev: Wireless device structure pointer
4887 * @data: Pointer to the data received
4888 * @data_len: Length of the data received
4889 *
4890 * This function enables or disables the collection of packet statistics from
4891 * the firmware
4892 *
4893 * Return: 0 on success and errno on failure
4894 */
4895static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4896 struct wireless_dev *wdev,
4897 const void *data,
4898 int data_len)
4899{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304900 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004901 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4902 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4903 struct sir_wifi_start_log start_log;
4904
Jeff Johnson1f61b612016-02-12 16:28:33 -08004905 ENTER_DEV(wdev->netdev);
4906
Anurag Chouhan6d760662016-02-20 16:05:43 +05304907 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004908 hdd_err("Command not allowed in FTM mode");
4909 return -EPERM;
4910 }
4911
4912 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304913 if (status)
4914 return status;
4915
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05304916 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
4917 hdd_err("Driver Modules are closed, can not start logger");
4918 return -EINVAL;
4919 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004920
4921 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4922 data, data_len,
4923 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004924 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004925 return -EINVAL;
4926 }
4927
4928 /* Parse and fetch ring id */
4929 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004930 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004931 return -EINVAL;
4932 }
4933 start_log.ring_id = nla_get_u32(
4934 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004935 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004936
4937 /* Parse and fetch verbose level */
4938 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004939 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004940 return -EINVAL;
4941 }
4942 start_log.verbose_level = nla_get_u32(
4943 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004944 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004945
4946 /* Parse and fetch flag */
4947 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004948 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004949 return -EINVAL;
4950 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304951 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004952 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004953 hdd_debug("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004954
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304955 /* size is buff size which can be set using iwpriv command*/
4956 start_log.size = 0;
Poddar, Siddarthab99a272017-04-10 12:53:26 +05304957 start_log.is_pktlog_buff_clear = false;
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304958
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004959 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4960
4961 if (start_log.ring_id == RING_ID_WAKELOCK) {
4962 /* Start/stop wakelock events */
4963 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4964 cds_set_wakelock_logging(true);
4965 else
4966 cds_set_wakelock_logging(false);
4967 return 0;
4968 }
4969
4970 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304971 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004972 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004973 status);
4974 return -EINVAL;
4975 }
4976 return 0;
4977}
4978
4979/**
4980 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4981 * or disable the collection of packet statistics from the firmware
4982 * @wiphy: WIPHY structure pointer
4983 * @wdev: Wireless device structure pointer
4984 * @data: Pointer to the data received
4985 * @data_len: Length of the data received
4986 *
4987 * This function is used to enable or disable the collection of packet
4988 * statistics from the firmware
4989 *
4990 * Return: 0 on success and errno on failure
4991 */
4992static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4993 struct wireless_dev *wdev,
4994 const void *data,
4995 int data_len)
4996{
4997 int ret = 0;
4998
4999 cds_ssr_protect(__func__);
5000 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
5001 wdev, data, data_len);
5002 cds_ssr_unprotect(__func__);
5003
5004 return ret;
5005}
5006
5007static const struct
5008nla_policy
5009qca_wlan_vendor_wifi_logger_get_ring_data_policy
5010[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
5011 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
5012 = {.type = NLA_U32 },
5013};
5014
5015/**
5016 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
5017 * @wiphy: WIPHY structure pointer
5018 * @wdev: Wireless device structure pointer
5019 * @data: Pointer to the data received
5020 * @data_len: Length of the data received
5021 *
5022 * This function is used to flush or retrieve the per packet statistics from
5023 * the driver
5024 *
5025 * Return: 0 on success and errno on failure
5026 */
5027static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5028 struct wireless_dev *wdev,
5029 const void *data,
5030 int data_len)
5031{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305032 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005033 uint32_t ring_id;
5034 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5035 struct nlattr *tb
5036 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
5037
Jeff Johnson1f61b612016-02-12 16:28:33 -08005038 ENTER_DEV(wdev->netdev);
5039
Anurag Chouhan6d760662016-02-20 16:05:43 +05305040 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005041 hdd_err("Command not allowed in FTM mode");
5042 return -EPERM;
5043 }
5044
5045 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305046 if (status)
5047 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005048
5049 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5050 data, data_len,
5051 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005052 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005053 return -EINVAL;
5054 }
5055
5056 /* Parse and fetch ring id */
5057 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005058 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005059 return -EINVAL;
5060 }
5061
5062 ring_id = nla_get_u32(
5063 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5064
5065 if (ring_id == RING_ID_PER_PACKET_STATS) {
5066 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005067 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305068 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5069 /*
5070 * As part of DRIVER ring ID, flush both driver and fw logs.
5071 * For other Ring ID's driver doesn't have any rings to flush
5072 */
5073 hdd_notice("Bug report triggered by framework");
5074
5075 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5076 WLAN_LOG_INDICATOR_FRAMEWORK,
5077 WLAN_LOG_REASON_CODE_UNUSED,
5078 true, false);
5079 if (QDF_STATUS_SUCCESS != status) {
5080 hdd_err("Failed to trigger bug report");
5081 return -EINVAL;
5082 }
5083 } else {
5084 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5085 WLAN_LOG_INDICATOR_FRAMEWORK,
5086 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005087 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005088 return 0;
5089}
5090
5091/**
5092 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5093 * @wiphy: WIPHY structure pointer
5094 * @wdev: Wireless device structure pointer
5095 * @data: Pointer to the data received
5096 * @data_len: Length of the data received
5097 *
5098 * This function is used to flush or retrieve the per packet statistics from
5099 * the driver
5100 *
5101 * Return: 0 on success and errno on failure
5102 */
5103static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5104 struct wireless_dev *wdev,
5105 const void *data,
5106 int data_len)
5107{
5108 int ret = 0;
5109
5110 cds_ssr_protect(__func__);
5111 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5112 wdev, data, data_len);
5113 cds_ssr_unprotect(__func__);
5114
5115 return ret;
5116}
5117
5118#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5119/**
5120 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5121 * @hdd_ctx: HDD context
5122 * @request_id: [input] request id
5123 * @pattern_id: [output] pattern id
5124 *
5125 * This function loops through request id to pattern id array
5126 * if the slot is available, store the request id and return pattern id
5127 * if entry exists, return the pattern id
5128 *
5129 * Return: 0 on success and errno on failure
5130 */
5131static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5132 uint32_t request_id,
5133 uint8_t *pattern_id)
5134{
5135 uint32_t i;
5136
5137 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5138 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5139 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5140 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5141 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5142 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5143 return 0;
5144 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5145 request_id) {
5146 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5147 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5148 return 0;
5149 }
5150 }
5151 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5152 return -EINVAL;
5153}
5154
5155/**
5156 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5157 * @hdd_ctx: HDD context
5158 * @request_id: [input] request id
5159 * @pattern_id: [output] pattern id
5160 *
5161 * This function loops through request id to pattern id array
5162 * reset request id to 0 (slot available again) and
5163 * return pattern id
5164 *
5165 * Return: 0 on success and errno on failure
5166 */
5167static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5168 uint32_t request_id,
5169 uint8_t *pattern_id)
5170{
5171 uint32_t i;
5172
5173 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5174 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5175 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5176 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5177 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5178 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5179 return 0;
5180 }
5181 }
5182 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5183 return -EINVAL;
5184}
5185
5186
5187/*
5188 * define short names for the global vendor params
5189 * used by __wlan_hdd_cfg80211_offloaded_packets()
5190 */
5191#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5192#define PARAM_REQUEST_ID \
5193 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5194#define PARAM_CONTROL \
5195 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5196#define PARAM_IP_PACKET \
5197 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5198#define PARAM_SRC_MAC_ADDR \
5199 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5200#define PARAM_DST_MAC_ADDR \
5201 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5202#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5203
5204/**
5205 * wlan_hdd_add_tx_ptrn() - add tx pattern
5206 * @adapter: adapter pointer
5207 * @hdd_ctx: hdd context
5208 * @tb: nl attributes
5209 *
5210 * This function reads the NL attributes and forms a AddTxPtrn message
5211 * posts it to SME.
5212 *
5213 */
5214static int
5215wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5216 struct nlattr **tb)
5217{
5218 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305219 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005220 uint32_t request_id, ret, len;
5221 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305222 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005223 uint16_t eth_type = htons(ETH_P_IP);
5224
5225 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005226 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005227 return -ENOTSUPP;
5228 }
5229
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305230 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005231 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005232 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005233 return -ENOMEM;
5234 }
5235
5236 /* Parse and fetch request Id */
5237 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005238 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005239 goto fail;
5240 }
5241
5242 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5243 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005244 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005245 return -EINVAL;
5246 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005247 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005248
5249 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005250 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005251 goto fail;
5252 }
5253 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005254 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005255 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005256 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005257 goto fail;
5258 }
5259
5260 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005261 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005262 goto fail;
5263 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005264 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305265 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005266 hdd_debug("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005267 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005268
Anurag Chouhanc5548422016-02-24 18:33:27 +05305269 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005270 &adapter->macAddressCurrent)) {
5271 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005272 goto fail;
5273 }
5274
5275 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005276 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005277 goto fail;
5278 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305279 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005280 hdd_debug("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005281 MAC_ADDR_ARRAY(dst_addr.bytes));
5282
5283 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005284 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005285 goto fail;
5286 }
5287 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005288 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005289
5290 if (add_req->ucPtrnSize < 0 ||
5291 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5292 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005293 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005294 add_req->ucPtrnSize);
5295 goto fail;
5296 }
5297
5298 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305299 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305300 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305301 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305302 QDF_MAC_ADDR_SIZE);
5303 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305304 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005305 len += 2;
5306
5307 /*
5308 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5309 * ------------------------------------------------------------
5310 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5311 * ------------------------------------------------------------
5312 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305313 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005314 nla_data(tb[PARAM_IP_PACKET]),
5315 add_req->ucPtrnSize);
5316 add_req->ucPtrnSize += len;
5317
5318 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5319 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005320 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005321 goto fail;
5322 }
5323 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005324 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005325
5326 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305327 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005328 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005329 goto fail;
5330 }
5331
5332 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305333 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005334 return 0;
5335
5336fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305337 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005338 return -EINVAL;
5339}
5340
5341/**
5342 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5343 * @adapter: adapter pointer
5344 * @hdd_ctx: hdd context
5345 * @tb: nl attributes
5346 *
5347 * This function reads the NL attributes and forms a DelTxPtrn message
5348 * posts it to SME.
5349 *
5350 */
5351static int
5352wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5353 struct nlattr **tb)
5354{
5355 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305356 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005357 uint32_t request_id, ret;
5358 uint8_t pattern_id = 0;
5359
5360 /* Parse and fetch request Id */
5361 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005362 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005363 return -EINVAL;
5364 }
5365 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5366 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005367 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005368 return -EINVAL;
5369 }
5370
5371 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5372 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005373 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005374 return -EINVAL;
5375 }
5376
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305377 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005378 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005379 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005380 return -ENOMEM;
5381 }
5382
Anurag Chouhanc5548422016-02-24 18:33:27 +05305383 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005384 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005385 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005386 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005387 request_id, del_req->ucPtrnId);
5388
5389 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305390 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005391 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005392 goto fail;
5393 }
5394
5395 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305396 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005397 return 0;
5398
5399fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305400 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005401 return -EINVAL;
5402}
5403
5404
5405/**
5406 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5407 * @wiphy: Pointer to wireless phy
5408 * @wdev: Pointer to wireless device
5409 * @data: Pointer to data
5410 * @data_len: Data length
5411 *
5412 * Return: 0 on success, negative errno on failure
5413 */
5414static int
5415__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5416 struct wireless_dev *wdev,
5417 const void *data,
5418 int data_len)
5419{
5420 struct net_device *dev = wdev->netdev;
5421 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5422 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5423 struct nlattr *tb[PARAM_MAX + 1];
5424 uint8_t control;
5425 int ret;
5426 static const struct nla_policy policy[PARAM_MAX + 1] = {
5427 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5428 [PARAM_CONTROL] = { .type = NLA_U32 },
5429 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305430 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005431 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305432 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005433 [PARAM_PERIOD] = { .type = NLA_U32 },
5434 };
5435
Jeff Johnson1f61b612016-02-12 16:28:33 -08005436 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005437
Anurag Chouhan6d760662016-02-20 16:05:43 +05305438 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005439 hdd_err("Command not allowed in FTM mode");
5440 return -EPERM;
5441 }
5442
5443 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305444 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005445 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005446
5447 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005448 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005449 return -ENOTSUPP;
5450 }
5451
5452 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005453 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005454 return -EINVAL;
5455 }
5456
5457 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005458 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005459 return -EINVAL;
5460 }
5461 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005462 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005463
5464 if (control == WLAN_START_OFFLOADED_PACKETS)
5465 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005466 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005467 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005468
5469 hdd_err("Invalid control: %d", control);
5470
5471 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005472}
5473
5474/*
5475 * done with short names for the global vendor params
5476 * used by __wlan_hdd_cfg80211_offloaded_packets()
5477 */
5478#undef PARAM_MAX
5479#undef PARAM_REQUEST_ID
5480#undef PARAM_CONTROL
5481#undef PARAM_IP_PACKET
5482#undef PARAM_SRC_MAC_ADDR
5483#undef PARAM_DST_MAC_ADDR
5484#undef PARAM_PERIOD
5485
5486/**
5487 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5488 * @wiphy: wiphy structure pointer
5489 * @wdev: Wireless device structure pointer
5490 * @data: Pointer to the data received
5491 * @data_len: Length of @data
5492 *
5493 * Return: 0 on success; errno on failure
5494 */
5495static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5496 struct wireless_dev *wdev,
5497 const void *data,
5498 int data_len)
5499{
5500 int ret = 0;
5501
5502 cds_ssr_protect(__func__);
5503 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5504 wdev, data, data_len);
5505 cds_ssr_unprotect(__func__);
5506
5507 return ret;
5508}
5509#endif
5510
5511/*
5512 * define short names for the global vendor params
5513 * used by __wlan_hdd_cfg80211_monitor_rssi()
5514 */
5515#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5516#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5517#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5518#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5519#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5520
5521/**
5522 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5523 * @wiphy: Pointer to wireless phy
5524 * @wdev: Pointer to wireless device
5525 * @data: Pointer to data
5526 * @data_len: Data length
5527 *
5528 * Return: 0 on success, negative errno on failure
5529 */
5530static int
5531__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5532 struct wireless_dev *wdev,
5533 const void *data,
5534 int data_len)
5535{
5536 struct net_device *dev = wdev->netdev;
5537 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5538 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5539 struct nlattr *tb[PARAM_MAX + 1];
5540 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305541 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005542 int ret;
5543 uint32_t control;
5544 static const struct nla_policy policy[PARAM_MAX + 1] = {
5545 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5546 [PARAM_CONTROL] = { .type = NLA_U32 },
5547 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5548 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5549 };
5550
Jeff Johnson1f61b612016-02-12 16:28:33 -08005551 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005552
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305553 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5554 hdd_err("invalid session id: %d", adapter->sessionId);
5555 return -EINVAL;
5556 }
5557
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005558 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305559 if (ret)
5560 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005561
5562 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005563 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005564 return -ENOTSUPP;
5565 }
5566
5567 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005568 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005569 return -EINVAL;
5570 }
5571
5572 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005573 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005574 return -EINVAL;
5575 }
5576
5577 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005578 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005579 return -EINVAL;
5580 }
5581
5582 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5583 req.session_id = adapter->sessionId;
5584 control = nla_get_u32(tb[PARAM_CONTROL]);
5585
5586 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5587 req.control = true;
5588 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005589 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005590 return -EINVAL;
5591 }
5592
5593 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005594 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005595 return -EINVAL;
5596 }
5597
5598 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5599 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5600
5601 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005602 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005603 req.min_rssi, req.max_rssi);
5604 return -EINVAL;
5605 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005606 hdd_debug("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005607 req.min_rssi, req.max_rssi);
5608
5609 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5610 req.control = false;
5611 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005612 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005613 return -EINVAL;
5614 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005615 hdd_debug("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005616 req.request_id, req.session_id, req.control);
5617
5618 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305619 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005620 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005621 return -EINVAL;
5622 }
5623
5624 return 0;
5625}
5626
5627/*
5628 * done with short names for the global vendor params
5629 * used by __wlan_hdd_cfg80211_monitor_rssi()
5630 */
5631#undef PARAM_MAX
5632#undef PARAM_CONTROL
5633#undef PARAM_REQUEST_ID
5634#undef PARAM_MAX_RSSI
5635#undef PARAM_MIN_RSSI
5636
5637/**
5638 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5639 * @wiphy: wiphy structure pointer
5640 * @wdev: Wireless device structure pointer
5641 * @data: Pointer to the data received
5642 * @data_len: Length of @data
5643 *
5644 * Return: 0 on success; errno on failure
5645 */
5646static int
5647wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5648 const void *data, int data_len)
5649{
5650 int ret;
5651
5652 cds_ssr_protect(__func__);
5653 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5654 cds_ssr_unprotect(__func__);
5655
5656 return ret;
5657}
5658
5659/**
5660 * hdd_rssi_threshold_breached() - rssi breached NL event
5661 * @hddctx: HDD context
5662 * @data: rssi breached event data
5663 *
5664 * This function reads the rssi breached event %data and fill in the skb with
5665 * NL attributes and send up the NL event.
5666 *
5667 * Return: none
5668 */
5669void hdd_rssi_threshold_breached(void *hddctx,
5670 struct rssi_breach_event *data)
5671{
5672 hdd_context_t *hdd_ctx = hddctx;
5673 struct sk_buff *skb;
5674
5675 ENTER();
5676
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305677 if (wlan_hdd_validate_context(hdd_ctx))
5678 return;
5679 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005680 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005681 return;
5682 }
5683
5684 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5685 NULL,
5686 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5687 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5688 GFP_KERNEL);
5689
5690 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005691 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005692 return;
5693 }
5694
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005695 hdd_debug("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005696 data->request_id, data->curr_rssi);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005697 hdd_debug("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005698 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5699
5700 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5701 data->request_id) ||
5702 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5703 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5704 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5705 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005706 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005707 goto fail;
5708 }
5709
5710 cfg80211_vendor_event(skb, GFP_KERNEL);
5711 return;
5712
5713fail:
5714 kfree_skb(skb);
5715 return;
5716}
5717
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305718static const struct nla_policy
5719ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5720 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5721};
5722
5723/**
5724 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5725 * @wiphy: Pointer to wireless phy
5726 * @wdev: Pointer to wireless device
5727 * @data: Pointer to data
5728 * @data_len: Length of @data
5729 *
5730 * Return: 0 on success, negative errno on failure
5731 */
5732static int
5733__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5734 struct wireless_dev *wdev,
5735 const void *data, int data_len)
5736{
5737 int status;
5738 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5739 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005740 struct net_device *dev = wdev->netdev;
5741 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305742
5743 ENTER_DEV(wdev->netdev);
5744
5745 status = wlan_hdd_validate_context(pHddCtx);
5746 if (0 != status)
5747 return status;
5748 if (!pHddCtx->config->fhostNSOffload) {
5749 hdd_err("ND Offload not supported");
5750 return -EINVAL;
5751 }
5752
5753 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5754 (struct nlattr *)data,
5755 data_len, ns_offload_set_policy)) {
5756 hdd_err("nla_parse failed");
5757 return -EINVAL;
5758 }
5759
5760 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5761 hdd_err("ND Offload flag attribute not present");
5762 return -EINVAL;
5763 }
5764
5765 pHddCtx->ns_offload_enable =
5766 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5767
Dustin Brownd8279d22016-09-07 14:52:57 -07005768 /* update ns offload in case it is already enabled/disabled */
Mukul Sharma3ba26b82017-01-12 21:59:41 +05305769 if (pHddCtx->ns_offload_enable)
5770 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
5771 else
5772 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07005773
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305774 return 0;
5775}
5776
5777/**
5778 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5779 * @wiphy: pointer to wireless wiphy structure.
5780 * @wdev: pointer to wireless_dev structure.
5781 * @data: Pointer to the data to be passed via vendor interface
5782 * @data_len:Length of the data to be passed
5783 *
5784 * Return: Return the Success or Failure code.
5785 */
5786static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5787 struct wireless_dev *wdev,
5788 const void *data, int data_len)
5789{
5790 int ret;
5791
5792 cds_ssr_protect(__func__);
5793 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5794 cds_ssr_unprotect(__func__);
5795
5796 return ret;
5797}
5798
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005799/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5800 * @wiphy: Pointer to wireless phy
5801 * @wdev: Pointer to wireless device
5802 * @data: Pointer to data
5803 * @data_len: Data length
5804 *
5805 * This function return the preferred frequency list generated by the policy
5806 * manager.
5807 *
5808 * Return: success or failure code
5809 */
5810static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5811 struct wireless_dev
5812 *wdev, const void *data,
5813 int data_len)
5814{
5815 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5816 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305817 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305818 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005819 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305820 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005821 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005822 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5823 struct sk_buff *reply_skb;
5824
Jeff Johnson1f61b612016-02-12 16:28:33 -08005825 ENTER_DEV(wdev->netdev);
5826
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005827 ret = wlan_hdd_validate_context(hdd_ctx);
5828 if (ret)
5829 return -EINVAL;
5830
5831 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5832 data, data_len, NULL)) {
5833 hdd_err("Invalid ATTR");
5834 return -EINVAL;
5835 }
5836
5837 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5838 hdd_err("attr interface type failed");
5839 return -EINVAL;
5840 }
5841
5842 intf_mode = nla_get_u32(tb
5843 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5844
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005845 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005846 hdd_err("Invalid interface type");
5847 return -EINVAL;
5848 }
5849
5850 hdd_debug("Userspace requested pref freq list");
5851
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005852 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc,
5853 intf_mode, pcl, &pcl_len,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305854 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305855 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005856 hdd_err("Get pcl failed");
5857 return -EINVAL;
5858 }
5859
5860 /* convert channel number to frequency */
5861 for (i = 0; i < pcl_len; i++) {
5862 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5863 freq_list[i] =
5864 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005865 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005866 else
5867 freq_list[i] =
5868 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005869 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005870 }
5871
5872 /* send the freq_list back to supplicant */
5873 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5874 sizeof(u32) *
5875 pcl_len +
5876 NLMSG_HDRLEN);
5877
5878 if (!reply_skb) {
5879 hdd_err("Allocate reply_skb failed");
5880 return -EINVAL;
5881 }
5882
5883 if (nla_put_u32(reply_skb,
5884 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5885 intf_mode) ||
5886 nla_put(reply_skb,
5887 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5888 sizeof(uint32_t) * pcl_len,
5889 freq_list)) {
5890 hdd_err("nla put fail");
5891 kfree_skb(reply_skb);
5892 return -EINVAL;
5893 }
5894
5895 return cfg80211_vendor_cmd_reply(reply_skb);
5896}
5897
5898/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5899 * @wiphy: Pointer to wireless phy
5900 * @wdev: Pointer to wireless device
5901 * @data: Pointer to data
5902 * @data_len: Data length
5903 *
5904 * This function return the preferred frequency list generated by the policy
5905 * manager.
5906 *
5907 * Return: success or failure code
5908 */
5909static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5910 struct wireless_dev
5911 *wdev, const void *data,
5912 int data_len)
5913{
5914 int ret = 0;
5915
5916 cds_ssr_protect(__func__);
5917 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5918 data, data_len);
5919 cds_ssr_unprotect(__func__);
5920
5921 return ret;
5922}
5923
5924/**
5925 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5926 * @wiphy: Pointer to wireless phy
5927 * @wdev: Pointer to wireless device
5928 * @data: Pointer to data
5929 * @data_len: Data length
5930 *
5931 * Return: 0 on success, negative errno on failure
5932 */
5933static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5934 struct wireless_dev *wdev,
5935 const void *data,
5936 int data_len)
5937{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305938 struct net_device *ndev = wdev->netdev;
5939 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005940 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5941 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005942 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005943 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5944 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005945
Jeff Johnson1f61b612016-02-12 16:28:33 -08005946 ENTER_DEV(ndev);
5947
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005948 ret = wlan_hdd_validate_context(hdd_ctx);
5949 if (ret)
5950 return ret;
5951
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005952 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5953 data, data_len, NULL)) {
5954 hdd_err("Invalid ATTR");
5955 return -EINVAL;
5956 }
5957
5958 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5959 hdd_err("attr interface type failed");
5960 return -EINVAL;
5961 }
5962
5963 intf_mode = nla_get_u32(tb
5964 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5965
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005966 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005967 hdd_err("Invalid interface type");
5968 return -EINVAL;
5969 }
5970
5971 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5972 hdd_err("attr probable freq failed");
5973 return -EINVAL;
5974 }
5975
5976 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5977 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5978
5979 /* check pcl table */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005980 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc, intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005981 channel_hint, HW_MODE_20_MHZ)) {
5982 hdd_err("Set channel hint failed due to concurrency check");
5983 return -EINVAL;
5984 }
5985
Krunal Soni09e55032016-06-07 10:06:55 -07005986 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5987 hdd_warn("Remain On Channel Pending");
5988
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005989 ret = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07005990 if (!QDF_IS_STATUS_SUCCESS(ret))
5991 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005992
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005993 ret = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
5994 adapter->sessionId, channel_hint,
Krunal Soni3091bcc2016-06-23 12:28:21 -07005995 SIR_UPDATE_REASON_SET_OPER_CHAN);
5996 if (QDF_STATUS_E_FAILURE == ret) {
5997 /* return in the failure case */
5998 hdd_err("ERROR: connections update failed!!");
5999 return -EINVAL;
6000 }
6001
6002 if (QDF_STATUS_SUCCESS == ret) {
6003 /*
6004 * Success is the only case for which we expect hw mode
6005 * change to take place, hence we need to wait.
6006 * For any other return value it should be a pass
6007 * through
6008 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08006009 ret = policy_mgr_wait_for_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07006010 if (!QDF_IS_STATUS_SUCCESS(ret)) {
6011 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006012 return -EINVAL;
6013 }
6014
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08006015 }
6016
6017 return 0;
6018}
6019
6020/**
6021 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6022 * @wiphy: Pointer to wireless phy
6023 * @wdev: Pointer to wireless device
6024 * @data: Pointer to data
6025 * @data_len: Data length
6026 *
6027 * Return: 0 on success, negative errno on failure
6028 */
6029static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6030 struct wireless_dev *wdev,
6031 const void *data,
6032 int data_len)
6033{
6034 int ret = 0;
6035
6036 cds_ssr_protect(__func__);
6037 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
6038 data, data_len);
6039 cds_ssr_unprotect(__func__);
6040
6041 return ret;
6042}
6043
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306044static const struct
6045nla_policy
6046qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
6047 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
6048};
6049
6050/**
6051 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6052 * @wiphy: WIPHY structure pointer
6053 * @wdev: Wireless device structure pointer
6054 * @data: Pointer to the data received
6055 * @data_len: Length of the data received
6056 *
6057 * This function is used to get link properties like nss, rate flags and
6058 * operating frequency for the active connection with the given peer.
6059 *
6060 * Return: 0 on success and errno on failure
6061 */
6062static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6063 struct wireless_dev *wdev,
6064 const void *data,
6065 int data_len)
6066{
6067 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6068 struct net_device *dev = wdev->netdev;
6069 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6070 hdd_station_ctx_t *hdd_sta_ctx;
6071 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306072 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306073 uint32_t sta_id;
6074 struct sk_buff *reply_skb;
6075 uint32_t rate_flags = 0;
6076 uint8_t nss;
6077 uint8_t final_rate_flags = 0;
6078 uint32_t freq;
6079
Jeff Johnson1f61b612016-02-12 16:28:33 -08006080 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306081
Anurag Chouhan6d760662016-02-20 16:05:43 +05306082 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306083 hdd_err("Command not allowed in FTM mode");
6084 return -EPERM;
6085 }
6086
6087 if (0 != wlan_hdd_validate_context(hdd_ctx))
6088 return -EINVAL;
6089
6090 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6091 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006092 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306093 return -EINVAL;
6094 }
6095
6096 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006097 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306098 adapter->device_mode);
6099 return -EINVAL;
6100 }
6101
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306102 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306103 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006104 hdd_debug("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306105 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6106
Krunal Sonib4326f22016-03-10 13:05:51 -08006107 if (adapter->device_mode == QDF_STA_MODE ||
6108 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306109 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6110 if ((hdd_sta_ctx->conn_info.connState !=
6111 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306112 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306113 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006114 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306115 MAC_ADDR_ARRAY(peer_mac));
6116 return -EINVAL;
6117 }
6118
6119 nss = hdd_sta_ctx->conn_info.nss;
6120 freq = cds_chan_to_freq(
6121 hdd_sta_ctx->conn_info.operationChannel);
6122 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006123 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6124 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306125
6126 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6127 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306128 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306129 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306130 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306131 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306132 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306133 break;
6134 }
6135
6136 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006137 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306138 MAC_ADDR_ARRAY(peer_mac));
6139 return -EINVAL;
6140 }
6141
6142 nss = adapter->aStaInfo[sta_id].nss;
6143 freq = cds_chan_to_freq(
6144 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6145 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6146 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006147 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306148 MAC_ADDR_ARRAY(peer_mac));
6149 return -EINVAL;
6150 }
6151
6152 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6153 if (rate_flags & eHAL_TX_RATE_VHT80) {
6154 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006155#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306156 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006157#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306158 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6159 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006160#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306161 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006162#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306163 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6164 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6165 } else if (rate_flags &
6166 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6167 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006168#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306169 if (rate_flags & eHAL_TX_RATE_HT40)
6170 final_rate_flags |=
6171 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006172#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306173 }
6174
6175 if (rate_flags & eHAL_TX_RATE_SGI) {
6176 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6177 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6178 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6179 }
6180 }
6181
6182 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6183 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6184
6185 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006186 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306187 return -EINVAL;
6188 }
6189
6190 if (nla_put_u8(reply_skb,
6191 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6192 nss) ||
6193 nla_put_u8(reply_skb,
6194 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6195 final_rate_flags) ||
6196 nla_put_u32(reply_skb,
6197 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6198 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006199 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306200 kfree_skb(reply_skb);
6201 return -EINVAL;
6202 }
6203
6204 return cfg80211_vendor_cmd_reply(reply_skb);
6205}
6206
6207/**
6208 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6209 * properties.
6210 * @wiphy: WIPHY structure pointer
6211 * @wdev: Wireless device structure pointer
6212 * @data: Pointer to the data received
6213 * @data_len: Length of the data received
6214 *
6215 * This function is used to get link properties like nss, rate flags and
6216 * operating frequency for the active connection with the given peer.
6217 *
6218 * Return: 0 on success and errno on failure
6219 */
6220static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6221 struct wireless_dev *wdev,
6222 const void *data,
6223 int data_len)
6224{
6225 int ret = 0;
6226
6227 cds_ssr_protect(__func__);
6228 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6229 wdev, data, data_len);
6230 cds_ssr_unprotect(__func__);
6231
6232 return ret;
6233}
6234
Peng Xu278d0122015-09-24 16:34:17 -07006235static const struct
6236nla_policy
6237qca_wlan_vendor_ota_test_policy
6238[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6239 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6240};
6241
6242/**
6243 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6244 * @wiphy: Pointer to wireless phy
6245 * @wdev: Pointer to wireless device
6246 * @data: Pointer to data
6247 * @data_len: Data length
6248 *
6249 * Return: 0 on success, negative errno on failure
6250 */
6251static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6252 struct wireless_dev *wdev,
6253 const void *data,
6254 int data_len)
6255{
6256 struct net_device *dev = wdev->netdev;
6257 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6258 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6259 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6260 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6261 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306262 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006263 uint32_t current_roam_state;
6264
Jeff Johnson1f61b612016-02-12 16:28:33 -08006265 ENTER_DEV(dev);
6266
Anurag Chouhan6d760662016-02-20 16:05:43 +05306267 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006268 hdd_err("Command not allowed in FTM mode");
6269 return -EPERM;
6270 }
6271
6272 if (0 != wlan_hdd_validate_context(hdd_ctx))
6273 return -EINVAL;
6274
6275 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6276 data, data_len,
6277 qca_wlan_vendor_ota_test_policy)) {
6278 hdd_err("invalid attr");
6279 return -EINVAL;
6280 }
6281
6282 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6283 hdd_err("attr ota test failed");
6284 return -EINVAL;
6285 }
6286
6287 ota_enable = nla_get_u8(
6288 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6289
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006290 hdd_debug(" OTA test enable = %d", ota_enable);
Peng Xu278d0122015-09-24 16:34:17 -07006291 if (ota_enable != 1) {
6292 hdd_err("Invalid value, only enable test mode is supported!");
6293 return -EINVAL;
6294 }
6295
6296 current_roam_state =
6297 sme_get_current_roam_state(hal, adapter->sessionId);
6298 status = sme_stop_roaming(hal, adapter->sessionId,
6299 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306300 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006301 hdd_err("Enable/Disable roaming failed");
6302 return -EINVAL;
6303 }
6304
6305 status = sme_ps_enable_disable(hal, adapter->sessionId,
6306 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306307 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006308 hdd_err("Enable/Disable power save failed");
6309 /* restore previous roaming setting */
6310 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6311 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6312 status = sme_start_roaming(hal, adapter->sessionId,
6313 eCsrHddIssued);
6314 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6315 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6316 status = sme_stop_roaming(hal, adapter->sessionId,
6317 eCsrHddIssued);
6318
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306319 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006320 hdd_err("Restoring roaming state failed");
6321
6322 return -EINVAL;
6323 }
6324
6325
6326 return 0;
6327}
6328
6329/**
6330 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6331 * @wiphy: Pointer to wireless phy
6332 * @wdev: Pointer to wireless device
6333 * @data: Pointer to data
6334 * @data_len: Data length
6335 *
6336 * Return: 0 on success, negative errno on failure
6337 */
6338static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6339 struct wireless_dev *wdev,
6340 const void *data,
6341 int data_len)
6342{
6343 int ret = 0;
6344
6345 cds_ssr_protect(__func__);
6346 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6347 cds_ssr_unprotect(__func__);
6348
6349 return ret;
6350}
6351
Peng Xu4d67c8f2015-10-16 16:02:26 -07006352/**
6353 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6354 * @wiphy: Pointer to wireless phy
6355 * @wdev: Pointer to wireless device
6356 * @data: Pointer to data
6357 * @data_len: Data length
6358 *
6359 * Return: 0 on success, negative errno on failure
6360 */
6361static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6362 struct wireless_dev *wdev,
6363 const void *data,
6364 int data_len)
6365{
6366 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6367 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006368 hdd_adapter_t *adapter;
6369 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006370 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6371 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006372 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006373
Jeff Johnson1f61b612016-02-12 16:28:33 -08006374 ENTER_DEV(dev);
6375
Peng Xu4d67c8f2015-10-16 16:02:26 -07006376 ret = wlan_hdd_validate_context(hdd_ctx);
6377 if (ret)
6378 return ret;
6379
6380 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6381
6382 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6383 data, data_len, NULL)) {
6384 hdd_err("Invalid ATTR");
6385 return -EINVAL;
6386 }
6387
6388 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6389 hdd_err("attr tx power scale failed");
6390 return -EINVAL;
6391 }
6392
6393 scale_value = nla_get_u8(tb
6394 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6395
6396 if (scale_value > MAX_TXPOWER_SCALE) {
6397 hdd_err("Invalid tx power scale level");
6398 return -EINVAL;
6399 }
6400
Peng Xu62c8c432016-05-09 15:23:02 -07006401 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006402
Peng Xu62c8c432016-05-09 15:23:02 -07006403 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006404 hdd_err("Set tx power scale failed");
6405 return -EINVAL;
6406 }
6407
6408 return 0;
6409}
6410
6411/**
6412 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6413 * @wiphy: Pointer to wireless phy
6414 * @wdev: Pointer to wireless device
6415 * @data: Pointer to data
6416 * @data_len: Data length
6417 *
6418 * Return: 0 on success, negative errno on failure
6419 */
6420static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6421 struct wireless_dev *wdev,
6422 const void *data,
6423 int data_len)
6424{
Peng Xu62c8c432016-05-09 15:23:02 -07006425 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006426
6427 cds_ssr_protect(__func__);
6428 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6429 data, data_len);
6430 cds_ssr_unprotect(__func__);
6431
6432 return ret;
6433}
6434
6435/**
6436 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6437 * @wiphy: Pointer to wireless phy
6438 * @wdev: Pointer to wireless device
6439 * @data: Pointer to data
6440 * @data_len: Data length
6441 *
6442 * Return: 0 on success, negative errno on failure
6443 */
6444static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6445 struct wireless_dev *wdev,
6446 const void *data,
6447 int data_len)
6448{
6449 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6450 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006451 hdd_adapter_t *adapter;
6452 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006453 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6454 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006455 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006456
Jeff Johnson1f61b612016-02-12 16:28:33 -08006457 ENTER_DEV(dev);
6458
Peng Xu4d67c8f2015-10-16 16:02:26 -07006459 ret = wlan_hdd_validate_context(hdd_ctx);
6460 if (ret)
6461 return ret;
6462
6463 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6464
6465 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6466 data, data_len, NULL)) {
6467 hdd_err("Invalid ATTR");
6468 return -EINVAL;
6469 }
6470
6471 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6472 hdd_err("attr tx power decrease db value failed");
6473 return -EINVAL;
6474 }
6475
6476 scale_value = nla_get_u8(tb
6477 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6478
Peng Xu62c8c432016-05-09 15:23:02 -07006479 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6480 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006481
Peng Xu62c8c432016-05-09 15:23:02 -07006482 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006483 hdd_err("Set tx power decrease db failed");
6484 return -EINVAL;
6485 }
6486
6487 return 0;
6488}
6489
6490/**
6491 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6492 * @wiphy: Pointer to wireless phy
6493 * @wdev: Pointer to wireless device
6494 * @data: Pointer to data
6495 * @data_len: Data length
6496 *
6497 * Return: 0 on success, negative errno on failure
6498 */
6499static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6500 struct wireless_dev *wdev,
6501 const void *data,
6502 int data_len)
6503{
Peng Xu62c8c432016-05-09 15:23:02 -07006504 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006505
6506 cds_ssr_protect(__func__);
6507 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6508 data, data_len);
6509 cds_ssr_unprotect(__func__);
6510
6511 return ret;
6512}
Peng Xu8fdaa492016-06-22 10:20:47 -07006513
6514/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306515 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6516 * @wiphy: Pointer to wireless phy
6517 * @wdev: Pointer to wireless device
6518 * @data: Pointer to data
6519 * @data_len: Data length
6520 *
6521 * Processes the conditional channel switch request and invokes the helper
6522 * APIs to process the channel switch request.
6523 *
6524 * Return: 0 on success, negative errno on failure
6525 */
6526static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6527 struct wireless_dev *wdev,
6528 const void *data,
6529 int data_len)
6530{
6531 int ret;
6532 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6533 struct net_device *dev = wdev->netdev;
6534 hdd_adapter_t *adapter;
6535 struct nlattr
6536 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6537 uint32_t freq_len, i;
6538 uint32_t *freq;
6539 uint8_t chans[QDF_MAX_NUM_CHAN];
6540
6541 ENTER_DEV(dev);
6542
6543 ret = wlan_hdd_validate_context(hdd_ctx);
6544 if (ret)
6545 return ret;
6546
6547 if (!hdd_ctx->config->enableDFSMasterCap) {
6548 hdd_err("DFS master capability is not present in the driver");
6549 return -EINVAL;
6550 }
6551
6552 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6553 hdd_err("Command not allowed in FTM mode");
6554 return -EPERM;
6555 }
6556
6557 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6558 if (adapter->device_mode != QDF_SAP_MODE) {
6559 hdd_err("Invalid device mode %d", adapter->device_mode);
6560 return -EINVAL;
6561 }
6562
6563 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6564 data, data_len, NULL)) {
6565 hdd_err("Invalid ATTR");
6566 return -EINVAL;
6567 }
6568
6569 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6570 hdd_err("Frequency list is missing");
6571 return -EINVAL;
6572 }
6573
6574 freq_len = nla_len(
6575 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6576 sizeof(uint32_t);
6577
6578 if (freq_len > QDF_MAX_NUM_CHAN) {
6579 hdd_err("insufficient space to hold channels");
6580 return -ENOMEM;
6581 }
6582
6583 hdd_debug("freq_len=%d", freq_len);
6584
6585 freq = nla_data(
6586 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6587
6588
6589 for (i = 0; i < freq_len; i++) {
6590 if (freq[i] == 0)
6591 chans[i] = 0;
6592 else
6593 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6594
6595 hdd_debug("freq[%d]=%d", i, freq[i]);
6596 }
6597
6598 /*
6599 * The input frequency list from user space is designed to be a
6600 * priority based frequency list. This is only to accommodate any
6601 * future request. But, current requirement is only to perform CAC
6602 * on a single channel. So, the first entry from the list is picked.
6603 *
6604 * If channel is zero, any channel in the available outdoor regulatory
6605 * domain will be selected.
6606 */
6607 ret = wlan_hdd_request_pre_cac(chans[0]);
6608 if (ret) {
6609 hdd_err("pre cac request failed with reason:%d", ret);
6610 return ret;
6611 }
6612
6613 return 0;
6614}
6615
6616/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006617 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6618 * @wiphy: Pointer to wireless phy
6619 * @wdev: Pointer to wireless device
6620 * @data: Pointer to data
6621 * @data_len: Data length
6622 *
6623 * This function is to process the p2p listen offload start vendor
6624 * command. It parses the input parameters and invoke WMA API to
6625 * send the command to firmware.
6626 *
6627 * Return: 0 on success, negative errno on failure
6628 */
6629static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6630 struct wireless_dev *wdev,
6631 const void *data,
6632 int data_len)
6633{
6634 int ret;
6635 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6636 struct net_device *dev = wdev->netdev;
6637 hdd_adapter_t *adapter;
6638 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6639 struct sir_p2p_lo_start params;
Peng Xu8fdaa492016-06-22 10:20:47 -07006640
6641 ENTER_DEV(dev);
6642
6643 ret = wlan_hdd_validate_context(hdd_ctx);
6644 if (ret)
6645 return ret;
6646
6647 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6648 hdd_err("Command not allowed in FTM mode");
6649 return -EPERM;
6650 }
6651
6652 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6653 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6654 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6655 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6656 hdd_err("Invalid device mode %d", adapter->device_mode);
6657 return -EINVAL;
6658 }
6659
6660 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6661 data, data_len, NULL)) {
6662 hdd_err("Invalid ATTR");
6663 return -EINVAL;
6664 }
6665
6666 memset(&params, 0, sizeof(params));
6667
6668 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6669 params.ctl_flags = 1; /* set to default value */
6670 else
6671 params.ctl_flags = nla_get_u32(tb
6672 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6673
6674 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6675 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6676 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6677 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6678 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6679 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6680 hdd_err("Attribute parsing failed");
6681 return -EINVAL;
6682 }
6683
6684 params.vdev_id = adapter->sessionId;
6685 params.freq = nla_get_u32(tb
6686 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6687 if ((params.freq != 2412) && (params.freq != 2437) &&
6688 (params.freq != 2462)) {
6689 hdd_err("Invalid listening channel: %d", params.freq);
6690 return -EINVAL;
6691 }
6692
6693 params.period = nla_get_u32(tb
6694 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6695 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6696 hdd_err("Invalid period: %d", params.period);
6697 return -EINVAL;
6698 }
6699
6700 params.interval = nla_get_u32(tb
6701 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6702 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6703 hdd_err("Invalid interval: %d", params.interval);
6704 return -EINVAL;
6705 }
6706
6707 params.count = nla_get_u32(tb
6708 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006709 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006710 hdd_err("Invalid count: %d", params.count);
6711 return -EINVAL;
6712 }
6713
6714 params.device_types = nla_data(tb
6715 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6716 if (params.device_types == NULL) {
6717 hdd_err("Invalid device types");
6718 return -EINVAL;
6719 }
6720
6721 params.dev_types_len = nla_len(tb
6722 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6723 if (params.dev_types_len < 8) {
6724 hdd_err("Invalid device type length: %d", params.dev_types_len);
6725 return -EINVAL;
6726 }
6727
6728 params.probe_resp_tmplt = nla_data(tb
6729 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6730 if (params.probe_resp_tmplt == NULL) {
6731 hdd_err("Invalid probe response template");
6732 return -EINVAL;
6733 }
6734
6735 params.probe_resp_len = nla_len(tb
6736 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6737 if (params.probe_resp_len == 0) {
6738 hdd_err("Invalid probe resp template length: %d",
6739 params.probe_resp_len);
6740 return -EINVAL;
6741 }
6742
6743 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6744 params.freq, params.period, params.interval, params.count);
6745
Wu Gao9a704f42017-03-10 18:42:11 +08006746 return wlan_hdd_listen_offload_start(adapter, &params);
Peng Xu8fdaa492016-06-22 10:20:47 -07006747}
6748
6749
6750/**
6751 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6752 * @wiphy: Pointer to wireless phy
6753 * @wdev: Pointer to wireless device
6754 * @data: Pointer to data
6755 * @data_len: Data length
6756 *
6757 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6758 * to process p2p listen offload start vendor command.
6759 *
6760 * Return: 0 on success, negative errno on failure
6761 */
6762static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6763 struct wireless_dev *wdev,
6764 const void *data,
6765 int data_len)
6766{
6767 int ret = 0;
6768
6769 cds_ssr_protect(__func__);
6770 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6771 data, data_len);
6772 cds_ssr_unprotect(__func__);
6773
6774 return ret;
6775}
6776
6777/**
6778 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6779 * @wiphy: Pointer to wireless phy
6780 * @wdev: Pointer to wireless device
6781 * @data: Pointer to data
6782 * @data_len: Data length
6783 *
6784 * This function is to process the p2p listen offload stop vendor
6785 * command. It invokes WMA API to send command to firmware.
6786 *
6787 * Return: 0 on success, negative errno on failure
6788 */
6789static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6790 struct wireless_dev *wdev,
6791 const void *data,
6792 int data_len)
6793{
Peng Xu8fdaa492016-06-22 10:20:47 -07006794 hdd_adapter_t *adapter;
6795 struct net_device *dev = wdev->netdev;
6796
6797 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6798 hdd_err("Command not allowed in FTM mode");
6799 return -EPERM;
6800 }
6801
6802 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6803 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6804 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6805 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6806 hdd_err("Invalid device mode");
6807 return -EINVAL;
6808 }
6809
Wu Gao9a704f42017-03-10 18:42:11 +08006810 return wlan_hdd_listen_offload_stop(adapter);
Peng Xu8fdaa492016-06-22 10:20:47 -07006811}
6812
6813/**
6814 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6815 * @wiphy: Pointer to wireless phy
6816 * @wdev: Pointer to wireless device
6817 * @data: Pointer to data
6818 * @data_len: Data length
6819 *
6820 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6821 * to process p2p listen offload stop vendor command.
6822 *
6823 * Return: 0 on success, negative errno on failure
6824 */
6825static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6826 struct wireless_dev *wdev,
6827 const void *data,
6828 int data_len)
6829{
6830 int ret = 0;
6831
6832 cds_ssr_protect(__func__);
6833 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6834 data, data_len);
6835 cds_ssr_unprotect(__func__);
6836
6837 return ret;
6838}
6839
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306840/**
6841 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6842 * @wiphy: Pointer to wireless phy
6843 * @wdev: Pointer to wireless device
6844 * @data: Pointer to data
6845 * @data_len: Data length
6846 *
6847 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6848 * to process the conditional channel switch request.
6849 *
6850 * Return: 0 on success, negative errno on failure
6851 */
6852static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6853 struct wireless_dev *wdev,
6854 const void *data,
6855 int data_len)
6856{
6857 int ret;
6858
6859 cds_ssr_protect(__func__);
6860 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6861 data, data_len);
6862 cds_ssr_unprotect(__func__);
6863
6864 return ret;
6865}
6866
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306867/*
6868 * define short names for the global vendor params
6869 * used by __wlan_hdd_cfg80211_bpf_offload()
6870 */
6871#define BPF_INVALID \
6872 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6873#define BPF_SET_RESET \
6874 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6875#define BPF_VERSION \
6876 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6877#define BPF_FILTER_ID \
6878 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6879#define BPF_PACKET_SIZE \
6880 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6881#define BPF_CURRENT_OFFSET \
6882 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6883#define BPF_PROGRAM \
6884 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6885#define BPF_MAX \
6886 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006887
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306888static const struct nla_policy
6889wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6890 [BPF_SET_RESET] = {.type = NLA_U32},
6891 [BPF_VERSION] = {.type = NLA_U32},
6892 [BPF_FILTER_ID] = {.type = NLA_U32},
6893 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6894 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6895 [BPF_PROGRAM] = {.type = NLA_U8},
6896};
6897
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006898struct bpf_offload_priv {
6899 struct sir_bpf_get_offload bpf_get_offload;
6900};
6901
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306902/**
6903 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006904 * @context: opaque context originally passed to SME. HDD always passes
6905 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306906 * @bpf_get_offload: struct for get offload
6907 *
6908 * This function receives the response/data from the lower layer and
6909 * checks to see if the thread is still waiting then post the results to
6910 * upper layer, if the request has timed out then ignore.
6911 *
6912 * Return: None
6913 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006914static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006915 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306916{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006917 struct hdd_request *request;
6918 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306919
6920 ENTER();
6921
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006922 request = hdd_request_get(context);
6923 if (!request) {
6924 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306925 return;
6926 }
6927
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006928 priv = hdd_request_priv(request);
6929 priv->bpf_get_offload = *data;
6930 hdd_request_complete(request);
6931 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306932}
6933
6934/**
6935 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6936 * @hdd_context: hdd_context
6937 * @bpf_get_offload: struct for get offload
6938 *
6939 * Return: 0 on success, error number otherwise.
6940 */
6941static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6942 struct sir_bpf_get_offload *bpf_get_offload)
6943{
6944 struct sk_buff *skb;
6945 uint32_t nl_buf_len;
6946
6947 ENTER();
6948
6949 nl_buf_len = NLMSG_HDRLEN;
6950 nl_buf_len +=
6951 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6952 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6953
6954 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6955 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006956 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306957 return -ENOMEM;
6958 }
6959
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006960 hdd_debug("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306961 bpf_get_offload->bpf_version,
6962 bpf_get_offload->max_bytes_for_bpf_inst);
6963
6964 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6965 bpf_get_offload->max_bytes_for_bpf_inst) ||
6966 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006967 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306968 goto nla_put_failure;
6969 }
6970
6971 cfg80211_vendor_cmd_reply(skb);
6972 EXIT();
6973 return 0;
6974
6975nla_put_failure:
6976 kfree_skb(skb);
6977 return -EINVAL;
6978}
6979
6980/**
6981 * hdd_get_bpf_offload - Get BPF offload Capabilities
6982 * @hdd_ctx: Hdd context
6983 *
6984 * Return: 0 on success, errno on failure
6985 */
6986static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6987{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306988 QDF_STATUS status;
6989 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006990 void *cookie;
6991 struct hdd_request *request;
6992 struct bpf_offload_priv *priv;
6993 static const struct hdd_request_params params = {
6994 .priv_size = sizeof(*priv),
6995 .timeout_ms = WLAN_WAIT_TIME_BPF,
6996 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306997
6998 ENTER();
6999
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007000 request = hdd_request_alloc(&params);
7001 if (!request) {
7002 hdd_err("Unable to allocate request");
7003 return -EINVAL;
7004 }
7005 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307006
Jeff Johnsona867e0c2017-01-26 13:43:51 -08007007 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
7008 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007009 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307010 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007011 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007012 ret = qdf_status_to_os_return(status);
7013 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307014 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007015 ret = hdd_request_wait_for_response(request);
7016 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07007017 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007018 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307019 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007020 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307021 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007022 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307023 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07007024 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307025
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007026cleanup:
7027 /*
7028 * either we never sent a request to SME, we sent a request to
7029 * SME and timed out, or we sent a request to SME, received a
7030 * response from SME, and posted the response to userspace.
7031 * regardless we are done with the request.
7032 */
7033 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307034 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007035
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307036 return ret;
7037}
7038
7039/**
7040 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7041 * @hdd_ctx: Hdd context
7042 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307043 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307044 *
7045 * Return: 0 on success; errno on failure
7046 */
7047static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7048 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307049 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307050{
7051 struct sir_bpf_set_offload *bpf_set_offload;
7052 QDF_STATUS status;
7053 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307054 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307055
7056 ENTER();
7057
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307058 if (adapter->device_mode == QDF_STA_MODE ||
7059 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7060 if (!hdd_conn_is_connected(
7061 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7062 hdd_err("Not in Connected state!");
7063 return -ENOTSUPP;
7064 }
7065 }
7066
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307067 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7068 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007069 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307070 return -ENOMEM;
7071 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307072
7073 /* Parse and fetch bpf packet size */
7074 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007075 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307076 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307077 goto fail;
7078 }
7079 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7080
7081 if (!bpf_set_offload->total_length) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007082 hdd_debug("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307083 goto post_sme;
7084 }
7085
7086 /* Parse and fetch bpf program */
7087 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007088 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307089 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307090 goto fail;
7091 }
7092
7093 prog_len = nla_len(tb[BPF_PROGRAM]);
7094 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307095
7096 if (bpf_set_offload->program == NULL) {
7097 hdd_err("qdf_mem_malloc failed for bpf offload program");
7098 ret = -ENOMEM;
7099 goto fail;
7100 }
7101
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307102 bpf_set_offload->current_length = prog_len;
7103 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307104 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307105
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007106 hdd_debug("BPF set instructions");
Srinivas Girigowdac06543c2017-03-09 15:10:03 -08007107 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307108 bpf_set_offload->program, prog_len);
7109
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307110 /* Parse and fetch filter Id */
7111 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007112 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307113 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307114 goto fail;
7115 }
7116 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7117
7118 /* Parse and fetch current offset */
7119 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007120 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307121 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307122 goto fail;
7123 }
7124 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7125
7126post_sme:
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007127 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 +05307128 bpf_set_offload->session_id,
7129 bpf_set_offload->version,
7130 bpf_set_offload->filter_id,
7131 bpf_set_offload->total_length,
7132 bpf_set_offload->current_length,
7133 bpf_set_offload->current_offset);
7134
7135 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7136 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007137 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307138 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307139 goto fail;
7140 }
7141 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307142
7143fail:
7144 if (bpf_set_offload->current_length)
7145 qdf_mem_free(bpf_set_offload->program);
7146 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307147 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307148}
7149
7150/**
7151 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7152 * @wiphy: wiphy structure pointer
7153 * @wdev: Wireless device structure pointer
7154 * @data: Pointer to the data received
7155 * @data_len: Length of @data
7156 *
7157 * Return: 0 on success; errno on failure
7158 */
7159static int
7160__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7161 struct wireless_dev *wdev,
7162 const void *data, int data_len)
7163{
7164 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7165 struct net_device *dev = wdev->netdev;
7166 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7167 struct nlattr *tb[BPF_MAX + 1];
7168 int ret_val, packet_filter_subcmd;
7169
7170 ENTER();
7171
7172 ret_val = wlan_hdd_validate_context(hdd_ctx);
7173 if (ret_val)
7174 return ret_val;
7175
7176 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007177 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307178 return -EINVAL;
7179 }
7180
7181 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007182 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307183 return -ENOTSUPP;
7184 }
7185
7186 if (nla_parse(tb, BPF_MAX, data, data_len,
7187 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007188 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307189 return -EINVAL;
7190 }
7191
7192 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007193 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307194 return -EINVAL;
7195 }
7196
7197 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7198
7199 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7200 return hdd_get_bpf_offload(hdd_ctx);
7201 else
7202 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307203 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307204}
7205
7206/**
7207 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7208 * @wiphy: wiphy structure pointer
7209 * @wdev: Wireless device structure pointer
7210 * @data: Pointer to the data received
7211 * @data_len: Length of @data
7212 *
7213 * Return: 0 on success; errno on failure
7214 */
7215
7216static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7217 struct wireless_dev *wdev,
7218 const void *data, int data_len)
7219{
7220 int ret;
7221
7222 cds_ssr_protect(__func__);
7223 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7224 cds_ssr_unprotect(__func__);
7225
7226 return ret;
7227}
7228
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307229/**
7230 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7231 * @pre_cac_adapter: AP adapter used for pre cac
7232 * @status: Status (true or false)
7233 * @handle: Global handle
7234 *
7235 * Sets the status of pre cac i.e., whether the pre cac is active or not
7236 *
7237 * Return: Zero on success, non-zero on failure
7238 */
7239static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7240 bool status, tHalHandle handle)
7241{
7242 QDF_STATUS ret;
7243
7244 ret = wlan_sap_set_pre_cac_status(
7245 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7246 if (QDF_IS_STATUS_ERROR(ret))
7247 return -EINVAL;
7248
7249 return 0;
7250}
7251
7252/**
7253 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7254 * @ap_adapter: AP adapter
7255 * @chan_before_pre_cac: Channel
7256 *
7257 * Saves the channel which the AP was beaconing on before moving to the pre
7258 * cac channel. If radar is detected on the pre cac channel, this saved
7259 * channel will be used for AP operations.
7260 *
7261 * Return: Zero on success, non-zero on failure
7262 */
7263static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7264 uint8_t chan_before_pre_cac)
7265{
7266 QDF_STATUS ret;
7267
7268 ret = wlan_sap_set_chan_before_pre_cac(
7269 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7270 if (QDF_IS_STATUS_ERROR(ret))
7271 return -EINVAL;
7272
7273 return 0;
7274}
7275
7276/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307277 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7278 * are in nol list from provided channel list
7279 * @adapter: AP adapter
7280 * @channel_count: channel count
7281 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307282 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307283 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307284 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307285static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7286 uint32_t *channel_count,
7287 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307288{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307289 uint8_t i, j;
7290 uint32_t nol_len = 0;
7291 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7292 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7293 uint32_t chan_count;
7294 bool found;
7295 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307296
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307297 if (!hdd_ctx) {
7298 hdd_err("hdd ctx not found");
7299 *channel_count = 0;
7300 return;
7301 }
7302
7303 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7304 hdd_err("invalid channel count %d", *channel_count);
7305 return;
7306 }
7307
7308 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7309 if (nol_len == 0)
7310 return;
7311
7312 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7313 chan_count = *channel_count;
7314 qdf_mem_zero(channel_list, chan_count);
7315 *channel_count = 0;
7316
7317 for (i = 0 ; i < chan_count; i++) {
7318 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7319 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7320 continue;
7321 found = false;
7322 for (j = 0; j < nol_len; j++) {
7323 if (tmp_chan_list[i] == nol[j]) {
7324 found = true;
7325 hdd_notice("skipped channel %d due to nol",
7326 nol[j]);
7327 break;
7328 }
7329 }
7330 if (!found) {
7331 channel_list[*channel_count] = tmp_chan_list[i];
7332 *channel_count = *channel_count + 1;
7333 }
7334 }
7335}
7336
7337int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7338 uint32_t *channel_count,
7339 uint8_t *channel_list)
7340{
7341 tsap_Config_t *sap_config;
7342
7343 sap_config = &adapter->sessionCtx.ap.sapConfig;
7344
7345 qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
7346 sap_config->acs_cfg.ch_list_count);
7347 *channel_count = sap_config->acs_cfg.ch_list_count;
7348 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
7349
7350 if (*channel_count == 0) {
7351 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307352 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307353 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307354
7355 return 0;
7356}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307357
7358/**
7359 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7360 * @hdd_ctx: HDD context
7361 * @ap_adapter: AP adapter
7362 * @channel: Channel requested by userspace
7363 * @pre_cac_chan: Pointer to the pre CAC channel
7364 *
7365 * Validates the channel provided by userspace. If user provided channel 0,
7366 * a valid outdoor channel must be selected from the regulatory channel.
7367 *
7368 * Return: Zero on success and non zero value on error
7369 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007370static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7371 hdd_adapter_t *ap_adapter,
7372 uint8_t channel,
7373 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307374{
7375 uint32_t i, j;
7376 QDF_STATUS status;
7377 int ret;
7378 uint8_t nol[QDF_MAX_NUM_CHAN];
7379 uint32_t nol_len = 0, weight_len = 0;
7380 bool found;
7381 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7382 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7383 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7384
7385 if (0 == channel) {
7386 /* Channel is not obtained from PCL because PCL may not have
7387 * the entire channel list. For example: if SAP is up on
7388 * channel 6 and PCL is queried for the next SAP interface,
7389 * if SCC is preferred, the PCL will contain only the channel
7390 * 6. But, we are in need of a DFS channel. So, going with the
7391 * first channel from the valid channel list.
7392 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007393 status = policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7394 channel_list, &len);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307395 if (QDF_IS_STATUS_ERROR(status)) {
7396 hdd_err("Failed to get channel list");
7397 return -EINVAL;
7398 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007399 policy_mgr_update_with_safe_channel_list(channel_list, &len,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307400 pcl_weights, weight_len);
7401 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7402 for (i = 0; i < len; i++) {
7403 found = false;
7404 for (j = 0; j < nol_len; j++) {
7405 if (channel_list[i] == nol[j]) {
7406 found = true;
7407 break;
7408 }
7409 }
7410 if (found)
7411 continue;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007412 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7413 channel_list[i])) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307414 *pre_cac_chan = channel_list[i];
7415 break;
7416 }
7417 }
7418 if (*pre_cac_chan == 0) {
7419 hdd_err("unable to find outdoor channel");
7420 return -EINVAL;
7421 }
7422 } else {
7423 /* Only when driver selects a channel, check is done for
7424 * unnsafe and NOL channels. When user provides a fixed channel
7425 * the user is expected to take care of this.
7426 */
7427 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007428 !wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307429 hdd_err("Invalid channel for pre cac:%d", channel);
7430 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307431 }
Jeff Johnson68755312017-02-10 11:46:55 -08007432
7433 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307434 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007435 hdd_debug("selected pre cac channel:%d", *pre_cac_chan);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307436 return 0;
7437}
7438
7439/**
7440 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7441 * @channel: Channel option provided by userspace
7442 *
7443 * Sets the driver to the required hardware mode and start an adapater for
7444 * pre CAC which will mimic an AP.
7445 *
7446 * Return: Zero on success, non-zero value on error
7447 */
7448int wlan_hdd_request_pre_cac(uint8_t channel)
7449{
Krunal Sonib37bb352016-12-20 14:12:21 -08007450 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307451 hdd_context_t *hdd_ctx;
7452 int ret;
7453 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7454 hdd_ap_ctx_t *hdd_ap_ctx;
7455 QDF_STATUS status;
7456 struct wiphy *wiphy;
7457 struct net_device *dev;
7458 struct cfg80211_chan_def chandef;
7459 enum nl80211_channel_type channel_type;
7460 uint32_t freq;
7461 struct ieee80211_channel *chan;
7462 tHalHandle handle;
7463 bool val;
7464
7465 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7466 if (0 != wlan_hdd_validate_context(hdd_ctx))
7467 return -EINVAL;
7468
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007469 if (policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) > 1) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307470 hdd_err("pre cac not allowed in concurrency");
7471 return -EINVAL;
7472 }
7473
7474 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7475 if (!ap_adapter) {
7476 hdd_err("unable to get SAP adapter");
7477 return -EINVAL;
7478 }
7479
7480 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7481 if (!handle) {
7482 hdd_err("Invalid handle");
7483 return -EINVAL;
7484 }
7485
7486 val = wlan_sap_is_pre_cac_active(handle);
7487 if (val) {
7488 hdd_err("pre cac is already in progress");
7489 return -EINVAL;
7490 }
7491
7492 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7493 if (!hdd_ap_ctx) {
7494 hdd_err("SAP context is NULL");
7495 return -EINVAL;
7496 }
7497
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007498 if (wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
7499 hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307500 hdd_err("SAP is already on DFS channel:%d",
7501 hdd_ap_ctx->operatingChannel);
7502 return -EINVAL;
7503 }
7504
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07007505 if (!WLAN_REG_IS_24GHZ_CH(hdd_ap_ctx->operatingChannel)) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307506 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7507 hdd_ap_ctx->operatingChannel);
7508 return -EINVAL;
7509 }
7510
Krunal Sonib37bb352016-12-20 14:12:21 -08007511 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7512 if (!mac_addr) {
7513 hdd_err("can't add virtual intf: Not getting valid mac addr");
7514 return -EINVAL;
7515 }
7516
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007517 hdd_debug("channel:%d", channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307518
7519 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7520 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007521 if (ret != 0) {
7522 hdd_err("can't validate pre-cac channel");
7523 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307524 }
7525
7526 hdd_debug("starting pre cac SAP adapter");
7527
7528 /* Starting a SAP adapter:
7529 * Instead of opening an adapter, we could just do a SME open session
7530 * for AP type. But, start BSS would still need an adapter.
7531 * So, this option is not taken.
7532 *
7533 * hdd open adapter is going to register this precac interface with
7534 * user space. This interface though exposed to user space will be in
7535 * DOWN state. Consideration was done to avoid this registration to the
7536 * user space. But, as part of SAP operations multiple events are sent
7537 * to user space. Some of these events received from unregistered
7538 * interface was causing crashes. So, retaining the registration.
7539 *
7540 * So, this interface would remain registered and will remain in DOWN
7541 * state for the CAC duration. We will add notes in the feature
7542 * announcement to not use this temporary interface for any activity
7543 * from user space.
7544 */
7545 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007546 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307547 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307548 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007549 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307550 }
7551
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307552 /*
7553 * This interface is internally created by the driver. So, no interface
7554 * up comes for this interface from user space and hence starting
7555 * the adapter internally.
7556 */
7557 if (hdd_start_adapter(pre_cac_adapter)) {
7558 hdd_err("error starting the pre cac adapter");
7559 goto close_pre_cac_adapter;
7560 }
7561
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307562 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7563
7564 wiphy = hdd_ctx->wiphy;
7565 dev = pre_cac_adapter->dev;
7566
7567 /* Since this is only a dummy interface lets us use the IEs from the
7568 * other active SAP interface. In regular scenarios, these IEs would
7569 * come from the user space entity
7570 */
7571 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7572 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7573 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7574 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307575 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307576 }
7577 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7578 ap_adapter->sessionCtx.ap.beacon,
7579 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7580 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7581 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7582 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7583 ap_adapter->sessionCtx.ap.sapConfig.authType;
7584
7585 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7586 * to operate on the same bandwidth as that of the 2.4GHz operations.
7587 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7588 */
7589 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7590 case CH_WIDTH_20MHZ:
7591 channel_type = NL80211_CHAN_HT20;
7592 break;
7593 case CH_WIDTH_40MHZ:
7594 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7595 ap_adapter->sessionCtx.ap.sapConfig.channel)
7596 channel_type = NL80211_CHAN_HT40PLUS;
7597 else
7598 channel_type = NL80211_CHAN_HT40MINUS;
7599 break;
7600 default:
7601 channel_type = NL80211_CHAN_NO_HT;
7602 break;
7603 }
7604
7605 freq = cds_chan_to_freq(pre_cac_chan);
7606 chan = __ieee80211_get_channel(wiphy, freq);
7607 if (!chan) {
7608 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307609 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307610 }
7611
7612 cfg80211_chandef_create(&chandef, chan, channel_type);
7613
7614 hdd_debug("orig width:%d channel_type:%d freq:%d",
7615 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7616 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007617 /*
7618 * Doing update after opening and starting pre-cac adapter will make
7619 * sure that driver won't do hardware mode change if there are any
7620 * initial hick-ups or issues in pre-cac adapter's configuration.
7621 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7622 * connection update should result in DBS mode
7623 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007624 status = policy_mgr_update_and_wait_for_connection_update(
7625 hdd_ctx->hdd_psoc,
Krunal Sonib37bb352016-12-20 14:12:21 -08007626 ap_adapter->sessionId,
7627 pre_cac_chan,
7628 SIR_UPDATE_REASON_PRE_CAC);
7629 if (QDF_IS_STATUS_ERROR(status)) {
7630 hdd_err("error in moving to DBS mode");
7631 goto stop_close_pre_cac_adapter;
7632 }
7633
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307634
7635 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7636 if (0 != ret) {
7637 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307638 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307639 }
7640
7641 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7642 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007643 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307644 if (QDF_IS_STATUS_ERROR(status)) {
7645 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307646 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307647 }
7648
7649 /*
7650 * The pre cac status is set here. But, it would not be reset explicitly
7651 * anywhere, since after the pre cac success/failure, the pre cac
7652 * adapter itself would be removed.
7653 */
7654 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7655 if (0 != ret) {
7656 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307657 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307658 }
7659
7660 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7661 hdd_ap_ctx->operatingChannel);
7662 if (0 != ret) {
7663 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307664 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307665 }
7666
7667 ap_adapter->pre_cac_chan = pre_cac_chan;
7668
7669 return 0;
7670
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307671stop_close_pre_cac_adapter:
7672 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307673 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7674 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307675close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307676 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007677release_intf_addr_and_return_failure:
7678 /*
7679 * Release the interface address as the adapter
7680 * failed to start, if you don't release then next
7681 * adapter which is trying to come wouldn't get valid
7682 * mac address. Remember we have limited pool of mac addresses
7683 */
7684 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307685 return -EINVAL;
7686}
7687
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307688static const struct nla_policy
7689wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7690 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7691};
7692
Agrawal Ashish65634612016-08-18 13:24:32 +05307693static const struct nla_policy
7694wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7695 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7696 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7697};
7698
7699/**
7700 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7701 * @wiphy: Pointer to wireless phy
7702 * @wdev: Pointer to wireless device
7703 * @data: Pointer to data
7704 * @data_len: Length of @data
7705 *
7706 * This function parses the incoming NL vendor command data attributes and
7707 * updates the SAP context about channel_hint and DFS mode.
7708 * If channel_hint is set, SAP will choose that channel
7709 * as operating channel.
7710 *
7711 * If DFS mode is enabled, driver will include DFS channels
7712 * in ACS else driver will skip DFS channels.
7713 *
7714 * Return: 0 on success, negative errno on failure
7715 */
7716static int
7717__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7718 struct wireless_dev *wdev,
7719 const void *data, int data_len)
7720{
7721 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7722 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7723 int ret;
7724 struct acs_dfs_policy *acs_policy;
7725 int mode = DFS_MODE_NONE;
7726 int channel_hint = 0;
7727
7728 ENTER_DEV(wdev->netdev);
7729
7730 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7731 hdd_err("Command not allowed in FTM mode");
7732 return -EINVAL;
7733 }
7734
7735 ret = wlan_hdd_validate_context(hdd_ctx);
7736 if (0 != ret)
7737 return ret;
7738
7739 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7740 data, data_len,
7741 wlan_hdd_set_acs_dfs_config_policy)) {
7742 hdd_err("invalid attr");
7743 return -EINVAL;
7744 }
7745
7746 acs_policy = &hdd_ctx->acs_policy;
7747 /*
7748 * SCM sends this attribute to restrict SAP from choosing
7749 * DFS channels from ACS.
7750 */
7751 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7752 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7753
7754 if (!IS_DFS_MODE_VALID(mode)) {
7755 hdd_err("attr acs dfs mode is not valid");
7756 return -EINVAL;
7757 }
7758 acs_policy->acs_dfs_mode = mode;
7759
7760 /*
7761 * SCM sends this attribute to provide an active channel,
7762 * to skip redundant ACS between drivers, and save driver start up time
7763 */
7764 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7765 channel_hint = nla_get_u8(
7766 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7767
7768 if (!IS_CHANNEL_VALID(channel_hint)) {
7769 hdd_err("acs channel is not valid");
7770 return -EINVAL;
7771 }
7772 acs_policy->acs_channel = channel_hint;
7773
7774 return 0;
7775}
7776
7777/**
7778 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7779 * @wiphy: wiphy structure pointer
7780 * @wdev: Wireless device structure pointer
7781 * @data: Pointer to the data received
7782 * @data_len: Length of @data
7783 *
7784 * This function parses the incoming NL vendor command data attributes and
7785 * updates the SAP context about channel_hint and DFS mode.
7786 *
7787 * Return: 0 on success; errno on failure
7788 */
7789static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7790 struct wireless_dev *wdev,
7791 const void *data, int data_len)
7792{
7793 int ret;
7794
7795 cds_ssr_protect(__func__);
7796 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7797 cds_ssr_unprotect(__func__);
7798
7799 return ret;
7800}
7801
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307802/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307803 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7804 * @mode : cfg80211 dfs mode
7805 *
7806 * Return: return csr sta roam dfs mode else return NONE
7807 */
7808static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7809 enum dfs_mode mode)
7810{
7811 switch (mode) {
7812 case DFS_MODE_ENABLE:
7813 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7814 break;
7815 case DFS_MODE_DISABLE:
7816 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7817 break;
7818 case DFS_MODE_DEPRIORITIZE:
7819 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7820 break;
7821 default:
7822 hdd_err("STA Roam policy dfs mode is NONE");
7823 return CSR_STA_ROAM_POLICY_NONE;
7824 }
7825}
7826
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307827/*
7828 * hdd_get_sap_operating_band: Get current operating channel
7829 * for sap.
7830 * @hdd_ctx: hdd context
7831 *
7832 * Return : Corresponding band for SAP operating channel
7833 */
7834uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
7835{
7836 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7837 QDF_STATUS status;
7838 hdd_adapter_t *adapter;
7839 uint8_t operating_channel = 0;
7840 uint8_t sap_operating_band = 0;
7841 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7842 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7843 adapter = adapter_node->pAdapter;
7844
7845 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
7846 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7847 &next);
7848 adapter_node = next;
7849 continue;
7850 }
7851 operating_channel = adapter->sessionCtx.ap.operatingChannel;
7852 if (IS_24G_CH(operating_channel))
7853 sap_operating_band = eCSR_BAND_24;
7854 else if (IS_5G_CH(operating_channel))
7855 sap_operating_band = eCSR_BAND_5G;
7856 else
7857 sap_operating_band = eCSR_BAND_ALL;
7858 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7859 &next);
bings373b99b2017-01-23 10:35:08 +08007860 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307861 }
7862 return sap_operating_band;
7863}
7864
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307865static const struct nla_policy
7866wlan_hdd_set_sta_roam_config_policy[
7867QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7868 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7869 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7870};
7871
7872/**
7873 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7874 * for station connection or roaming.
7875 * @wiphy: Pointer to wireless phy
7876 * @wdev: Pointer to wireless device
7877 * @data: Pointer to data
7878 * @data_len: Length of @data
7879 *
7880 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7881 * channels needs to be skipped in scanning or not.
7882 * If dfs_mode is disabled, driver will not scan DFS channels.
7883 * If skip_unsafe_channels is set, driver will skip unsafe channels
7884 * in Scanning.
7885 *
7886 * Return: 0 on success, negative errno on failure
7887 */
7888static int
7889__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7890 struct wireless_dev *wdev,
7891 const void *data, int data_len)
7892{
7893 struct net_device *dev = wdev->netdev;
7894 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7895 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7896 struct nlattr *tb[
7897 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7898 int ret;
7899 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7900 enum dfs_mode mode = DFS_MODE_NONE;
7901 bool skip_unsafe_channels = false;
7902 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307903 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307904
7905 ENTER_DEV(dev);
7906
7907 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7908 hdd_err("Command not allowed in FTM mode");
7909 return -EINVAL;
7910 }
7911
7912 ret = wlan_hdd_validate_context(hdd_ctx);
7913 if (0 != ret)
7914 return ret;
7915 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7916 data, data_len,
7917 wlan_hdd_set_sta_roam_config_policy)) {
7918 hdd_err("invalid attr");
7919 return -EINVAL;
7920 }
7921 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7922 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7923 if (!IS_DFS_MODE_VALID(mode)) {
7924 hdd_err("attr sta roam dfs mode policy is not valid");
7925 return -EINVAL;
7926 }
7927
7928 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7929
7930 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7931 skip_unsafe_channels = nla_get_u8(
7932 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307933 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307934 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307935 skip_unsafe_channels, adapter->sessionId,
7936 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307937
7938 if (!QDF_IS_STATUS_SUCCESS(status)) {
7939 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7940 return -EINVAL;
7941 }
7942 return 0;
7943}
7944
7945/**
7946 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7947 * connection and roaming for station.
7948 * @wiphy: wiphy structure pointer
7949 * @wdev: Wireless device structure pointer
7950 * @data: Pointer to the data received
7951 * @data_len: Length of @data
7952 *
7953 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7954 * channels needs to be skipped in scanning or not.
7955 * If dfs_mode is disabled, driver will not scan DFS channels.
7956 * If skip_unsafe_channels is set, driver will skip unsafe channels
7957 * in Scanning.
7958 * Return: 0 on success; errno on failure
7959 */
7960static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7961 struct wireless_dev *wdev,
7962 const void *data, int data_len)
7963{
7964 int ret;
7965
7966 cds_ssr_protect(__func__);
7967 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7968 cds_ssr_unprotect(__func__);
7969
7970 return ret;
7971}
7972
Agrawal Ashish467dde42016-09-08 18:44:22 +05307973#ifdef FEATURE_WLAN_CH_AVOID
7974/**
7975 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7976 * is on unsafe channel.
7977 * @wiphy: wiphy structure pointer
7978 * @wdev: Wireless device structure pointer
7979 * @data: Pointer to the data received
7980 * @data_len: Length of @data
7981 *
7982 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7983 * on any of unsafe channels.
7984 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7985 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7986 *
7987 * Return: 0 on success; errno on failure
7988 */
7989static int
7990__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7991 struct wireless_dev *wdev,
7992 const void *data, int data_len)
7993{
7994 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7995 int ret;
7996 uint16_t unsafe_channel_count;
7997 int unsafe_channel_index;
7998 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7999
8000 ENTER_DEV(wdev->netdev);
8001
8002 if (!qdf_ctx) {
8003 cds_err("qdf_ctx is NULL");
8004 return -EINVAL;
8005 }
8006
8007 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8008 hdd_err("Command not allowed in FTM mode");
8009 return -EINVAL;
8010 }
8011
8012 ret = wlan_hdd_validate_context(hdd_ctx);
8013 if (0 != ret)
8014 return ret;
8015 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
8016 &(hdd_ctx->unsafe_channel_count),
8017 sizeof(hdd_ctx->unsafe_channel_list));
8018
8019 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
8020 (uint16_t)NUM_CHANNELS);
8021 for (unsafe_channel_index = 0;
8022 unsafe_channel_index < unsafe_channel_count;
8023 unsafe_channel_index++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008024 hdd_debug("Channel %d is not safe",
Agrawal Ashish467dde42016-09-08 18:44:22 +05308025 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
8026 }
8027 hdd_unsafe_channel_restart_sap(hdd_ctx);
8028 return 0;
8029}
8030
8031/**
8032 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8033 * is on unsafe channel.
8034 * @wiphy: wiphy structure pointer
8035 * @wdev: Wireless device structure pointer
8036 * @data: Pointer to the data received
8037 * @data_len: Length of @data
8038 *
8039 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8040 * on any of unsafe channels.
8041 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8042 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8043 *
8044 * Return: 0 on success; errno on failure
8045 */
8046static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8047 struct wireless_dev *wdev,
8048 const void *data, int data_len)
8049{
8050 int ret;
8051
8052 cds_ssr_protect(__func__);
8053 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8054 cds_ssr_unprotect(__func__);
8055
8056 return ret;
8057}
8058
8059#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308060/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308061 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8062 * SAP is on unsafe channel.
8063 * @wiphy: wiphy structure pointer
8064 * @wdev: Wireless device structure pointer
8065 * @data: Pointer to the data received
8066 * @data_len: Length of @data
8067 *
8068 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8069 * driver.
8070 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8071 * will initiate restart of sap.
8072 *
8073 * Return: 0 on success; errno on failure
8074 */
8075static int
8076__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8077 struct wireless_dev *wdev,
8078 const void *data, int data_len)
8079{
8080 struct net_device *ndev = wdev->netdev;
8081 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8082 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8083 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8084 uint8_t config_channel = 0;
8085 hdd_ap_ctx_t *ap_ctx;
8086 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308087 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308088
8089 ENTER();
8090
8091 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008092 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308093 return -EINVAL;
8094 }
8095
8096 ret = wlan_hdd_validate_context(hdd_ctx);
8097 if (0 != ret)
8098 return -EINVAL;
8099
8100 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8101 data, data_len,
8102 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008103 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308104 return -EINVAL;
8105 }
8106
8107 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8108 if (!test_bit(SOFTAP_BSS_STARTED,
8109 &hostapd_adapter->event_flags)) {
8110 hdd_err("SAP is not started yet. Restart sap will be invalid");
8111 return -EINVAL;
8112 }
8113
8114 config_channel =
8115 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8116
8117 if (!((IS_24G_CH(config_channel)) ||
8118 (IS_5G_CH(config_channel)))) {
8119 hdd_err("Channel %d is not valid to restart SAP",
8120 config_channel);
8121 return -ENOTSUPP;
8122 }
8123
8124 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8125 ap_ctx->sapConfig.channel = config_channel;
8126 ap_ctx->sapConfig.ch_params.ch_width =
8127 ap_ctx->sapConfig.ch_width_orig;
8128
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -07008129 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev,
8130 ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308131 ap_ctx->sapConfig.sec_ch,
8132 &ap_ctx->sapConfig.ch_params);
8133
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008134 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308135 }
8136
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308137 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8138 uint32_t freq_len, i;
8139 uint32_t *freq;
8140 uint8_t chans[QDF_MAX_NUM_CHAN];
8141
8142 hdd_debug("setting mandatory freq/chan list");
8143
8144 freq_len = nla_len(
8145 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8146 sizeof(uint32_t);
8147
8148 if (freq_len > QDF_MAX_NUM_CHAN) {
8149 hdd_err("insufficient space to hold channels");
8150 return -ENOMEM;
8151 }
8152
8153 freq = nla_data(
8154 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8155
8156 hdd_debug("freq_len=%d", freq_len);
8157
8158 for (i = 0; i < freq_len; i++) {
8159 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8160 hdd_debug("freq[%d]=%d", i, freq[i]);
8161 }
8162
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008163 status = policy_mgr_set_sap_mandatory_channels(
8164 hdd_ctx->hdd_psoc, chans, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308165 if (QDF_IS_STATUS_ERROR(status))
8166 return -EINVAL;
8167 }
8168
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308169 return 0;
8170}
8171
8172/**
8173 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8174 * @wiphy: wiphy structure pointer
8175 * @wdev: Wireless device structure pointer
8176 * @data: Pointer to the data received
8177 * @data_len: Length of @data
8178 *
8179 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8180 * driver.
8181 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8182 * will initiate restart of sap.
8183 *
8184 * Return: 0 on success; errno on failure
8185 */
8186static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8187 struct wireless_dev *wdev,
8188 const void *data, int data_len)
8189{
8190 int ret;
8191
8192 cds_ssr_protect(__func__);
8193 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8194 wdev, data, data_len);
8195 cds_ssr_unprotect(__func__);
8196
8197 return ret;
8198}
8199
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308200#undef BPF_INVALID
8201#undef BPF_SET_RESET
8202#undef BPF_VERSION
8203#undef BPF_ID
8204#undef BPF_PACKET_SIZE
8205#undef BPF_CURRENT_OFFSET
8206#undef BPF_PROGRAM
8207#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308208
8209/**
8210 * define short names for the global vendor params
8211 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8212 */
8213#define PARAM_TOTAL_CMD_EVENT_WAKE \
8214 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8215#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8216 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8217#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8218 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8219#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8220 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8221#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8222 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8223#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8224 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8225#define PARAM_TOTAL_RX_DATA_WAKE \
8226 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8227#define PARAM_RX_UNICAST_CNT \
8228 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8229#define PARAM_RX_MULTICAST_CNT \
8230 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8231#define PARAM_RX_BROADCAST_CNT \
8232 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8233#define PARAM_ICMP_PKT \
8234 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8235#define PARAM_ICMP6_PKT \
8236 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8237#define PARAM_ICMP6_RA \
8238 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8239#define PARAM_ICMP6_NA \
8240 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8241#define PARAM_ICMP6_NS \
8242 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8243#define PARAM_ICMP4_RX_MULTICAST_CNT \
8244 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8245#define PARAM_ICMP6_RX_MULTICAST_CNT \
8246 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8247#define PARAM_OTHER_RX_MULTICAST_CNT \
8248 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308249#define PARAM_RSSI_BREACH_CNT \
8250 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8251#define PARAM_LOW_RSSI_CNT \
8252 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8253#define PARAM_GSCAN_CNT \
8254 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8255#define PARAM_PNO_COMPLETE_CNT \
8256 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8257#define PARAM_PNO_MATCH_CNT \
8258 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8259
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308260
8261
8262/**
8263 * hdd_send_wakelock_stats() - API to send wakelock stats
8264 * @ctx: context to be passed to callback
8265 * @data: data passed to callback
8266 *
8267 * This function is used to send wake lock stats to HAL layer
8268 *
8269 * Return: 0 on success, error number otherwise.
8270 */
8271static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8272 const struct sir_wake_lock_stats *data)
8273{
8274 struct sk_buff *skb;
8275 uint32_t nl_buf_len;
8276 uint32_t total_rx_data_wake, rx_multicast_cnt;
8277 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308278 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308279
8280 ENTER();
8281
8282 nl_buf_len = NLMSG_HDRLEN;
8283 nl_buf_len +=
8284 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8285 (NLMSG_HDRLEN + sizeof(uint32_t));
8286
8287 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8288
8289 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008290 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308291 return -ENOMEM;
8292 }
8293
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008294 hdd_debug("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308295 data->wow_ucast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008296 hdd_debug("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308297 data->wow_bcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008298 hdd_debug("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308299 data->wow_ipv4_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008300 hdd_debug("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308301 data->wow_ipv6_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008302 hdd_debug("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308303 data->wow_ipv6_mcast_ra_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008304 hdd_debug("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308305 data->wow_ipv6_mcast_ns_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008306 hdd_debug("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308307 data->wow_ipv6_mcast_na_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008308 hdd_debug("wow_icmpv4_count %d", data->wow_icmpv4_count);
8309 hdd_debug("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308310 data->wow_icmpv6_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008311 hdd_debug("wow_rssi_breach_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308312 data->wow_rssi_breach_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008313 hdd_debug("wow_low_rssi_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308314 data->wow_low_rssi_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008315 hdd_debug("wow_gscan_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308316 data->wow_gscan_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008317 hdd_debug("wow_pno_complete_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308318 data->wow_pno_complete_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008319 hdd_debug("wow_pno_match_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308320 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308321
8322 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308323 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308324
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308325 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308326 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308327
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308328 rx_multicast_cnt =
8329 data->wow_ipv4_mcast_wake_up_count +
8330 ipv6_rx_multicast_addr_cnt;
8331
8332 total_rx_data_wake =
8333 data->wow_ucast_wake_up_count +
8334 data->wow_bcast_wake_up_count +
8335 rx_multicast_cnt;
8336
8337 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8338 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8339 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8340 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8341 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8342 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8343 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8344 total_rx_data_wake) ||
8345 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8346 data->wow_ucast_wake_up_count) ||
8347 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8348 rx_multicast_cnt) ||
8349 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8350 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308351 nla_put_u32(skb, PARAM_ICMP_PKT,
8352 data->wow_icmpv4_count) ||
8353 nla_put_u32(skb, PARAM_ICMP6_PKT,
8354 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308355 nla_put_u32(skb, PARAM_ICMP6_RA,
8356 data->wow_ipv6_mcast_ra_stats) ||
8357 nla_put_u32(skb, PARAM_ICMP6_NA,
8358 data->wow_ipv6_mcast_na_stats) ||
8359 nla_put_u32(skb, PARAM_ICMP6_NS,
8360 data->wow_ipv6_mcast_ns_stats) ||
8361 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8362 data->wow_ipv4_mcast_wake_up_count) ||
8363 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8364 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308365 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8366 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8367 data->wow_rssi_breach_wake_up_count) ||
8368 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8369 data->wow_low_rssi_wake_up_count) ||
8370 nla_put_u32(skb, PARAM_GSCAN_CNT,
8371 data->wow_gscan_wake_up_count) ||
8372 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8373 data->wow_pno_complete_wake_up_count) ||
8374 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8375 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008376 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308377 goto nla_put_failure;
8378 }
8379
8380 cfg80211_vendor_cmd_reply(skb);
8381
8382 EXIT();
8383 return 0;
8384
8385nla_put_failure:
8386 kfree_skb(skb);
8387 return -EINVAL;
8388}
8389
8390/**
8391 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8392 * @wiphy: wiphy pointer
8393 * @wdev: pointer to struct wireless_dev
8394 * @data: pointer to incoming NL vendor data
8395 * @data_len: length of @data
8396 *
8397 * This function parses the incoming NL vendor command data attributes and
8398 * invokes the SME Api and blocks on a completion variable.
8399 * WMA copies required data and invokes callback
8400 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8401 *
8402 * Return: 0 on success; error number otherwise.
8403 */
8404static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8405 struct wireless_dev *wdev,
8406 const void *data,
8407 int data_len)
8408{
8409 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8410 int status, ret;
8411 struct sir_wake_lock_stats wake_lock_stats;
8412 QDF_STATUS qdf_status;
8413
8414 ENTER();
8415
8416 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008417 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308418 return -EINVAL;
8419 }
8420
8421 status = wlan_hdd_validate_context(hdd_ctx);
8422 if (0 != status)
8423 return -EINVAL;
8424
8425 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8426 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008427 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308428 return -EINVAL;
8429 }
8430
8431 ret = hdd_send_wakelock_stats(hdd_ctx,
8432 &wake_lock_stats);
8433 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008434 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308435
8436 EXIT();
8437 return ret;
8438}
8439
8440/**
8441 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8442 * @wiphy: wiphy pointer
8443 * @wdev: pointer to struct wireless_dev
8444 * @data: pointer to incoming NL vendor data
8445 * @data_len: length of @data
8446 *
8447 * This function parses the incoming NL vendor command data attributes and
8448 * invokes the SME Api and blocks on a completion variable.
8449 * WMA copies required data and invokes callback
8450 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8451 *
8452 * Return: 0 on success; error number otherwise.
8453 */
8454static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8455 struct wireless_dev *wdev,
8456 const void *data, int data_len)
8457{
8458 int ret;
8459
8460 cds_ssr_protect(__func__);
8461 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8462 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008463 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308464
8465 return ret;
8466}
8467
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308468/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308469 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8470 * @wiphy: wiphy structure pointer
8471 * @wdev: Wireless device structure pointer
8472 * @data: Pointer to the data received
8473 * @data_len: Length of @data
8474 *
8475 * This function reads wmi max bus size and fill in the skb with
8476 * NL attributes and send up the NL event.
8477 * Return: 0 on success; errno on failure
8478 */
8479static int
8480__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8481 struct wireless_dev *wdev,
8482 const void *data, int data_len)
8483{
8484 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8485 int ret_val;
8486 struct sk_buff *skb;
8487 uint32_t nl_buf_len;
8488
8489 ENTER();
8490
8491 ret_val = wlan_hdd_validate_context(hdd_ctx);
8492 if (ret_val)
8493 return ret_val;
8494
8495 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8496 hdd_err("Command not allowed in FTM mode");
8497 return -EINVAL;
8498 }
8499
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008500 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308501
8502 nl_buf_len = NLMSG_HDRLEN;
8503 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8504
8505 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8506 if (!skb) {
8507 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8508 return -ENOMEM;
8509 }
8510
8511 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8512 hdd_ctx->wmi_max_len)) {
8513 hdd_err("nla put failure");
8514 goto nla_put_failure;
8515 }
8516
8517 cfg80211_vendor_cmd_reply(skb);
8518
8519 EXIT();
8520
8521 return 0;
8522
8523nla_put_failure:
8524 kfree_skb(skb);
8525 return -EINVAL;
8526}
8527
8528/**
8529 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8530 * @wiphy: wiphy structure pointer
8531 * @wdev: Wireless device structure pointer
8532 * @data: Pointer to the data received
8533 * @data_len: Length of @data
8534 *
8535 * Return: 0 on success; errno on failure
8536 */
8537static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8538 struct wireless_dev *wdev,
8539 const void *data, int data_len)
8540{
8541 int ret;
8542
8543 cds_ssr_protect(__func__);
8544 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8545 cds_ssr_unprotect(__func__);
8546
8547 return ret;
8548}
8549
8550/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308551 *__wlan_hdd_cfg80211_setband() - set band
8552 * @wiphy: Pointer to wireless phy
8553 * @wdev: Pointer to wireless device
8554 * @data: Pointer to data
8555 * @data_len: Length of @data
8556 *
8557 * Return: 0 on success, negative errno on failure
8558 */
8559static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8560 struct wireless_dev *wdev,
8561 const void *data, int data_len)
8562{
8563 struct net_device *dev = wdev->netdev;
8564 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8565 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8566 int ret;
8567 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8568 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8569
8570 ENTER();
8571
8572 ret = wlan_hdd_validate_context(hdd_ctx);
8573 if (ret)
8574 return ret;
8575
8576 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8577 hdd_err(FL("Invalid ATTR"));
8578 return -EINVAL;
8579 }
8580
8581 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8582 hdd_err(FL("attr SETBAND_VALUE failed"));
8583 return -EINVAL;
8584 }
8585
8586 ret = hdd_set_band(dev,
8587 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
8588
8589 EXIT();
8590 return ret;
8591}
8592
8593/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308594 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8595 * @adapter: hdd adapter
8596 * @channel: channel number
8597 *
8598 * return: QDF status based on success or failure
8599 */
8600static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8601 int channel, int chan_bw)
8602{
8603 if (QDF_STATUS_SUCCESS !=
8604 wlan_hdd_validate_operation_channel(adapter, channel))
8605 return QDF_STATUS_E_FAILURE;
8606 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8607 channel,
8608 PHY_SINGLE_CHANNEL_CENTERED))) {
8609 hdd_notice("channel %d is in nol", channel);
8610 return -EINVAL;
8611 }
8612
8613 if ((wlansap_is_channel_leaking_in_nol(
8614 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8615 channel, chan_bw))) {
8616 hdd_notice("channel %d is leaking in nol", channel);
8617 return -EINVAL;
8618 }
8619
8620 return 0;
8621
8622}
8623
Kapil Gupta8878ad92017-02-13 11:56:04 +05308624static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8625 tsap_Config_t *sap_config,
8626 struct hdd_vendor_chan_info *channel_list)
8627{
8628 sap_config->channel = channel_list->pri_ch;
8629
8630 sap_config->ch_params.center_freq_seg0 =
8631 channel_list->vht_seg0_center_ch;
8632 sap_config->ch_params.center_freq_seg1 =
8633 channel_list->vht_seg1_center_ch;
8634
8635 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8636 sap_config->ch_params.ch_width = channel_list->chan_width;
8637 if (sap_config->channel >= 36)
8638 sap_config->ch_width_orig =
8639 hdd_ctx->config->vhtChannelWidth;
8640 else
8641 sap_config->ch_width_orig =
8642 hdd_ctx->config->nChannelBondingMode24GHz ?
8643 eHT_CHANNEL_WIDTH_40MHZ :
8644 eHT_CHANNEL_WIDTH_20MHZ;
8645
8646 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8647 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8648 sap_config->acs_cfg.vht_seg0_center_ch =
8649 channel_list->vht_seg0_center_ch;
8650 sap_config->acs_cfg.vht_seg1_center_ch =
8651 channel_list->vht_seg1_center_ch;
8652 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8653}
8654
8655static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8656 uint8_t channel_cnt,
8657 struct hdd_vendor_chan_info *channel_list)
8658{
8659 tsap_Config_t *sap_config;
8660 hdd_ap_ctx_t *hdd_ap_ctx;
8661 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8662 QDF_STATUS status = QDF_STATUS_SUCCESS;
8663
8664 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8665 sap_config = &adapter->sessionCtx.ap.sapConfig;
8666
8667 if (QDF_TIMER_STATE_RUNNING ==
8668 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8669 ap.vendor_acs_timer)) {
8670 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8671 }
8672
8673 if (channel_list && channel_list->pri_ch == 0) {
8674 /* Check mode, set default channel */
8675 channel_list->pri_ch = 6;
8676 /*
8677 * sap_select_default_oper_chan(hdd_ctx->hHal,
8678 * sap_config->acs_cfg.hw_mode);
8679 */
8680 }
8681
8682 switch (reason) {
8683 /* SAP init case */
8684 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8685 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8686 /* Update Hostapd */
8687 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8688 break;
8689
8690 /* DFS detected on current channel */
8691 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8692 wlan_sap_update_next_channel(
8693 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8694 channel_list->pri_ch,
8695 channel_list->chan_width);
8696 status = sme_update_new_channel_event(
8697 WLAN_HDD_GET_HAL_CTX(adapter),
8698 adapter->sessionId);
8699 break;
8700
8701 /* LTE coex event on current channel */
8702 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8703 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8704 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8705 hdd_ap_ctx->sapConfig.ch_width_orig =
8706 channel_list->chan_width;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008707 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +05308708 break;
8709
8710 default:
8711 hdd_info("invalid reason for timer invoke");
8712 }
8713 qdf_mem_free(channel_list);
8714 EXIT();
8715 return status;
8716}
8717
8718/**
8719 * Define short name for vendor channel set config
8720 */
8721#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8722#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8723#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8724#define SET_CHAN_PRIMARY_CHANNEL \
8725 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8726#define SET_CHAN_SECONDARY_CHANNEL \
8727 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8728#define SET_CHAN_SEG0_CENTER_CHANNEL \
8729 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8730#define SET_CHAN_SEG1_CENTER_CHANNEL \
8731 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8732#define SET_CHAN_CHANNEL_WIDTH \
8733 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8734#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8735
8736/**
8737 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8738 * @channel_list: pointer to hdd_vendor_chan_info
8739 * @reason: channel change reason
8740 * @channel_cnt: channel count
8741 * @data: data
8742 * @data_len: data len
8743 *
8744 * Return: 0 on success, negative errno on failure
8745 */
8746static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8747 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8748 const void *data, int data_len)
8749{
8750 int rem, i = 0;
8751 struct nlattr *tb[SET_CHAN_MAX + 1];
8752 struct nlattr *tb2[SET_CHAN_MAX + 1];
8753 struct nlattr *curr_attr;
8754 struct hdd_vendor_chan_info *channel_list;
8755
8756 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
8757 hdd_err("Invalid ATTR");
8758 return -EINVAL;
8759 }
8760
8761 if (tb[SET_CHAN_REASON])
8762 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8763
8764 if (tb[SET_CHAN_CHANNEL_COUNT]) {
8765 *channel_cnt = nla_get_u8(tb[
8766 SET_CHAN_CHANNEL_COUNT]);
8767 hdd_info("channel count %d", *channel_cnt);
8768 }
8769
8770 if (!(*channel_cnt)) {
8771 hdd_err("channel count is %d", *channel_cnt);
8772 return -EINVAL;
8773 }
8774
8775 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8776 (*channel_cnt));
8777
8778 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
8779 if (nla_parse(tb2,
8780 SET_CHAN_MAX,
8781 nla_data(curr_attr), nla_len(curr_attr),
8782 NULL)) {
8783 hdd_err("nla_parse failed");
8784 return -EINVAL;
8785 }
8786 /* Parse and Fetch allowed SSID list*/
8787 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
8788 channel_list[i].pri_ch =
8789 nla_get_u8(
8790 tb2[SET_CHAN_PRIMARY_CHANNEL]);
8791 }
8792 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
8793 channel_list[i].ht_sec_ch =
8794 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
8795 }
8796 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
8797 channel_list[i].vht_seg0_center_ch =
8798 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
8799 }
8800 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
8801 channel_list[i].vht_seg1_center_ch =
8802 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
8803 }
8804 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
8805 channel_list[i].chan_width =
8806 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
8807 }
8808 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
8809 i, channel_list[i].pri_ch,
8810 channel_list[i].ht_sec_ch,
8811 channel_list[i].vht_seg0_center_ch,
8812 channel_list[i].vht_seg1_center_ch,
8813 channel_list[i].chan_width);
8814 i++;
8815 if (i > *channel_cnt)
8816 break;
8817 }
8818 *chan_list_ptr = channel_list;
8819
8820 return 0;
8821}
8822
8823/**
8824 * Undef short names for vendor set channel configuration
8825 */
8826#undef SET_CHAN_REASON
8827#undef SET_CHAN_CHANNEL_COUNT
8828#undef SET_CHAN_CHAN_LIST
8829#undef SET_CHAN_PRIMARY_CHANNEL
8830#undef SET_CHAN_SECONDARY_CHANNEL
8831#undef SET_CHAN_SEG0_CENTER_CHANNEL
8832#undef SET_CHAN_SEG1_CENTER_CHANNEL
8833#undef SET_CHAN_CHANNEL_WIDTH
8834#undef SET_CHAN_MAX
8835
8836/**
8837 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8838 * @wiphy: Pointer to wireless phy
8839 * @wdev: Pointer to wireless device
8840 * @data: Pointer to data
8841 * @data_len: Length of @data
8842 *
8843 * Return: 0 on success, negative errno on failure
8844 */
8845static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8846 struct wireless_dev *wdev,
8847 const void *data, int data_len)
8848{
8849 int ret_val;
8850 QDF_STATUS qdf_status;
8851 uint8_t channel_cnt = 0, reason = -1;
8852 struct hdd_vendor_chan_info *channel_list = NULL;
8853 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
8854 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8855
8856 ENTER();
8857
8858 ret_val = wlan_hdd_validate_context(hdd_ctx);
8859 if (ret_val)
8860 return ret_val;
8861
8862 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8863 hdd_err("Command not allowed in FTM mode");
8864 return -EINVAL;
8865 }
8866
8867 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
8868 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
8869 else {
8870 hdd_err("already timeout happened for acs");
8871 return -EINVAL;
8872 }
8873
8874 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
8875 &channel_cnt, data, data_len);
8876 if (ret_val)
8877 return ret_val;
8878
8879 /* Validate channel to be set */
8880 while (channel_cnt && channel_list) {
8881 qdf_status = wlan_hdd_validate_acs_channel(adapter,
8882 channel_list->pri_ch,
8883 channel_list->chan_width);
8884 if (qdf_status == QDF_STATUS_SUCCESS)
8885 break;
8886 channel_cnt--;
8887 channel_list++;
8888 }
8889 if ((channel_cnt <= 0) || !channel_list) {
8890 hdd_err("no available channel/chanlist %p", channel_list);
8891 return -EINVAL;
8892 }
8893
8894 qdf_status = hdd_update_acs_channel(adapter, reason,
8895 channel_cnt, channel_list);
8896 return qdf_status_to_os_return(qdf_status);
8897}
8898
8899/**
8900 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8901 * @wiphy: Pointer to wireless phy
8902 * @wdev: Pointer to wireless device
8903 * @data: Pointer to data
8904 * @data_len: Length of @data
8905 *
8906 * Return: 0 on success, negative errno on failure
8907 */
8908static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8909 struct wireless_dev *wdev,
8910 const void *data, int data_len)
8911{
8912 int ret;
8913
8914 cds_ssr_protect(__func__);
8915 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
8916 data_len);
8917 cds_ssr_protect(__func__);
8918
8919 return ret;
8920}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308921
8922/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308923 * wlan_hdd_cfg80211_setband() - Wrapper to setband
8924 * @wiphy: wiphy structure pointer
8925 * @wdev: Wireless device structure pointer
8926 * @data: Pointer to the data received
8927 * @data_len: Length of @data
8928 *
8929 * Return: 0 on success; errno on failure
8930 */
8931static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8932 struct wireless_dev *wdev,
8933 const void *data, int data_len)
8934{
8935 int ret;
8936
8937 cds_ssr_protect(__func__);
8938 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
8939 cds_ssr_unprotect(__func__);
8940
8941 return ret;
8942}
8943
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008944/**
8945 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
8946 * @nl80211_value: Vendor command attribute value
8947 * @wmi_value: Pointer to return converted WMI return value
8948 *
8949 * Convert NL80211 vendor command value for SAR limit set to WMI value
8950 * Return: 0 on success, -1 on invalid value
8951 */
8952static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
8953 u32 *wmi_value)
8954{
8955 int ret = 0;
8956
8957 switch (nl80211_value) {
8958 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
8959 *wmi_value = WMI_SAR_FEATURE_OFF;
8960 break;
8961 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
8962 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
8963 break;
8964 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
8965 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
8966 break;
8967 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
8968 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
8969 break;
8970 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
8971 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
8972 break;
8973 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
8974 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
8975 break;
8976 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
8977 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
8978 break;
8979 default:
8980 ret = -1;
8981 }
8982 return ret;
8983}
8984
8985/**
8986 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
8987 * @nl80211_value: Vendor command attribute value
8988 * @wmi_value: Pointer to return converted WMI return value
8989 *
8990 * Convert NL80211 vendor command value for SAR BAND to WMI value
8991 * Return: 0 on success, -1 on invalid value
8992 */
8993static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
8994{
8995 int ret = 0;
8996
8997 switch (nl80211_value) {
8998 case NL80211_BAND_2GHZ:
8999 *wmi_value = WMI_SAR_2G_ID;
9000 break;
9001 case NL80211_BAND_5GHZ:
9002 *wmi_value = WMI_SAR_5G_ID;
9003 break;
9004 default:
9005 ret = -1;
9006 }
9007 return ret;
9008}
9009
9010/**
9011 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
9012 * @nl80211_value: Vendor command attribute value
9013 * @wmi_value: Pointer to return converted WMI return value
9014 *
9015 * Convert NL80211 vendor command value for SAR Modulation to WMI value
9016 * Return: 0 on success, -1 on invalid value
9017 */
9018static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
9019 u32 *wmi_value)
9020{
9021 int ret = 0;
9022
9023 switch (nl80211_value) {
9024 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
9025 *wmi_value = WMI_SAR_MOD_CCK;
9026 break;
9027 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
9028 *wmi_value = WMI_SAR_MOD_OFDM;
9029 break;
9030 default:
9031 ret = -1;
9032 }
9033 return ret;
9034}
9035
9036
9037/**
9038 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
9039 * @wiphy: Pointer to wireless phy
9040 * @wdev: Pointer to wireless device
9041 * @data: Pointer to data
9042 * @data_len: Length of @data
9043 *
9044 * This function is used to setup Specific Absorption Rate limit specs.
9045 *
9046 * Return: 0 on success, negative errno on failure
9047 */
9048static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9049 struct wireless_dev *wdev,
9050 const void *data, int data_len)
9051{
9052 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9053 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9054 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9055 *sar_spec_list;
9056 struct sar_limit_cmd_params sar_limit_cmd = {0};
9057 int ret = -EINVAL, i = 0, rem = 0;
9058
9059 ENTER();
9060
9061 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9062 hdd_err("Command not allowed in FTM mode");
9063 return -EPERM;
9064 }
9065
9066 if (wlan_hdd_validate_context(hdd_ctx))
9067 return -EINVAL;
9068
9069 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9070 data, data_len, NULL)) {
9071 hdd_err("Invalid SAR attributes");
9072 return -EINVAL;
9073 }
9074
9075 /* Vendor command manadates all SAR Specs in single call */
9076 sar_limit_cmd.commit_limits = 1;
9077 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9078 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9079 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9080 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9081 &sar_limit_cmd.sar_enable) < 0) {
9082 hdd_err("Invalid SAR Enable attr");
9083 goto fail;
9084 }
9085 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009086 hdd_debug("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009087
9088 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9089 sar_limit_cmd.num_limit_rows = nla_get_u32(
9090 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009091 hdd_debug("attr sar num_limit_rows %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009092 sar_limit_cmd.num_limit_rows);
9093 }
9094 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9095 hdd_err("SAR Spec list exceed supported size");
9096 goto fail;
9097 }
9098 if (sar_limit_cmd.num_limit_rows == 0)
9099 goto send_sar_limits;
9100 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9101 struct sar_limit_cmd_row) *
9102 sar_limit_cmd.num_limit_rows);
9103 if (!sar_limit_cmd.sar_limit_row_list) {
9104 ret = -ENOMEM;
9105 goto fail;
9106 }
9107 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9108 hdd_err("Invalid SAR SPECs list");
9109 goto fail;
9110 }
9111
9112 nla_for_each_nested(sar_spec_list,
9113 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9114 if (i == sar_limit_cmd.num_limit_rows) {
9115 hdd_warn("SAR Cmd has excess SPECs in list");
9116 break;
9117 }
9118
9119 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9120 nla_data(sar_spec_list), nla_len(sar_spec_list),
9121 NULL)) {
9122 hdd_err("nla_parse failed for SAR Spec list");
9123 goto fail;
9124 }
9125 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9126 if (sar_spec[
9127 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9128 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9129 nla_get_u32(sar_spec[
9130 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9131 } else {
9132 hdd_err("SAR Spec does not have power limit value");
9133 goto fail;
9134 }
9135
9136 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9137 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9138 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9139 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9140 < 0) {
9141 hdd_err("Invalid SAR Band attr");
9142 goto fail;
9143 }
9144 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9145 WMI_SAR_BAND_ID_VALID_MASK;
9146 }
9147 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9148 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9149 nla_get_u32(sar_spec[
9150 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9151 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9152 WMI_SAR_CHAIN_ID_VALID_MASK;
9153 }
9154 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9155 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9156 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9157 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9158 < 0) {
9159 hdd_err("Invalid SAR Modulation attr");
9160 goto fail;
9161 }
9162 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9163 WMI_SAR_MOD_ID_VALID_MASK;
9164 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009165 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009166 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9167 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9168 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9169 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9170 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9171 i++;
9172 }
9173
9174 if (i < sar_limit_cmd.num_limit_rows) {
9175 hdd_warn("SAR Cmd has less SPECs in list");
9176 sar_limit_cmd.num_limit_rows = i;
9177 }
9178
9179send_sar_limits:
9180 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9181 QDF_STATUS_SUCCESS)
9182 ret = 0;
9183fail:
9184 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9185 return ret;
9186}
9187
9188/**
9189 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9190 * @wiphy: Pointer to wireless phy
9191 * @wdev: Pointer to wireless device
9192 * @data: Pointer to data
9193 * @data_len: Length of @data
9194 *
9195 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9196 *
9197 * Return: 0 on success, negative errno on failure
9198 */
9199static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9200 struct wireless_dev *wdev,
9201 const void *data,
9202 int data_len)
9203{
9204 int ret;
9205
9206 cds_ssr_protect(__func__);
9207 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9208 data_len);
9209 cds_ssr_unprotect(__func__);
9210
9211 return ret;
9212}
9213
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309214static const struct
9215nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9216 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9217 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9218 .len = QDF_MAC_ADDR_SIZE},
9219};
9220
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309221void wlan_hdd_rso_cmd_status_cb(void *ctx, struct rso_cmd_status *rso_status)
9222{
9223 hdd_context_t *hdd_ctx = (hdd_context_t *)ctx;
9224 hdd_adapter_t *adapter;
9225
9226 adapter = hdd_get_adapter_by_vdev(hdd_ctx, rso_status->vdev_id);
9227 if (!adapter) {
9228 hdd_err("adapter NULL");
9229 return;
9230 }
9231
9232 adapter->lfr_fw_status.is_disabled = rso_status->status;
9233 complete(&adapter->lfr_fw_status.disable_lfr_event);
9234}
9235
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309236/**
9237 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9238 * @wiphy: Pointer to wireless phy
9239 * @wdev: Pointer to wireless device
9240 * @data: Pointer to data
9241 * @data_len: Length of @data
9242 *
9243 * This function is used to enable/disable roaming using vendor commands
9244 *
9245 * Return: 0 on success, negative errno on failure
9246 */
9247static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9248 struct wireless_dev *wdev,
9249 const void *data, int data_len)
9250{
9251 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9252 struct net_device *dev = wdev->netdev;
9253 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9254 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309255 uint32_t is_fast_roam_enabled, enable_lfr_fw;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309256 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309257 QDF_STATUS qdf_status;
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309258 unsigned long rc;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309259
9260 ENTER_DEV(dev);
9261
9262 ret = wlan_hdd_validate_context(hdd_ctx);
9263 if (0 != ret)
9264 return ret;
9265
9266 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9267 hdd_err("Command not allowed in FTM mode");
9268 return -EINVAL;
9269 }
9270
9271 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9272 qca_wlan_vendor_attr);
9273 if (ret) {
9274 hdd_err("Invalid ATTR");
9275 return -EINVAL;
9276 }
9277
9278 /* Parse and fetch Enable flag */
9279 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9280 hdd_err("attr enable failed");
9281 return -EINVAL;
9282 }
9283
9284 is_fast_roam_enabled = nla_get_u32(
9285 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009286 hdd_debug("isFastRoamEnabled %d fast_roaming_allowed %d",
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009287 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309288
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009289 if (!adapter->fast_roaming_allowed) {
9290 hdd_err("fast roaming not allowed on %s interface",
9291 adapter->dev->name);
9292 return -EINVAL;
9293 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309294 /* Update roaming */
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309295 enable_lfr_fw = (is_fast_roam_enabled && adapter->fast_roaming_allowed);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309296 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309297 enable_lfr_fw);
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309298 if (qdf_status != QDF_STATUS_SUCCESS)
9299 hdd_err("sme_config_fast_roaming failed with status=%d",
9300 qdf_status);
9301 ret = qdf_status_to_os_return(qdf_status);
9302
Sreelakshmi Konamki88a2a412017-04-14 15:11:55 +05309303 INIT_COMPLETION(adapter->lfr_fw_status.disable_lfr_event);
9304 if (QDF_IS_STATUS_SUCCESS(qdf_status) && !enable_lfr_fw) {
9305 /*
9306 * wait only for LFR disable in fw as LFR enable
9307 * is always success
9308 */
9309 rc = wait_for_completion_timeout(
9310 &adapter->lfr_fw_status.disable_lfr_event,
9311 msecs_to_jiffies(WAIT_TIME_RSO_CMD_STATUS));
9312 if (!rc) {
9313 hdd_err("Timed out waiting for RSO CMD status");
9314 return -ETIMEDOUT;
9315 }
9316
9317 if (!adapter->lfr_fw_status.is_disabled) {
9318 hdd_err("Roam disable attempt in FW fails");
9319 return -EBUSY;
9320 }
9321 }
9322
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309323 EXIT();
9324 return ret;
9325}
9326
9327/**
9328 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9329 * @wiphy: Pointer to wireless phy
9330 * @wdev: Pointer to wireless device
9331 * @data: Pointer to data
9332 * @data_len: Length of @data
9333 *
9334 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9335 *
9336 * Return: 0 on success, negative errno on failure
9337 */
9338static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9339 struct wireless_dev *wdev,
9340 const void *data, int data_len)
9341{
9342 int ret;
9343
9344 cds_ssr_protect(__func__);
9345 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9346 cds_ssr_unprotect(__func__);
9347
9348 return ret;
9349}
9350
Padma, Santhosh Kumar16dacfb2017-03-21 19:05:40 +05309351
9352void hdd_update_cca_info_cb(void *context, uint32_t congestion,
9353 uint32_t vdev_id)
9354{
9355 hdd_context_t *hdd_ctx = (hdd_context_t *)context;
9356 int status;
9357 hdd_adapter_t *adapter = NULL;
9358 hdd_station_ctx_t *hdd_sta_ctx;
9359
9360 status = wlan_hdd_validate_context(hdd_ctx);
9361 if (status != 0)
9362 return;
9363
9364 adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
9365 if (adapter == NULL) {
9366 hdd_err("vdev_id %d does not exist with host", vdev_id);
9367 return;
9368 }
9369
9370 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
9371 hdd_sta_ctx->conn_info.cca = congestion;
9372 hdd_info("congestion:%d", congestion);
9373}
9374
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309375static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9376 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9377 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9378 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9379 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9380};
9381
9382/**
9383 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9384 * @wiphy: Pointer to wireless phy
9385 * @wdev: Pointer to wireless device
9386 * @data: Pointer to data
9387 * @data_len: Length of @data
9388 *
9389 * Return: 0 on success, negative errno on failure
9390 */
9391static int
9392__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9393 struct wireless_dev *wdev,
9394 const void *data,
9395 int data_len)
9396{
9397 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9398 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9399 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9400 struct nlattr *apth;
9401 int rem;
9402 int ret = 1;
9403 int print_idx = -1;
9404 int module_id = -1;
9405 int bit_mask = -1;
9406 int status;
9407
9408 ENTER();
9409
9410 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9411 hdd_err("Command not allowed in FTM mode");
9412 return -EINVAL;
9413 }
9414
9415 ret = wlan_hdd_validate_context(hdd_ctx);
9416 if (ret != 0)
9417 return -EINVAL;
9418
9419 print_idx = qdf_get_pidx();
9420 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9421 hdd_err("Invalid print controle object index");
9422 return -EINVAL;
9423 }
9424
9425 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9426 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9427 hdd_err("Invalid attr");
9428 return -EINVAL;
9429 }
9430
9431 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9432 hdd_err("attr trace level param failed");
9433 return -EINVAL;
9434 }
9435
9436 nla_for_each_nested(apth,
9437 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9438 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9439 nla_data(apth), nla_len(apth), NULL)) {
9440 hdd_err("Invalid attr");
9441 return -EINVAL;
9442 }
9443
9444 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9445 hdd_err("attr Module ID failed");
9446 return -EINVAL;
9447 }
9448 module_id = nla_get_u32
9449 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9450
9451 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9452 hdd_err("attr Verbose mask failed");
9453 return -EINVAL;
9454 }
9455 bit_mask = nla_get_u32
9456 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9457
9458 status = hdd_qdf_trace_enable(module_id, bit_mask);
9459
9460 if (status != 0)
9461 hdd_err("can not set verbose mask %d for the category %d",
9462 bit_mask, module_id);
9463 }
9464
9465 EXIT();
9466 return ret;
9467}
9468
9469/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309470 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9471 * @wiphy: Pointer to wireless phy
9472 * @wdev: Pointer to wireless device
9473 * @data: Pointer to data
9474 * @data_len: Length of @data
9475 *
9476 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9477 *
9478 * Return: 0 on success, negative errno on failure
9479 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309480
9481static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9482 struct wireless_dev *wdev,
9483 const void *data,
9484 int data_len)
9485{
9486 int ret;
9487
9488 cds_ssr_protect(__func__);
9489 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9490 cds_ssr_unprotect(__func__);
9491
9492 return ret;
9493}
9494
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009495const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9496 {
9497 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9498 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9499 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309500 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009501 .doit = is_driver_dfs_capable
9502 },
9503
9504#ifdef WLAN_FEATURE_NAN
9505 {
9506 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9507 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9508 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9509 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9510 .doit = wlan_hdd_cfg80211_nan_request
9511 },
9512#endif
9513
9514#ifdef WLAN_FEATURE_STATS_EXT
9515 {
9516 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9517 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9518 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9519 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9520 .doit = wlan_hdd_cfg80211_stats_ext_request
9521 },
9522#endif
9523#ifdef FEATURE_WLAN_EXTSCAN
9524 {
9525 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9526 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9527 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9528 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9529 .doit = wlan_hdd_cfg80211_extscan_start
9530 },
9531 {
9532 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9533 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9534 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9535 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9536 .doit = wlan_hdd_cfg80211_extscan_stop
9537 },
9538 {
9539 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9540 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9541 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9542 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9543 },
9544 {
9545 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9546 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9547 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9548 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9549 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9550 },
9551 {
9552 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9553 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9554 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9555 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9556 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9557 },
9558 {
9559 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9560 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9561 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9562 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9563 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9564 },
9565 {
9566 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9567 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9568 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9569 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9570 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9571 },
9572 {
9573 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9574 .info.subcmd =
9575 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9576 .flags =
9577 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9578 WIPHY_VENDOR_CMD_NEED_RUNNING,
9579 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9580 },
9581 {
9582 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9583 .info.subcmd =
9584 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9585 .flags =
9586 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9587 WIPHY_VENDOR_CMD_NEED_RUNNING,
9588 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9589 },
9590 {
9591 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9592 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9593 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9594 WIPHY_VENDOR_CMD_NEED_NETDEV |
9595 WIPHY_VENDOR_CMD_NEED_RUNNING,
9596 .doit = wlan_hdd_cfg80211_set_epno_list
9597 },
9598#endif /* FEATURE_WLAN_EXTSCAN */
9599
9600#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9601 {
9602 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9603 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9604 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9605 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9606 .doit = wlan_hdd_cfg80211_ll_stats_clear
9607 },
9608
9609 {
9610 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9611 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9612 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9613 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9614 .doit = wlan_hdd_cfg80211_ll_stats_set
9615 },
9616
9617 {
9618 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9619 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9620 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9621 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9622 .doit = wlan_hdd_cfg80211_ll_stats_get
9623 },
9624#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9625#ifdef FEATURE_WLAN_TDLS
9626 {
9627 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9628 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9629 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9630 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9631 .doit = wlan_hdd_cfg80211_exttdls_enable
9632 },
9633 {
9634 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9635 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9636 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9637 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9638 .doit = wlan_hdd_cfg80211_exttdls_disable
9639 },
9640 {
9641 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9642 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9643 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9644 .doit = wlan_hdd_cfg80211_exttdls_get_status
9645 },
9646#endif
9647 {
9648 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9649 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9650 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9651 .doit = wlan_hdd_cfg80211_get_supported_features
9652 },
9653 {
9654 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9655 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309656 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9657 WIPHY_VENDOR_CMD_NEED_NETDEV |
9658 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009659 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9660 },
9661 {
9662 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9663 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9664 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309665 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009666 },
9667 {
9668 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9669 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9670 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309671 WIPHY_VENDOR_CMD_NEED_NETDEV |
9672 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009673 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9674 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009675 {
9676 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9677 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9678 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309679 WIPHY_VENDOR_CMD_NEED_NETDEV |
9680 WIPHY_VENDOR_CMD_NEED_RUNNING,
Manikandan Mohan80dea792016-04-28 16:36:48 -07009681 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9682 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009683 {
9684 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309685 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9686 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9687 WIPHY_VENDOR_CMD_NEED_NETDEV |
9688 WIPHY_VENDOR_CMD_NEED_RUNNING,
9689 .doit = hdd_cfg80211_get_station_cmd
9690 },
9691 {
9692 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009693 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9694 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9695 WIPHY_VENDOR_CMD_NEED_NETDEV |
9696 WIPHY_VENDOR_CMD_NEED_RUNNING,
9697 .doit = wlan_hdd_cfg80211_do_acs
9698 },
9699
9700 {
9701 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9702 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9703 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9704 WIPHY_VENDOR_CMD_NEED_NETDEV,
9705 .doit = wlan_hdd_cfg80211_get_features
9706 },
9707#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9708 {
9709 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9710 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9711 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9712 WIPHY_VENDOR_CMD_NEED_NETDEV |
9713 WIPHY_VENDOR_CMD_NEED_RUNNING,
9714 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9715 },
9716#endif
9717#ifdef FEATURE_WLAN_EXTSCAN
9718 {
9719 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9720 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9721 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9722 WIPHY_VENDOR_CMD_NEED_NETDEV |
9723 WIPHY_VENDOR_CMD_NEED_RUNNING,
9724 .doit = wlan_hdd_cfg80211_set_passpoint_list
9725 },
9726 {
9727 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9728 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9729 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9730 WIPHY_VENDOR_CMD_NEED_NETDEV |
9731 WIPHY_VENDOR_CMD_NEED_RUNNING,
9732 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9733 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009734#endif /* FEATURE_WLAN_EXTSCAN */
9735 {
9736 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9737 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9738 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9739 WIPHY_VENDOR_CMD_NEED_NETDEV,
9740 .doit = wlan_hdd_cfg80211_get_wifi_info
9741 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009742#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009743 {
9744 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9745 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9746 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9747 WIPHY_VENDOR_CMD_NEED_NETDEV |
9748 WIPHY_VENDOR_CMD_NEED_RUNNING,
9749 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9750 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009751#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009752 {
9753 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9754 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9755 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309756 WIPHY_VENDOR_CMD_NEED_NETDEV |
9757 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009758 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9759 },
9760 {
9761 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9762 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9763 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309764 WIPHY_VENDOR_CMD_NEED_NETDEV |
9765 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009766 .doit = wlan_hdd_cfg80211_wifi_logger_start
9767 },
9768 {
9769 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9770 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9771 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
SaidiReddy Yenuga76047d02017-04-26 19:17:42 +05309772 WIPHY_VENDOR_CMD_NEED_NETDEV |
9773 WIPHY_VENDOR_CMD_NEED_RUNNING,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009774 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9775 },
9776 {
9777 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9778 .info.subcmd =
9779 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
9780 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9781 WIPHY_VENDOR_CMD_NEED_NETDEV |
9782 WIPHY_VENDOR_CMD_NEED_RUNNING,
9783 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
9784 },
9785 {
9786 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9787 .info.subcmd =
9788 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
9789 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9790 WIPHY_VENDOR_CMD_NEED_NETDEV |
9791 WIPHY_VENDOR_CMD_NEED_RUNNING,
9792 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
9793 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07009794#ifdef WLAN_FEATURE_TSF
9795 {
9796 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9797 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
9798 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9799 WIPHY_VENDOR_CMD_NEED_NETDEV |
9800 WIPHY_VENDOR_CMD_NEED_RUNNING,
9801 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
9802 },
9803#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009804#ifdef FEATURE_WLAN_TDLS
9805 {
9806 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9807 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
9808 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9809 WIPHY_VENDOR_CMD_NEED_NETDEV |
9810 WIPHY_VENDOR_CMD_NEED_RUNNING,
9811 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
9812 },
9813#endif
9814#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9815 {
9816 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9817 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
9818 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9819 WIPHY_VENDOR_CMD_NEED_NETDEV |
9820 WIPHY_VENDOR_CMD_NEED_RUNNING,
9821 .doit = wlan_hdd_cfg80211_offloaded_packets
9822 },
9823#endif
9824 {
9825 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9826 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
9827 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9828 WIPHY_VENDOR_CMD_NEED_NETDEV |
9829 WIPHY_VENDOR_CMD_NEED_RUNNING,
9830 .doit = wlan_hdd_cfg80211_monitor_rssi
9831 },
9832 {
9833 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309834 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
9835 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9836 WIPHY_VENDOR_CMD_NEED_NETDEV |
9837 WIPHY_VENDOR_CMD_NEED_RUNNING,
9838 .doit = wlan_hdd_cfg80211_set_ns_offload
9839 },
9840 {
9841 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009842 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
9843 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9844 WIPHY_VENDOR_CMD_NEED_NETDEV |
9845 WIPHY_VENDOR_CMD_NEED_RUNNING,
9846 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
9847 },
9848#ifdef WLAN_FEATURE_MEMDUMP
9849 {
9850 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9851 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
9852 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9853 WIPHY_VENDOR_CMD_NEED_NETDEV |
9854 WIPHY_VENDOR_CMD_NEED_RUNNING,
9855 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
9856 },
9857#endif /* WLAN_FEATURE_MEMDUMP */
9858 {
9859 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9860 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
9861 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9862 WIPHY_VENDOR_CMD_NEED_NETDEV |
9863 WIPHY_VENDOR_CMD_NEED_RUNNING,
9864 .doit = wlan_hdd_cfg80211_vendor_scan
9865 },
9866
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05309867 /* Vendor abort scan */
9868 {
9869 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9870 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
9871 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9872 WIPHY_VENDOR_CMD_NEED_NETDEV |
9873 WIPHY_VENDOR_CMD_NEED_RUNNING,
9874 .doit = wlan_hdd_vendor_abort_scan
9875 },
9876
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009877 /* OCB commands */
9878 {
9879 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9880 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
9881 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9882 WIPHY_VENDOR_CMD_NEED_NETDEV |
9883 WIPHY_VENDOR_CMD_NEED_RUNNING,
9884 .doit = wlan_hdd_cfg80211_ocb_set_config
9885 },
9886 {
9887 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9888 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
9889 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9890 WIPHY_VENDOR_CMD_NEED_NETDEV |
9891 WIPHY_VENDOR_CMD_NEED_RUNNING,
9892 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
9893 },
9894 {
9895 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9896 .info.subcmd =
9897 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
9898 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9899 WIPHY_VENDOR_CMD_NEED_NETDEV |
9900 WIPHY_VENDOR_CMD_NEED_RUNNING,
9901 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
9902 },
9903 {
9904 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9905 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
9906 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9907 WIPHY_VENDOR_CMD_NEED_NETDEV |
9908 WIPHY_VENDOR_CMD_NEED_RUNNING,
9909 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
9910 },
9911 {
9912 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9913 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
9914 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9915 WIPHY_VENDOR_CMD_NEED_NETDEV |
9916 WIPHY_VENDOR_CMD_NEED_RUNNING,
9917 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
9918 },
9919 {
9920 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9921 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
9922 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9923 WIPHY_VENDOR_CMD_NEED_NETDEV |
9924 WIPHY_VENDOR_CMD_NEED_RUNNING,
9925 .doit = wlan_hdd_cfg80211_dcc_get_stats
9926 },
9927 {
9928 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9929 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
9930 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9931 WIPHY_VENDOR_CMD_NEED_NETDEV |
9932 WIPHY_VENDOR_CMD_NEED_RUNNING,
9933 .doit = wlan_hdd_cfg80211_dcc_clear_stats
9934 },
9935 {
9936 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9937 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
9938 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9939 WIPHY_VENDOR_CMD_NEED_NETDEV |
9940 WIPHY_VENDOR_CMD_NEED_RUNNING,
9941 .doit = wlan_hdd_cfg80211_dcc_update_ndl
9942 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309943 {
9944 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9945 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
9946 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9947 WIPHY_VENDOR_CMD_NEED_NETDEV |
9948 WIPHY_VENDOR_CMD_NEED_RUNNING,
9949 .doit = wlan_hdd_cfg80211_get_link_properties
9950 },
Peng Xu278d0122015-09-24 16:34:17 -07009951 {
Peng Xud2220962016-07-11 17:59:17 -07009952 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07009953 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
9954 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9955 WIPHY_VENDOR_CMD_NEED_NETDEV |
9956 WIPHY_VENDOR_CMD_NEED_RUNNING,
9957 .doit = wlan_hdd_cfg80211_set_ota_test
9958 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08009959#ifdef FEATURE_LFR_SUBNET_DETECTION
9960 {
9961 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9962 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
9963 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9964 WIPHY_VENDOR_CMD_NEED_NETDEV |
9965 WIPHY_VENDOR_CMD_NEED_RUNNING,
9966 .doit = wlan_hdd_cfg80211_set_gateway_params
9967 },
9968#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07009969 {
Peng Xud2220962016-07-11 17:59:17 -07009970 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07009971 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
9972 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9973 WIPHY_VENDOR_CMD_NEED_NETDEV |
9974 WIPHY_VENDOR_CMD_NEED_RUNNING,
9975 .doit = wlan_hdd_cfg80211_txpower_scale
9976 },
9977 {
9978 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9979 .info.subcmd =
9980 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
9981 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9982 WIPHY_VENDOR_CMD_NEED_NETDEV |
9983 WIPHY_VENDOR_CMD_NEED_RUNNING,
9984 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
9985 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309986 {
9987 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9988 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
9989 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9990 WIPHY_VENDOR_CMD_NEED_NETDEV |
9991 WIPHY_VENDOR_CMD_NEED_RUNNING,
9992 .doit = wlan_hdd_cfg80211_bpf_offload
9993 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309994 {
9995 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05309996 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
9997 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9998 WIPHY_VENDOR_CMD_NEED_NETDEV |
9999 WIPHY_VENDOR_CMD_NEED_RUNNING,
10000 .doit = wlan_hdd_cfg80211_acs_dfs_mode
10001 },
10002 {
10003 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010004 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
10005 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10006 WIPHY_VENDOR_CMD_NEED_NETDEV |
10007 WIPHY_VENDOR_CMD_NEED_RUNNING,
10008 .doit = wlan_hdd_cfg80211_sta_roam_policy
10009 },
Agrawal Ashish467dde42016-09-08 18:44:22 +053010010#ifdef FEATURE_WLAN_CH_AVOID
10011 {
10012 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10013 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
10014 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10015 WIPHY_VENDOR_CMD_NEED_NETDEV |
10016 WIPHY_VENDOR_CMD_NEED_RUNNING,
10017 .doit = wlan_hdd_cfg80211_avoid_freq
10018 },
10019#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +053010020 {
10021 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +053010022 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
10023 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10024 WIPHY_VENDOR_CMD_NEED_NETDEV |
10025 WIPHY_VENDOR_CMD_NEED_RUNNING,
10026 .doit = wlan_hdd_cfg80211_sap_configuration_set
10027 },
Peng Xu8fdaa492016-06-22 10:20:47 -070010028 {
Peng Xu4225c152016-07-14 21:18:14 -070010029 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -070010030 .info.subcmd =
10031 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
10032 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10033 WIPHY_VENDOR_CMD_NEED_NETDEV |
10034 WIPHY_VENDOR_CMD_NEED_RUNNING,
10035 .doit = wlan_hdd_cfg80211_p2p_lo_start
10036 },
10037 {
10038 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10039 .info.subcmd =
10040 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
10041 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10042 WIPHY_VENDOR_CMD_NEED_NETDEV |
10043 WIPHY_VENDOR_CMD_NEED_RUNNING,
10044 .doit = wlan_hdd_cfg80211_p2p_lo_stop
10045 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053010046 {
10047 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10048 .info.subcmd =
10049 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
10050 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10051 WIPHY_VENDOR_CMD_NEED_NETDEV |
10052 WIPHY_VENDOR_CMD_NEED_RUNNING,
10053 .doit = wlan_hdd_cfg80211_conditional_chan_switch
10054 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070010055#ifdef WLAN_FEATURE_NAN_DATAPATH
10056 {
10057 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10058 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
10059 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10060 WIPHY_VENDOR_CMD_NEED_NETDEV |
10061 WIPHY_VENDOR_CMD_NEED_RUNNING,
10062 .doit = wlan_hdd_cfg80211_process_ndp_cmd
10063 },
10064#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +053010065 {
10066 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10067 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
10068 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10069 WIPHY_VENDOR_CMD_NEED_NETDEV |
10070 WIPHY_VENDOR_CMD_NEED_RUNNING,
10071 .doit = wlan_hdd_cfg80211_get_wakelock_stats
10072 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010073 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +053010074 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10075 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
10076 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10077 WIPHY_VENDOR_CMD_NEED_NETDEV |
10078 WIPHY_VENDOR_CMD_NEED_RUNNING,
10079 .doit = wlan_hdd_cfg80211_get_bus_size
10080 },
10081 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053010082 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10083 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
10084 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10085 WIPHY_VENDOR_CMD_NEED_NETDEV |
10086 WIPHY_VENDOR_CMD_NEED_RUNNING,
10087 .doit = wlan_hdd_cfg80211_update_vendor_channel
10088 },
10089 {
bingsd09dea32017-03-17 10:08:26 +080010090 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010091 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10092 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10093 WIPHY_VENDOR_CMD_NEED_NETDEV |
10094 WIPHY_VENDOR_CMD_NEED_RUNNING,
10095 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010096 },
10097 {
10098 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10099 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
10100 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10101 WIPHY_VENDOR_CMD_NEED_NETDEV |
10102 WIPHY_VENDOR_CMD_NEED_RUNNING,
10103 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010104 },
10105#ifdef WLAN_FEATURE_DISA
10106 {
10107 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10108 .info.subcmd =
10109 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10110 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10111 WIPHY_VENDOR_CMD_NEED_NETDEV |
10112 WIPHY_VENDOR_CMD_NEED_RUNNING,
10113 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10114 },
10115#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010116#ifdef FEATURE_WLAN_TDLS
10117 {
10118 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10119 .info.subcmd =
10120 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10121 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10122 WIPHY_VENDOR_CMD_NEED_NETDEV |
10123 WIPHY_VENDOR_CMD_NEED_RUNNING,
10124 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010125 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010126#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010127 {
10128 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10129 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10130 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10131 WIPHY_VENDOR_CMD_NEED_RUNNING,
10132 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10133 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010134 {
10135 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10136 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10137 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10138 WIPHY_VENDOR_CMD_NEED_NETDEV |
10139 WIPHY_VENDOR_CMD_NEED_RUNNING,
10140 .doit = wlan_hdd_cfg80211_set_trace_level
10141 },
10142
Paul Zhang3a210c52016-12-08 10:18:12 +080010143#ifdef WLAN_UMAC_CONVERGENCE
10144 COMMON_VENDOR_COMMANDS
10145#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080010146 FEATURE_11AX_VENDOR_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010147};
10148
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010149#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10150 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10151 defined(FEATURE_WLAN_SCAN_PNO)
10152/**
10153 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10154 * @wiphy: pointer to wiphy
10155 * @config: pointer to config
10156 *
10157 * Return: None
10158 */
10159static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10160 struct hdd_config *config)
10161{
10162 if (config->configPNOScanSupport) {
10163 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
Abhishek Singh0481d662017-04-11 18:20:11 +053010164 wiphy->max_sched_scan_ssids = SCAN_PNO_MAX_SUPP_NETWORKS;
10165 wiphy->max_match_sets = SCAN_PNO_MAX_SUPP_NETWORKS;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010166 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Abhishek Singh0481d662017-04-11 18:20:11 +053010167 wiphy->max_sched_scan_plans = SCAN_PNO_MAX_PLAN_REQUEST;
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010168 if (config->max_sched_scan_plan_interval)
10169 wiphy->max_sched_scan_plan_interval =
10170 config->max_sched_scan_plan_interval;
10171 if (config->max_sched_scan_plan_iterations)
10172 wiphy->max_sched_scan_plan_iterations =
10173 config->max_sched_scan_plan_iterations;
10174 }
10175}
10176#else
10177static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10178 struct hdd_config *config)
10179{
10180}
10181#endif
10182
10183
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010184/**
10185 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10186 * @priv_size: Size of the hdd context.
10187 *
10188 * Allocate wiphy context and hdd context.
10189 *
10190 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010191 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010192hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010193{
10194 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010195 hdd_context_t *hdd_ctx;
10196
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010197 ENTER();
10198
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010199 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10200
10201 if (!wiphy) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010202 hdd_err("wiphy init failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010203 return NULL;
10204 }
10205
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010206 hdd_ctx = wiphy_priv(wiphy);
10207
10208 hdd_ctx->wiphy = wiphy;
10209
10210 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010211}
10212
10213/*
10214 * FUNCTION: wlan_hdd_cfg80211_update_band
10215 * This function is called from the supplicant through a
10216 * private ioctl to change the band value
10217 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010218int wlan_hdd_cfg80211_update_band(hdd_context_t *hdd_ctx, struct wiphy *wiphy,
10219 eCsrBand eBand)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010220{
10221 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010222 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010223
10224 ENTER();
Dustin Browna30892e2016-10-12 17:28:36 -070010225 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010226
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010227 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010228 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010229
10230 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10231 struct ieee80211_supported_band *band = wiphy->bands[i];
10232
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010233 channelEnabledState = wlan_reg_get_channel_state(
10234 hdd_ctx->hdd_pdev,
10235 band->channels[j].hw_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010236
Dustin Browna30892e2016-10-12 17:28:36 -070010237 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010238 /* 5G only */
10239#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10240 /* Enable Social channels for P2P */
10241 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10242 (band->channels[j].center_freq)
10243 && CHANNEL_STATE_ENABLE ==
10244 channelEnabledState)
10245 band->channels[j].flags &=
10246 ~IEEE80211_CHAN_DISABLED;
10247 else
10248#endif
10249 band->channels[j].flags |=
10250 IEEE80211_CHAN_DISABLED;
10251 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010252 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010253 eCSR_BAND_24 == eBand) {
10254 /* 2G only */
10255 band->channels[j].flags |=
10256 IEEE80211_CHAN_DISABLED;
10257 continue;
10258 }
10259
Amar Singhal6842e8f2016-02-23 16:30:32 -080010260 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010261 band->channels[j].flags &=
10262 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010263 }
10264 }
10265 return 0;
10266}
10267
Peng Xuacfdda12017-02-06 16:15:38 -080010268#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010269/*
10270 * FUNCTION: wlan_hdd_cfg80211_init
10271 * This function is called by hdd_wlan_startup()
10272 * during initialization.
10273 * This function is used to initialize and register wiphy structure.
10274 */
10275int wlan_hdd_cfg80211_init(struct device *dev,
10276 struct wiphy *wiphy, struct hdd_config *pCfg)
10277{
10278 int i, j;
10279 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10280
10281 ENTER();
10282
10283 /* Now bind the underlying wlan device with wiphy */
10284 set_wiphy_dev(wiphy, dev);
10285
10286 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10287
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010288 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10289 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10290 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10291#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10292 | WIPHY_FLAG_4ADDR_STATION
10293#endif
10294 | WIPHY_FLAG_OFFCHAN_TX;
10295
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010296#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10297 wiphy->wowlan = &wowlan_support_cfg80211_init;
10298#else
10299 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10300 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10301 wiphy->wowlan.pattern_min_len = 1;
10302 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10303#endif
10304
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010305 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010306#ifdef FEATURE_WLAN_ESE
10307 || pCfg->isEseIniFeatureEnabled
10308#endif
10309 ) {
10310 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10311 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010312#ifdef FEATURE_WLAN_TDLS
10313 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10314 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10315#endif
10316
10317 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10318
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010319#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10320 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10321#endif
10322
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010323 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010324
10325#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010326 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010327#endif
10328
10329 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010330 * driver can still register regulatory callback and
10331 * it will get regulatory settings in wiphy->band[], but
10332 * driver need to determine what to do with both
10333 * regulatory settings
10334 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010335
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010336#if defined QCA_WIFI_FTM
10337}
10338#endif
10339
10340 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10341
10342 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10343
10344 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10345
Arun Khandavallifae92942016-08-01 13:31:08 +053010346 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10347 | BIT(NL80211_IFTYPE_ADHOC)
10348 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10349 | BIT(NL80211_IFTYPE_P2P_GO)
10350 | BIT(NL80211_IFTYPE_AP)
10351 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010352
Arun Khandavallifae92942016-08-01 13:31:08 +053010353 if (pCfg->advertiseConcurrentOperation) {
10354 if (pCfg->enableMCC) {
10355 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010356
Arun Khandavallifae92942016-08-01 13:31:08 +053010357 for (i = 0;
10358 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10359 i++) {
10360 if (!pCfg->allowMCCGODiffBI)
10361 wlan_hdd_iface_combination[i].
10362 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010363 }
10364 }
10365 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010366 ARRAY_SIZE(wlan_hdd_iface_combination);
10367 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010368 }
10369
10370 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010371 * on ini values
10372 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010373 if (!pCfg->ShortGI20MhzEnable) {
10374 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10375 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010376 }
10377
10378 if (!pCfg->ShortGI40MhzEnable) {
10379 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10380 }
10381
10382 if (!pCfg->nChannelBondingMode5GHz) {
10383 wlan_hdd_band_5_ghz.ht_cap.cap &=
10384 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10385 }
10386
Abhishek Singhf512bf32016-05-04 16:47:46 +053010387 /*
10388 * In case of static linked driver at the time of driver unload,
10389 * module exit doesn't happens. Module cleanup helps in cleaning
10390 * of static memory.
10391 * If driver load happens statically, at the time of driver unload,
10392 * wiphy flags don't get reset because of static memory.
10393 * It's better not to store channel in static memory.
10394 */
Dustin Browna30892e2016-10-12 17:28:36 -070010395 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10396 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010397 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010398 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010399 hdd_err("Not enough memory to allocate channels");
10400 return -ENOMEM;
10401 }
Dustin Browna30892e2016-10-12 17:28:36 -070010402 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010403 &hdd_channels_2_4_ghz[0],
10404 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010405 if ((hdd_is_5g_supported(pHddCtx)) &&
10406 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10407 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10408 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10409 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010410 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10411 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010412 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010413 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010414 hdd_err("Not enough memory to allocate channels");
10415 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010416 bands[NL80211_BAND_2GHZ]->channels);
10417 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010418 return -ENOMEM;
10419 }
Dustin Browna30892e2016-10-12 17:28:36 -070010420 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010421 &hdd_channels_5_ghz[0],
10422 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010423 }
10424
Dustin Browna30892e2016-10-12 17:28:36 -070010425 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010426
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010427 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010428 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010429
10430 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10431 struct ieee80211_supported_band *band = wiphy->bands[i];
10432
Dustin Browna30892e2016-10-12 17:28:36 -070010433 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010434 eCSR_BAND_5G == pCfg->nBandCapability) {
10435 /* 5G only */
10436#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10437 /* Enable social channels for P2P */
10438 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10439 (band->channels[j].center_freq))
10440 band->channels[j].flags &=
10441 ~IEEE80211_CHAN_DISABLED;
10442 else
10443#endif
10444 band->channels[j].flags |=
10445 IEEE80211_CHAN_DISABLED;
10446 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010447 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010448 eCSR_BAND_24 == pCfg->nBandCapability) {
10449 /* 2G only */
10450 band->channels[j].flags |=
10451 IEEE80211_CHAN_DISABLED;
10452 continue;
10453 }
10454 }
10455 }
10456 /*Initialise the supported cipher suite details */
10457 wiphy->cipher_suites = hdd_cipher_suites;
10458 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10459
10460 /*signal strength in mBm (100*dBm) */
10461 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10462 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10463
Anurag Chouhan6d760662016-02-20 16:05:43 +053010464 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010465 wiphy->n_vendor_commands =
10466 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10467 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10468
10469 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10470 wiphy->n_vendor_events =
10471 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10472 }
10473
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010474 if (pCfg->enableDFSMasterCap) {
10475 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10476 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010477
10478 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10479
10480#ifdef QCA_HT_2040_COEX
10481 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10482#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010483 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010484
10485#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10486 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10487 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10488 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10489 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10490#endif
10491
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010492 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010493 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010494
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010495 EXIT();
10496 return 0;
10497}
10498
Abhishek Singhf512bf32016-05-04 16:47:46 +053010499/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010500 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10501 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010502 *
10503 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010504 * memory allocated in wlan_hdd_cfg80211_init also
10505 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010506 *
10507 * Return: void
10508 */
10509void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10510{
10511 int i;
10512
Dustin Browna30892e2016-10-12 17:28:36 -070010513 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010514 if (NULL != wiphy->bands[i] &&
10515 (NULL != wiphy->bands[i]->channels)) {
10516 qdf_mem_free(wiphy->bands[i]->channels);
10517 wiphy->bands[i]->channels = NULL;
10518 }
10519 }
Amar Singhal5cccafe2017-02-15 12:42:58 -080010520
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010521 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010522}
10523
Yingying Tang80e15f32016-09-27 18:23:01 +080010524/**
10525 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10526 * @hdd_ctx: HDD context
10527 *
10528 * this function will update capabilities for supported bands
10529 *
10530 * Return: void
10531 */
10532static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10533{
10534 uint32_t val32;
10535 uint16_t val16;
10536 tSirMacHTCapabilityInfo *ht_cap_info;
10537 QDF_STATUS status;
10538
10539 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10540 if (QDF_STATUS_SUCCESS != status) {
10541 hdd_err("could not get HT capability info");
10542 val32 = 0;
10543 }
10544 val16 = (uint16_t)val32;
10545 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10546
10547 if (ht_cap_info->txSTBC == true) {
10548 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10549 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10550 IEEE80211_HT_CAP_TX_STBC;
10551 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10552 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10553 IEEE80211_HT_CAP_TX_STBC;
10554 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010555
10556 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10557 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10558 vht_cap.vht_supported = 0;
10559 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10560 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10561 vht_cap.vht_supported = 0;
10562 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10563 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010564}
10565
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010566/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010567 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010568 * initialization. In wlan_hdd_cfg80211_init, only the
10569 * default values will be initialized. The final initialization
10570 * of all required members can be done here.
10571 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010572void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010573{
Yingying Tang80e15f32016-09-27 18:23:01 +080010574 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10575
10576 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010577}
10578
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010579/**
10580 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10581 * @cfg: hdd cfg
10582 *
10583 * this function update 11n mode in hdd cfg
10584 *
10585 * Return: void
10586 */
10587void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10588{
10589 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010590 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010591 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010592 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010593 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10594 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10595 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10596 cfg->sap_p2p_11ac_override = 0;
10597 }
10598 }
10599}
10600
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010601/* In this function we are registering wiphy. */
10602int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10603{
10604 ENTER();
10605 /* Register our wiphy dev with cfg80211 */
10606 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010607 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010608 return -EIO;
10609 }
10610
10611 EXIT();
10612 return 0;
10613}
10614
10615/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010616 * HDD function to update wiphy capability based on target offload status.
10617 *
10618 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10619 * capability even before downloading firmware to the target. In discrete
10620 * case, host will get know certain offload capability (say sched_scan
10621 * caps) only after downloading firmware to the target and target boots up.
10622 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10623 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010624 */
10625void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10626{
10627#ifdef FEATURE_WLAN_SCAN_PNO
10628 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10629 struct hdd_config *pCfg = pHddCtx->config;
10630
10631 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10632 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010633 * have PNO support.
10634 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010635 if (!pCfg->PnoOffload) {
10636 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10637 wiphy->max_sched_scan_ssids = 0;
10638 wiphy->max_match_sets = 0;
10639 wiphy->max_sched_scan_ie_len = 0;
10640 }
10641#endif
10642}
10643
10644/* This function registers for all frame which supplicant is interested in */
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070010645#if defined(CONVERGED_P2P_ENABLE) || defined(CONVERGED_TDLS_ENABLE)
10646
Wu Gao84d120c2017-03-24 18:46:00 +080010647void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10648{
10649 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10650 /* Register for all P2P action, public action etc frames */
10651 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10652
10653 ENTER();
10654
10655 /* Register frame indication call back */
10656 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10657
10658 /* Register for p2p ack indication */
10659 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10660
10661 /* Right now we are registering these frame when driver is getting
10662 * initialized. Once we will move to 2.6.37 kernel, in which we have
10663 * frame register ops, we will move this code as a part of that
10664 */
10665
10666 /* GAS Initial Request */
10667 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10668 (uint8_t *) GAS_INITIAL_REQ,
10669 GAS_INITIAL_REQ_SIZE);
10670
10671 /* GAS Initial Response */
10672 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10673 (uint8_t *) GAS_INITIAL_RSP,
10674 GAS_INITIAL_RSP_SIZE);
10675
10676 /* GAS Comeback Request */
10677 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10678 (uint8_t *) GAS_COMEBACK_REQ,
10679 GAS_COMEBACK_REQ_SIZE);
10680
10681 /* GAS Comeback Response */
10682 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10683 (uint8_t *) GAS_COMEBACK_RSP,
10684 GAS_COMEBACK_RSP_SIZE);
10685
10686 /* WNM BSS Transition Request frame */
10687 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10688 (uint8_t *) WNM_BSS_ACTION_FRAME,
10689 WNM_BSS_ACTION_FRAME_SIZE);
10690
10691 /* WNM-Notification */
10692 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10693 (uint8_t *) WNM_NOTIFICATION_FRAME,
10694 WNM_NOTIFICATION_FRAME_SIZE);
10695}
10696#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010697void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10698{
10699 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10700 /* Register for all P2P action, public action etc frames */
10701 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10702
10703 ENTER();
10704
Abhishek Singh7996eb72015-12-30 17:24:02 +053010705 /* Register frame indication call back */
10706 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10707
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010708 /* Register for p2p ack indication */
10709 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10710
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010711 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010712 * initialized. Once we will move to 2.6.37 kernel, in which we have
10713 * frame register ops, we will move this code as a part of that
10714 */
10715
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010716 /* GAS Initial Request */
10717 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10718 (uint8_t *) GAS_INITIAL_REQ,
10719 GAS_INITIAL_REQ_SIZE);
10720
10721 /* GAS Initial Response */
10722 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10723 (uint8_t *) GAS_INITIAL_RSP,
10724 GAS_INITIAL_RSP_SIZE);
10725
10726 /* GAS Comeback Request */
10727 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10728 (uint8_t *) GAS_COMEBACK_REQ,
10729 GAS_COMEBACK_REQ_SIZE);
10730
10731 /* GAS Comeback Response */
10732 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10733 (uint8_t *) GAS_COMEBACK_RSP,
10734 GAS_COMEBACK_RSP_SIZE);
10735
10736 /* P2P Public Action */
10737 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10738 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10739 P2P_PUBLIC_ACTION_FRAME_SIZE);
10740
10741 /* P2P Action */
10742 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10743 (uint8_t *) P2P_ACTION_FRAME,
10744 P2P_ACTION_FRAME_SIZE);
10745
10746 /* WNM BSS Transition Request frame */
10747 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10748 (uint8_t *) WNM_BSS_ACTION_FRAME,
10749 WNM_BSS_ACTION_FRAME_SIZE);
10750
10751 /* WNM-Notification */
10752 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10753 (uint8_t *) WNM_NOTIFICATION_FRAME,
10754 WNM_NOTIFICATION_FRAME_SIZE);
10755}
Wu Gao84d120c2017-03-24 18:46:00 +080010756#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010757
10758void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10759{
10760 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10761 /* Register for all P2P action, public action etc frames */
10762 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10763
10764 ENTER();
10765
10766 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010767 * initialized. Once we will move to 2.6.37 kernel, in which we have
10768 * frame register ops, we will move this code as a part of that
10769 */
10770
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010771 /* GAS Initial Request */
10772
10773 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10774 (uint8_t *) GAS_INITIAL_REQ,
10775 GAS_INITIAL_REQ_SIZE);
10776
10777 /* GAS Initial Response */
10778 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10779 (uint8_t *) GAS_INITIAL_RSP,
10780 GAS_INITIAL_RSP_SIZE);
10781
10782 /* GAS Comeback Request */
10783 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10784 (uint8_t *) GAS_COMEBACK_REQ,
10785 GAS_COMEBACK_REQ_SIZE);
10786
10787 /* GAS Comeback Response */
10788 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10789 (uint8_t *) GAS_COMEBACK_RSP,
10790 GAS_COMEBACK_RSP_SIZE);
10791
10792 /* P2P Public Action */
10793 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10794 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10795 P2P_PUBLIC_ACTION_FRAME_SIZE);
10796
10797 /* P2P Action */
10798 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10799 (uint8_t *) P2P_ACTION_FRAME,
10800 P2P_ACTION_FRAME_SIZE);
10801
10802 /* WNM-Notification */
10803 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
10804 (uint8_t *) WNM_NOTIFICATION_FRAME,
10805 WNM_NOTIFICATION_FRAME_SIZE);
10806}
10807
10808#ifdef FEATURE_WLAN_WAPI
10809void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
10810 const uint8_t *mac_addr, const uint8_t *key,
10811 int key_Len)
10812{
10813 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10814 tCsrRoamSetKey setKey;
10815 bool isConnected = true;
10816 int status = 0;
10817 uint32_t roamId = 0xFF;
10818 uint8_t *pKeyPtr = NULL;
10819 int n = 0;
10820
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010821 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010822 hdd_device_mode_to_string(pAdapter->device_mode),
10823 pAdapter->device_mode);
10824
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010825 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010826 setKey.keyId = key_index; /* Store Key ID */
10827 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
10828 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
10829 setKey.paeRole = 0; /* the PAE role */
10830 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053010831 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010832 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010833 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010834 }
10835 setKey.keyLength = key_Len;
10836 pKeyPtr = setKey.Key;
10837 memcpy(pKeyPtr, key, key_Len);
10838
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010839 hdd_debug("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010840 for (n = 0; n < key_Len; n++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010841 hdd_debug("WAPI KEY Data[%d]:%02x ",
Jeff Johnson46b40792016-06-29 14:03:14 -070010842 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010843
10844 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10845 if (isConnected) {
10846 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10847 pAdapter->sessionId, &setKey, &roamId);
10848 }
10849 if (status != 0) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010850 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010851 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
10852 }
10853}
10854#endif /* FEATURE_WLAN_WAPI */
10855
10856uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
10857 uint8_t eid)
10858{
10859 int left = length;
10860 uint8_t *ptr = (uint8_t *)ies_ptr;
10861 uint8_t elem_id, elem_len;
10862
10863 while (left >= 2) {
10864 elem_id = ptr[0];
10865 elem_len = ptr[1];
10866 left -= 2;
10867 if (elem_len > left) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010868 hdd_err("Invalid IEs eid: %d elem_len: %d left: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010869 eid, elem_len, left);
10870 return NULL;
10871 }
10872 if (elem_id == eid) {
10873 return ptr;
10874 }
10875
10876 left -= elem_len;
10877 ptr += (elem_len + 2);
10878 }
10879 return NULL;
10880}
10881
10882/*
10883 * FUNCTION: wlan_hdd_validate_operation_channel
10884 * called by wlan_hdd_cfg80211_start_bss() and
10885 * wlan_hdd_set_channel()
10886 * This function validates whether given channel is part of valid
10887 * channel list.
10888 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010889QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010890 int channel)
10891{
10892
10893 uint32_t num_ch = 0;
10894 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
10895 u32 indx = 0;
10896 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10897 uint8_t fValidChannel = false, count = 0;
10898 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
10899
10900 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10901
10902 if (hdd_pConfig_ini->sapAllowAllChannel) {
10903 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080010904 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070010905 if (channel == WLAN_REG_CH_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010906 fValidChannel = true;
10907 break;
10908 }
10909 }
10910 if (fValidChannel != true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010911 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010912 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010913 }
10914 } else {
10915 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
10916 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010917 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010918 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010919 }
10920 for (indx = 0; indx < num_ch; indx++) {
10921 if (channel == valid_ch[indx]) {
10922 break;
10923 }
10924 }
10925
10926 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010927 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010928 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010929 }
10930 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010931 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010932
10933}
10934
10935#ifdef DHCP_SERVER_OFFLOAD
10936static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
10937{
10938 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
10939 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
10940 uint8_t numEntries = 0;
10941 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
10942 uint8_t num;
10943 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010944 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010945 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070010946 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010947 return;
10948 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010949 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
10950 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
10951 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
10952 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
10953 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
10954 if (numEntries != IPADDR_NUM_ENTRIES) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010955 hdd_err("Incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010956 goto end;
10957 }
10958 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010959 hdd_err("Invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010960 goto end;
10961 }
10962 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010963 hdd_err("Invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010964 goto end;
10965 }
10966 for (num = 0; num < numEntries; num++) {
10967 temp = srv_ip[num];
10968 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
10969 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010970 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010971 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010972 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010973 goto end;
10974 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010975 hdd_debug("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010976end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010977 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010978 return;
10979}
10980#endif /* DHCP_SERVER_OFFLOAD */
10981
10982static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10983 struct net_device *dev,
10984 struct bss_parameters *params)
10985{
10986 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10987 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10988 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010989 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010990
10991 ENTER();
10992
Anurag Chouhan6d760662016-02-20 16:05:43 +053010993 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010994 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010995 return -EINVAL;
10996 }
10997
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010998 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10999 hdd_err("invalid session id: %d", pAdapter->sessionId);
11000 return -EINVAL;
11001 }
11002
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011003 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011004 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
11005 pAdapter->sessionId, params->ap_isolate));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011006 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011007 hdd_device_mode_to_string(pAdapter->device_mode),
11008 pAdapter->device_mode, params->ap_isolate);
11009
11010 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11011 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011012 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011013 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011014
Krunal Sonib4326f22016-03-10 13:05:51 -080011015 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
11016 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011017 return -EOPNOTSUPP;
11018 }
11019
11020 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011021 * want to update this parameter
11022 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011023 if (-1 != params->ap_isolate) {
11024 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
11025 !!params->ap_isolate;
11026
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011027 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011028 pAdapter->sessionId,
11029 pAdapter->sessionCtx.
11030 ap.
11031 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011032 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011033 ret = -EINVAL;
11034 }
11035 }
11036
11037 EXIT();
11038 return ret;
11039}
11040
Krunal Soni8c37e322016-02-03 16:08:37 -080011041/**
11042 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
11043 * @ndev: pointer to net device provided by supplicant
11044 * @type: type of the interface, upper layer wanted to change
11045 *
11046 * Upper layer provides the new interface mode that needs to be changed
11047 * for given net device
11048 *
11049 * Return: success or failure in terms of integer value
11050 */
11051static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011052 enum nl80211_iftype type)
11053{
Krunal Soni8c37e322016-02-03 16:08:37 -080011054 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11055 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
11056 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011057 hdd_wext_state_t *wext;
11058 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011059 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011060
11061 ENTER();
11062
Krunal Soni8c37e322016-02-03 16:08:37 -080011063 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011064 hdd_warn("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011065 return 0;
11066 }
11067
11068 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080011069 hdd_stop_adapter(hdd_ctx, adapter, true);
11070 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011071 wdev->iftype = type;
11072 /*Check for sub-string p2p to confirm its a p2p interface */
11073 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080011074 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011075 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011076 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080011077 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080011078 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011079 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080011080 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011081 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011082 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011083 }
Krunal Soni8c37e322016-02-03 16:08:37 -080011084 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
11085 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080011086 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
11087 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011088 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080011089 adapter->scan_info.scanAddIE.length;
11090 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011091 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080011092 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
11093 wext->roamProfile.phyMode =
11094 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
11095 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011096 EXIT();
11097 return status;
11098}
11099
11100static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11101 struct net_device *dev,
11102 struct bss_parameters *params)
11103{
11104 int ret;
11105
11106 cds_ssr_protect(__func__);
11107 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
11108 cds_ssr_unprotect(__func__);
11109
11110 return ret;
11111}
11112
11113/* FUNCTION: wlan_hdd_change_country_code_cd
11114 * to wait for contry code completion
11115 */
11116void *wlan_hdd_change_country_code_cb(void *pAdapter)
11117{
11118 hdd_adapter_t *call_back_pAdapter = pAdapter;
11119 complete(&call_back_pAdapter->change_country_code);
11120 return NULL;
11121}
11122
Rajeev Kumar98edb772016-01-19 12:42:19 -080011123/**
11124 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11125 * @wiphy: Pointer to the wiphy structure
11126 * @ndev: Pointer to the net device
11127 * @type: Interface type
11128 * @flags: Flags for change interface
11129 * @params: Pointer to change interface parameters
11130 *
11131 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011132 */
11133static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11134 struct net_device *ndev,
11135 enum nl80211_iftype type,
11136 u32 *flags,
11137 struct vif_params *params)
11138{
11139 struct wireless_dev *wdev;
11140 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11141 hdd_context_t *pHddCtx;
11142 tCsrRoamProfile *pRoamProfile = NULL;
11143 eCsrRoamBssType LastBSSType;
11144 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011145 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011146 int status;
11147
11148 ENTER();
11149
Anurag Chouhan6d760662016-02-20 16:05:43 +053011150 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011151 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011152 return -EINVAL;
11153 }
11154
11155 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11156 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011157 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011158 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011159
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011160 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011161 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11162 pAdapter->sessionId, type));
11163
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011164 hdd_debug("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011165 pAdapter->device_mode, type);
11166
Arun Khandavallifae92942016-08-01 13:31:08 +053011167 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11168 if (status) {
11169 hdd_err("Failed to start modules");
11170 return -EINVAL;
11171 }
11172
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011173 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011174 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11175 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011176 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011177 return -EINVAL;
11178 }
11179
11180 pConfig = pHddCtx->config;
11181 wdev = ndev->ieee80211_ptr;
11182
11183 /* Reset the current device mode bit mask */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011184 policy_mgr_clear_concurrency_mode(pHddCtx->hdd_psoc,
11185 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011186
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070011187 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shahe6359752017-02-23 19:57:50 +053011188 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011189 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11190 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11191 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11192 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011193 hdd_wext_state_t *pWextState =
11194 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11195
11196 pRoamProfile = &pWextState->roamProfile;
11197 LastBSSType = pRoamProfile->BSSType;
11198
11199 switch (type) {
11200 case NL80211_IFTYPE_STATION:
11201 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011202 case NL80211_IFTYPE_ADHOC:
11203 if (type == NL80211_IFTYPE_ADHOC) {
11204 wlan_hdd_tdls_exit(pAdapter);
11205 hdd_deregister_tx_flow_control(pAdapter);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011206 hdd_debug("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011207 }
11208 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
11209 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011210 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011211 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011212 if (hdd_start_adapter(pAdapter)) {
11213 hdd_err("Failed to start adapter :%d",
11214 pAdapter->device_mode);
11215 return -EINVAL;
11216 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011217 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011218 case NL80211_IFTYPE_AP:
11219 case NL80211_IFTYPE_P2P_GO:
11220 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011221 hdd_debug("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011222 (type ==
11223 NL80211_IFTYPE_AP) ? "SoftAP" :
11224 "P2pGo");
11225
11226 /* Cancel any remain on channel for GO mode */
11227 if (NL80211_IFTYPE_P2P_GO == type) {
11228 wlan_hdd_cancel_existing_remain_on_channel
11229 (pAdapter);
11230 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011231
Arun Khandavallifae92942016-08-01 13:31:08 +053011232 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011233 /* De-init the adapter */
11234 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11235 memset(&pAdapter->sessionCtx, 0,
11236 sizeof(pAdapter->sessionCtx));
11237 pAdapter->device_mode =
11238 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011239 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11240 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011241
11242 /*
11243 * Fw will take care incase of concurrency
11244 */
11245
Krunal Sonib4326f22016-03-10 13:05:51 -080011246 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011247 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011248 /* To meet Android requirements create
11249 * a randomized MAC address of the
11250 * form 02:1A:11:Fx:xx:xx
11251 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011252 get_random_bytes(&ndev->dev_addr[3], 3);
11253 ndev->dev_addr[0] = 0x02;
11254 ndev->dev_addr[1] = 0x1A;
11255 ndev->dev_addr[2] = 0x11;
11256 ndev->dev_addr[3] |= 0xF0;
11257 memcpy(pAdapter->macAddressCurrent.
11258 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011259 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011260 pr_info("wlan: Generated HotSpot BSSID "
11261 MAC_ADDRESS_STR "\n",
11262 MAC_ADDR_ARRAY(ndev->dev_addr));
11263 }
11264
11265 hdd_set_ap_ops(pAdapter->dev);
11266
Arun Khandavallifae92942016-08-01 13:31:08 +053011267 if (hdd_start_adapter(pAdapter)) {
11268 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011269 return -EINVAL;
11270 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011271 /* Interface type changed update in wiphy structure */
11272 if (wdev) {
11273 wdev->iftype = type;
11274 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011275 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011276 return -EINVAL;
11277 }
11278 goto done;
11279 }
11280
11281 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011282 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011283 return -EOPNOTSUPP;
11284 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011285 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11286 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011287 switch (type) {
11288 case NL80211_IFTYPE_STATION:
11289 case NL80211_IFTYPE_P2P_CLIENT:
11290 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011291 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11292 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011293 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011294 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011295 if (hdd_start_adapter(pAdapter)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011296 hdd_err("Failed to start adapter: %d",
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011297 pAdapter->device_mode);
11298 return -EINVAL;
11299 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011300 goto done;
11301
11302 case NL80211_IFTYPE_AP:
11303 case NL80211_IFTYPE_P2P_GO:
11304 wdev->iftype = type;
11305 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011306 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011307 goto done;
11308
11309 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011310 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011311 return -EOPNOTSUPP;
11312 }
11313 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011314 hdd_err("Unsupported device mode: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011315 pAdapter->device_mode);
11316 return -EOPNOTSUPP;
11317 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011318done:
11319 /* Set bitmask based on updated value */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011320 policy_mgr_set_concurrency_mode(pHddCtx->hdd_psoc,
11321 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011322
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011323 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011324
11325 EXIT();
11326 return 0;
11327}
11328
Rajeev Kumar98edb772016-01-19 12:42:19 -080011329/**
11330 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11331 * @wiphy: Pointer to the wiphy structure
11332 * @ndev: Pointer to the net device
11333 * @type: Interface type
11334 * @flags: Flags for change interface
11335 * @params: Pointer to change interface parameters
11336 *
11337 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011338 */
11339static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11340 struct net_device *ndev,
11341 enum nl80211_iftype type,
11342 u32 *flags,
11343 struct vif_params *params)
11344{
11345 int ret;
11346
11347 cds_ssr_protect(__func__);
11348 ret =
11349 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11350 cds_ssr_unprotect(__func__);
11351
11352 return ret;
11353}
11354
Frank Liud4b2fa02017-03-29 11:46:48 +080011355#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011356static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11357 int index, uint8_t match)
11358{
11359 int i;
11360 for (i = 0; i < index; i++) {
11361 if (arr[i] == match)
11362 return true;
11363 }
11364 return false;
11365}
11366#endif
11367
11368/**
11369 * __wlan_hdd_change_station() - change station
11370 * @wiphy: Pointer to the wiphy structure
11371 * @dev: Pointer to the net device.
11372 * @mac: bssid
11373 * @params: Pointer to station parameters
11374 *
11375 * Return: 0 for success, error number on failure.
11376 */
11377#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11378static int __wlan_hdd_change_station(struct wiphy *wiphy,
11379 struct net_device *dev,
11380 const uint8_t *mac,
11381 struct station_parameters *params)
11382#else
11383static int __wlan_hdd_change_station(struct wiphy *wiphy,
11384 struct net_device *dev,
11385 uint8_t *mac,
11386 struct station_parameters *params)
11387#endif
11388{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011389 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011390 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11391 hdd_context_t *pHddCtx;
11392 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011393 struct qdf_mac_addr STAMacAddress;
Frank Liud4b2fa02017-03-29 11:46:48 +080011394#if defined(FEATURE_WLAN_TDLS) && !defined(CONVERGED_TDLS_ENABLE)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011395 tCsrStaParams StaParams = { 0 };
11396 uint8_t isBufSta = 0;
11397 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011398 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011399#endif
11400 int ret;
11401
11402 ENTER();
11403
Anurag Chouhan6d760662016-02-20 16:05:43 +053011404 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011405 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011406 return -EINVAL;
11407 }
11408
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011409 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011410 TRACE_CODE_HDD_CHANGE_STATION,
11411 pAdapter->sessionId, params->listen_interval));
11412
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011413 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11414 hdd_err("invalid session id: %d", pAdapter->sessionId);
11415 return -EINVAL;
11416 }
11417
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011418 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11419 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011420 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011421 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011422
11423 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11424
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011425 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011426
Krunal Sonib4326f22016-03-10 13:05:51 -080011427 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11428 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011429 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11430 status =
11431 hdd_softap_change_sta_state(pAdapter,
11432 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011433 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011434
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011435 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011436 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011437 return -EINVAL;
11438 }
11439 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011440 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11441 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011442 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080011443#if defined(FEATURE_WLAN_TDLS) && defined(CONVERGED_TDLS_ENABLE)
11444 ret = wlan_cfg80211_tdls_update_peer(pHddCtx->hdd_pdev,
11445 dev, mac, params);
11446#else
Naveen Rawat64e477e2016-05-20 10:34:56 -070011447
11448 if (cds_is_sub_20_mhz_enabled()) {
11449 hdd_err("TDLS not allowed with sub 20 MHz");
11450 return -EINVAL;
11451 }
11452
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011453 StaParams.capability = params->capability;
11454 StaParams.uapsd_queues = params->uapsd_queues;
11455 StaParams.max_sp = params->max_sp;
11456
11457 /* Convert (first channel , number of channels) tuple to
11458 * the total list of channels. This goes with the assumption
11459 * that if the first channel is < 14, then the next channels
11460 * are an incremental of 1 else an incremental of 4 till the number
11461 * of channels.
11462 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011463 hdd_debug("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011464 if (0 != params->supported_channels_len) {
11465 int i = 0, j = 0, k = 0, no_of_channels = 0;
11466 int num_unique_channels;
11467 int next;
11468 for (i = 0;
11469 i < params->supported_channels_len
11470 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11471 int wifi_chan_index;
11472 if (!wlan_hdd_is_duplicate_channel
11473 (StaParams.supported_channels, j,
11474 params->supported_channels[i])) {
11475 StaParams.
11476 supported_channels[j] =
11477 params->
11478 supported_channels[i];
11479 } else {
11480 continue;
11481 }
11482 wifi_chan_index =
11483 ((StaParams.supported_channels[j] <=
11484 HDD_CHANNEL_14) ? 1 : 4);
11485 no_of_channels =
11486 params->supported_channels[i + 1];
11487
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011488 hdd_debug("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d, wifi_chan_index: %d, no_of_channels: %d", i, j, k, j,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011489 StaParams.
11490 supported_channels[j],
11491 wifi_chan_index,
11492 no_of_channels);
11493 for (k = 1; k <= no_of_channels &&
11494 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11495 k++) {
11496 next =
11497 StaParams.
11498 supported_channels[j] +
11499 wifi_chan_index;
11500 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11501 StaParams.
11502 supported_channels[j
11503 +
11504 1]
11505 = next;
11506 } else {
11507 continue;
11508 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011509 hdd_debug("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011510 j + 1,
11511 StaParams.
11512 supported_channels[j +
11513 1]);
11514 j += 1;
11515 }
11516 }
11517 num_unique_channels = j + 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011518 hdd_debug("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011519 for (i = 0; i < num_unique_channels; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011520 hdd_debug("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011521 StaParams.
11522 supported_channels[i]);
11523 }
11524 if (MAX_CHANNEL < num_unique_channels)
11525 num_unique_channels = MAX_CHANNEL;
11526 StaParams.supported_channels_len =
11527 num_unique_channels;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011528 hdd_debug("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011529 StaParams.supported_channels_len);
11530 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011531 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011532 params->supported_oper_classes,
11533 params->supported_oper_classes_len);
11534 StaParams.supported_oper_classes_len =
11535 params->supported_oper_classes_len;
11536
11537 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011538 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011539 params->ext_capab,
11540 sizeof(StaParams.extn_capability));
11541
11542 if (NULL != params->ht_capa) {
11543 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011544 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011545 sizeof(tSirHTCap));
11546 }
11547
11548 StaParams.supported_rates_len =
11549 params->supported_rates_len;
11550
11551 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11552 * The supported_rates array , for all the structures propogating till Add Sta
11553 * to the firmware has to be modified , if the supplicant (ieee80211) is
11554 * modified to send more rates.
11555 */
11556
11557 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11558 */
11559 if (StaParams.supported_rates_len >
11560 SIR_MAC_MAX_SUPP_RATES)
11561 StaParams.supported_rates_len =
11562 SIR_MAC_MAX_SUPP_RATES;
11563
11564 if (0 != StaParams.supported_rates_len) {
11565 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011566 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011567 params->supported_rates,
11568 StaParams.supported_rates_len);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011569 hdd_debug("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011570 StaParams.supported_rates_len);
11571 for (i = 0; i < StaParams.supported_rates_len;
11572 i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011573 hdd_debug("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011574 StaParams.supported_rates[i]);
11575 }
11576
11577 if (NULL != params->vht_capa) {
11578 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011579 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011580 params->vht_capa,
11581 sizeof(tSirVHTCap));
11582 }
11583
11584 if (0 != params->ext_capab_len) {
11585 /*Define A Macro : TODO Sunil */
11586 if ((1 << 4) & StaParams.extn_capability[3]) {
11587 isBufSta = 1;
11588 }
11589 /* TDLS Channel Switching Support */
11590 if ((1 << 6) & StaParams.extn_capability[3]) {
11591 isOffChannelSupported = 1;
11592 }
11593 }
11594
Nitesh Shah99934ac2016-09-05 15:54:08 +053011595 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011596 (params->ht_capa || params->vht_capa ||
11597 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011598 is_qos_wmm_sta = true;
11599
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011600 hdd_debug("%s: TDLS Peer is QOS capable"
Nitesh Shah99934ac2016-09-05 15:54:08 +053011601 " is_qos_wmm_sta= %d HTcapPresent = %d",
11602 __func__, is_qos_wmm_sta,
11603 StaParams.htcap_present);
11604
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011605 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011606 &StaParams,
11607 isBufSta,
11608 isOffChannelSupported,
11609 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011610 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011611 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011612 return -EINVAL;
11613 }
11614
11615 status =
11616 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11617 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011618 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011619 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011620 return -EINVAL;
11621 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011622#endif
Frank Liud4b2fa02017-03-29 11:46:48 +080011623 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011624 }
11625 EXIT();
11626 return ret;
11627}
11628
11629/**
11630 * wlan_hdd_change_station() - cfg80211 change station handler function
11631 * @wiphy: Pointer to the wiphy structure
11632 * @dev: Pointer to the net device.
11633 * @mac: bssid
11634 * @params: Pointer to station parameters
11635 *
11636 * This is the cfg80211 change station handler function which invokes
11637 * the internal function @__wlan_hdd_change_station with
11638 * SSR protection.
11639 *
11640 * Return: 0 for success, error number on failure.
11641 */
11642#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11643static int wlan_hdd_change_station(struct wiphy *wiphy,
11644 struct net_device *dev,
11645 const u8 *mac,
11646 struct station_parameters *params)
11647#else
11648static int wlan_hdd_change_station(struct wiphy *wiphy,
11649 struct net_device *dev,
11650 u8 *mac,
11651 struct station_parameters *params)
11652#endif
11653{
11654 int ret;
11655
11656 cds_ssr_protect(__func__);
11657 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11658 cds_ssr_unprotect(__func__);
11659
11660 return ret;
11661}
11662
11663/*
11664 * FUNCTION: __wlan_hdd_cfg80211_add_key
11665 * This function is used to initialize the key information
11666 */
11667static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11668 struct net_device *ndev,
11669 u8 key_index, bool pairwise,
11670 const u8 *mac_addr,
11671 struct key_params *params)
11672{
11673 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11674 tCsrRoamSetKey setKey;
11675 int status;
11676 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011677 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011678 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011679 hdd_context_t *pHddCtx;
11680 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11681
11682 ENTER();
11683
Anurag Chouhan6d760662016-02-20 16:05:43 +053011684 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011685 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011686 return -EINVAL;
11687 }
11688
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011689 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011690 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011691 return -EINVAL;
11692 }
11693
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011694 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011695 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11696 pAdapter->sessionId, params->key_len));
11697 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11698 status = wlan_hdd_validate_context(pHddCtx);
11699
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011700 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011701 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011702
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011703 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011704 hdd_device_mode_to_string(pAdapter->device_mode),
11705 pAdapter->device_mode);
11706
11707 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011708 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011709
11710 return -EINVAL;
11711 }
11712
11713 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011714 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011715
11716 return -EINVAL;
11717 }
11718
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011719 hdd_debug("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011720
11721 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011722 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011723 setKey.keyId = key_index;
11724 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011725 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011726
11727 switch (params->cipher) {
11728 case WLAN_CIPHER_SUITE_WEP40:
11729 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11730 break;
11731
11732 case WLAN_CIPHER_SUITE_WEP104:
11733 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11734 break;
11735
11736 case WLAN_CIPHER_SUITE_TKIP:
11737 {
11738 u8 *pKey = &setKey.Key[0];
11739 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11740
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011741 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011742
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011743 /* Supplicant sends the 32bytes key in this order
11744 *
11745 * |--------------|----------|----------|
11746 * | Tk1 |TX-MIC | RX Mic |
11747 * |--------------|----------|----------|
11748 * <---16bytes---><--8bytes--><--8bytes-->
11749 *
11750 * Sme expects the 32 bytes key to be in the below order
11751 *
11752 * |--------------|----------|----------|
11753 * | Tk1 |RX-MIC | TX Mic |
11754 * |--------------|----------|----------|
11755 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011756 */
11757 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011758 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011759
11760 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011761 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011762
11763 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011764 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011765
11766 break;
11767 }
11768
11769 case WLAN_CIPHER_SUITE_CCMP:
11770 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
11771 break;
11772
11773#ifdef FEATURE_WLAN_WAPI
11774 case WLAN_CIPHER_SUITE_SMS4:
11775 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011776 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011777 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
11778 mac_addr, params->key,
11779 params->key_len);
11780 return 0;
11781 }
11782#endif
11783
11784#ifdef FEATURE_WLAN_ESE
11785 case WLAN_CIPHER_SUITE_KRK:
11786 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
11787 break;
11788#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11789 case WLAN_CIPHER_SUITE_BTK:
11790 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
11791 break;
11792#endif
11793#endif
11794
11795#ifdef WLAN_FEATURE_11W
11796 case WLAN_CIPHER_SUITE_AES_CMAC:
11797 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
11798 break;
11799#endif
11800
11801 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011802 hdd_err("Unsupported cipher type: %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011803 return -EOPNOTSUPP;
11804 }
11805
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011806 hdd_debug("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011807
11808 if (!pairwise) {
11809 /* set group key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011810 hdd_debug("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011811 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011812 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011813 } else {
11814 /* set pairwise key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011815 hdd_debug("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011816 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011817 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011818 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011819 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011820 /* if a key is already installed, block all subsequent ones */
11821 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011822 hdd_debug("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011823 return 0;
11824 }
11825
11826 setKey.keyDirection = eSIR_TX_RX;
11827 /*Set the group key */
11828 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11829 pAdapter->sessionId, &setKey, &roamId);
11830
11831 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011832 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011833 return -EINVAL;
11834 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011835 /* Save the keys here and call sme_roam_set_key for setting
11836 * the PTK after peer joins the IBSS network
11837 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011838 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011839 &setKey, sizeof(tCsrRoamSetKey));
11840
11841 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
11842 return status;
11843 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011844 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11845 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011846 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11847 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070011848 status = wlansap_set_key_sta(
11849 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011850 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011851 hdd_err("wlansap_set_key_sta failed status: %d",
11852 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011853 }
11854 }
11855
11856 /* Save the key in ap ctx for use on START_BASS and restart */
11857 if (pairwise ||
11858 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
11859 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011860 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011861 sizeof(tCsrRoamSetKey));
11862 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011863 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011864 sizeof(tCsrRoamSetKey));
11865
Krunal Sonib4326f22016-03-10 13:05:51 -080011866 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11867 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011868 hdd_wext_state_t *pWextState =
11869 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11870 hdd_station_ctx_t *pHddStaCtx =
11871 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11872
11873 if (!pairwise) {
11874 /* set group key */
11875 if (pHddStaCtx->roam_info.deferKeyComplete) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011876 hdd_debug("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011877 __func__, __LINE__);
11878 hdd_perform_roam_set_key_complete(pAdapter);
11879 }
11880 }
11881
11882 pWextState->roamProfile.Keys.KeyLength[key_index] =
11883 (u8) params->key_len;
11884
11885 pWextState->roamProfile.Keys.defaultIndex = key_index;
11886
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011887 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011888 KeyMaterial[key_index][0], params->key,
11889 params->key_len);
11890
11891 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11892
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011893 hdd_debug("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011894 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11895 setKey.keyDirection);
11896
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011897 /* The supplicant may attempt to set the PTK once
11898 * pre-authentication is done. Save the key in the
11899 * UMAC and include it in the ADD BSS request
11900 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011901 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011902 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011903 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011904 hdd_debug("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011905 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011906 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011907 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011908 return -EINVAL;
11909 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011910
11911 /* issue set key request to SME */
11912 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11913 pAdapter->sessionId, &setKey, &roamId);
11914
11915 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011916 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011917 pHddStaCtx->roam_info.roamingState =
11918 HDD_ROAM_STATE_NONE;
11919 return -EINVAL;
11920 }
11921
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011922 /* in case of IBSS as there was no information
11923 * available about WEP keys during IBSS join, group
11924 * key intialized with NULL key, so re-initialize
11925 * group key with correct value
11926 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011927 if ((eCSR_BSS_TYPE_START_IBSS ==
11928 pWextState->roamProfile.BSSType)
11929 &&
11930 !((IW_AUTH_KEY_MGMT_802_1X ==
11931 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
11932 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
11933 pHddStaCtx->conn_info.authType)
11934 )
11935 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
11936 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
11937 )
11938 ) {
11939 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011940 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011941
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011942 hdd_debug("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011943 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11944 setKey.keyDirection);
11945
11946 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11947 pAdapter->sessionId, &setKey,
11948 &roamId);
11949
11950 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011951 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011952 pHddStaCtx->roam_info.roamingState =
11953 HDD_ROAM_STATE_NONE;
11954 return -EINVAL;
11955 }
11956 }
11957 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011958 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011959 return 0;
11960}
11961
11962static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11963 struct net_device *ndev,
11964 u8 key_index, bool pairwise,
11965 const u8 *mac_addr,
11966 struct key_params *params)
11967{
11968 int ret;
11969 cds_ssr_protect(__func__);
11970 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
11971 mac_addr, params);
11972 cds_ssr_unprotect(__func__);
11973
11974 return ret;
11975}
11976
11977/*
11978 * FUNCTION: __wlan_hdd_cfg80211_get_key
11979 * This function is used to get the key information
11980 */
11981static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11982 struct net_device *ndev,
11983 u8 key_index, bool pairwise,
11984 const u8 *mac_addr, void *cookie,
11985 void (*callback)(void *cookie,
11986 struct key_params *)
11987 )
11988{
11989 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11990 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11991 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
11992 struct key_params params;
11993
11994 ENTER();
11995
Anurag Chouhan6d760662016-02-20 16:05:43 +053011996 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011997 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011998 return -EINVAL;
11999 }
12000
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012001 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012002 hdd_device_mode_to_string(pAdapter->device_mode),
12003 pAdapter->device_mode);
12004
12005 memset(&params, 0, sizeof(params));
12006
12007 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012008 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012009 return -EINVAL;
12010 }
12011
12012 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
12013 case eCSR_ENCRYPT_TYPE_NONE:
12014 params.cipher = IW_AUTH_CIPHER_NONE;
12015 break;
12016
12017 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
12018 case eCSR_ENCRYPT_TYPE_WEP40:
12019 params.cipher = WLAN_CIPHER_SUITE_WEP40;
12020 break;
12021
12022 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
12023 case eCSR_ENCRYPT_TYPE_WEP104:
12024 params.cipher = WLAN_CIPHER_SUITE_WEP104;
12025 break;
12026
12027 case eCSR_ENCRYPT_TYPE_TKIP:
12028 params.cipher = WLAN_CIPHER_SUITE_TKIP;
12029 break;
12030
12031 case eCSR_ENCRYPT_TYPE_AES:
12032 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
12033 break;
12034
12035 default:
12036 params.cipher = IW_AUTH_CIPHER_NONE;
12037 break;
12038 }
12039
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012040 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012041 TRACE_CODE_HDD_CFG80211_GET_KEY,
12042 pAdapter->sessionId, params.cipher));
12043
12044 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
12045 params.seq_len = 0;
12046 params.seq = NULL;
12047 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
12048 callback(cookie, &params);
12049
12050 EXIT();
12051 return 0;
12052}
12053
12054static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
12055 struct net_device *ndev,
12056 u8 key_index, bool pairwise,
12057 const u8 *mac_addr, void *cookie,
12058 void (*callback)(void *cookie,
12059 struct key_params *)
12060 )
12061{
12062 int ret;
12063
12064 cds_ssr_protect(__func__);
12065 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
12066 mac_addr, cookie, callback);
12067 cds_ssr_unprotect(__func__);
12068
12069 return ret;
12070}
12071
12072/**
12073 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
12074 * @wiphy: wiphy interface context
12075 * @ndev: pointer to net device
12076 * @key_index: Key index used in 802.11 frames
12077 * @unicast: true if it is unicast key
12078 * @multicast: true if it is multicast key
12079 *
12080 * This function is required for cfg80211_ops API.
12081 * It is used to delete the key information
12082 * Underlying hardware implementation does not have API to delete the
12083 * encryption key. It is automatically deleted when the peer is
12084 * removed. Hence this function currently does nothing.
12085 * Future implementation may interprete delete key operation to
12086 * replacing the key with a random junk value, effectively making it
12087 * useless.
12088 *
12089 * Return: status code, always 0.
12090 */
12091
12092static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12093 struct net_device *ndev,
12094 u8 key_index,
12095 bool pairwise, const u8 *mac_addr)
12096{
12097 EXIT();
12098 return 0;
12099}
12100
12101/**
12102 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
12103 * @wiphy: Pointer to wiphy structure.
12104 * @dev: Pointer to net_device structure.
12105 * @key_index: key index
12106 * @pairwise: pairwise
12107 * @mac_addr: mac address
12108 *
12109 * This is the cfg80211 delete key handler function which invokes
12110 * the internal function @__wlan_hdd_cfg80211_del_key with
12111 * SSR protection.
12112 *
12113 * Return: 0 for success, error number on failure.
12114 */
12115static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12116 struct net_device *dev,
12117 u8 key_index,
12118 bool pairwise, const u8 *mac_addr)
12119{
12120 int ret;
12121
12122 cds_ssr_protect(__func__);
12123 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
12124 pairwise, mac_addr);
12125 cds_ssr_unprotect(__func__);
12126
12127 return ret;
12128}
12129
12130/*
12131 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12132 * This function is used to set the default tx key index
12133 */
12134static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12135 struct net_device *ndev,
12136 u8 key_index,
12137 bool unicast, bool multicast)
12138{
12139 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12140 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12141 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12142 hdd_context_t *pHddCtx;
12143 int status;
12144
12145 ENTER();
12146
Anurag Chouhan6d760662016-02-20 16:05:43 +053012147 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012148 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012149 return -EINVAL;
12150 }
12151
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012152 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012153 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012154 return -EINVAL;
12155 }
12156
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012157 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012158 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12159 pAdapter->sessionId, key_index));
12160
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012161 hdd_debug("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012162 hdd_device_mode_to_string(pAdapter->device_mode),
12163 pAdapter->device_mode, key_index);
12164
12165 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012166 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012167 return -EINVAL;
12168 }
12169
12170 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12171 status = wlan_hdd_validate_context(pHddCtx);
12172
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012173 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012174 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012175
Krunal Sonib4326f22016-03-10 13:05:51 -080012176 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12177 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012178 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12179 pHddStaCtx->conn_info.ucEncryptionType) &&
12180 (eCSR_ENCRYPT_TYPE_AES !=
12181 pHddStaCtx->conn_info.ucEncryptionType)) {
12182 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012183 * then update the default key index
12184 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012185
12186 tCsrRoamSetKey setKey;
12187 uint32_t roamId = 0xFF;
12188 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12189
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012190 hdd_debug("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012191
12192 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012193 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012194 setKey.keyId = key_index;
12195 setKey.keyLength = Keys->KeyLength[key_index];
12196
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012197 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012198 &Keys->KeyMaterial[key_index][0],
12199 Keys->KeyLength[key_index]);
12200
12201 setKey.keyDirection = eSIR_TX_RX;
12202
Anurag Chouhanc5548422016-02-24 18:33:27 +053012203 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012204 &pHddStaCtx->conn_info.bssId);
12205
12206 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12207 pWextState->roamProfile.EncryptionType.
12208 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012209 /* In the case of dynamic wep
12210 * supplicant hardcodes DWEP type to
12211 * eCSR_ENCRYPT_TYPE_WEP104 even
12212 * though ap is configured for WEP-40
12213 * encryption. In this canse the key
12214 * length is 5 but the encryption type
12215 * is 104 hence checking the key
12216 * lenght(5) and encryption type(104)
12217 * and switching encryption type to 40
12218 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012219 pWextState->roamProfile.EncryptionType.
12220 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12221 pWextState->roamProfile.mcEncryptionType.
12222 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12223 }
12224
12225 setKey.encType =
12226 pWextState->roamProfile.EncryptionType.
12227 encryptionType[0];
12228
12229 /* Issue set key request */
12230 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12231 pAdapter->sessionId, &setKey,
12232 &roamId);
12233
12234 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012235 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012236 status);
12237 return -EINVAL;
12238 }
12239 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012240 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012241 /* In SoftAp mode setting key direction for default mode */
12242 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12243 pWextState->roamProfile.EncryptionType.encryptionType[0])
12244 && (eCSR_ENCRYPT_TYPE_AES !=
12245 pWextState->roamProfile.EncryptionType.
12246 encryptionType[0])) {
12247 /* Saving key direction for default key index to TX default */
12248 hdd_ap_ctx_t *pAPCtx =
12249 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12250 pAPCtx->wepKey[key_index].keyDirection =
12251 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012252 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012253 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012254 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012255 }
12256 }
12257
12258 EXIT();
12259 return status;
12260}
12261
12262static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12263 struct net_device *ndev,
12264 u8 key_index,
12265 bool unicast, bool multicast)
12266{
12267 int ret;
12268 cds_ssr_protect(__func__);
12269 ret =
12270 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12271 multicast);
12272 cds_ssr_unprotect(__func__);
12273
12274 return ret;
12275}
12276
Abhishek Singhc9941602016-08-09 16:06:22 +053012277/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012278 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12279 * interface that BSS might have been lost.
12280 * @pAdapter: adaptor
12281 * @bssid: bssid which might have been lost
12282 *
12283 * Return: bss which is unlinked from kernel cache
12284 */
12285struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12286 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012287{
12288 struct net_device *dev = pAdapter->dev;
12289 struct wireless_dev *wdev = dev->ieee80211_ptr;
12290 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012291 struct cfg80211_bss *bss = NULL;
12292
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012293 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012294 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012295 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012296 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012297 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012298 hdd_debug("cfg80211_unlink_bss called for BSSID "
Abhishek Singhc9941602016-08-09 16:06:22 +053012299 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012300 cfg80211_unlink_bss(wiphy, bss);
12301 }
12302 return bss;
12303}
12304
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012305#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4 , 3, 0)) || \
12306 defined (CFG80211_INFORM_BSS_FRAME_DATA)
12307static struct cfg80211_bss *
12308wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12309 struct ieee80211_channel *chan,
12310 struct ieee80211_mgmt *mgmt,
12311 size_t frame_len,
12312 int rssi, gfp_t gfp,
12313 uint64_t boottime_ns)
12314{
12315 struct cfg80211_bss *bss_status = NULL;
12316 struct cfg80211_inform_bss data = {0};
12317
12318 data.chan = chan;
12319 data.boottime_ns = boottime_ns;
12320 data.signal = rssi;
12321 bss_status = cfg80211_inform_bss_frame_data(wiphy, &data, mgmt,
12322 frame_len, gfp);
12323 return bss_status;
12324}
12325#else
12326static struct cfg80211_bss *
12327wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12328 struct ieee80211_channel *chan,
12329 struct ieee80211_mgmt *mgmt,
12330 size_t frame_len,
12331 int rssi, gfp_t gfp,
12332 uint64_t boottime_ns)
12333{
12334 struct cfg80211_bss *bss_status = NULL;
12335
12336 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len,
12337 rssi, gfp);
12338 return bss_status;
12339}
12340#endif
Abhishek Singhc9941602016-08-09 16:06:22 +053012341
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012342/**
12343 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12344 * @pAdapter: Pointer to adapter
12345 * @bss_desc: Pointer to bss descriptor
12346 *
12347 * This function is used to inform the BSS details to nl80211 interface.
12348 *
12349 * Return: struct cfg80211_bss pointer
12350 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012351struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12352 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012353{
12354 /*
12355 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12356 * already exists in bss data base of cfg80211 for that particular BSS
12357 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12358 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12359 * As of now there is no possibility to get the mgmt(probe response)
12360 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12361 * and passing to cfg80211_inform_bss_frame.
12362 */
12363 struct net_device *dev = pAdapter->dev;
12364 struct wireless_dev *wdev = dev->ieee80211_ptr;
12365 struct wiphy *wiphy = wdev->wiphy;
12366 int chan_no = bss_desc->channelId;
12367#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12368 qcom_ie_age *qie_age = NULL;
12369 int ie_length =
12370 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12371#else
12372 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12373#endif
12374 const char *ie =
12375 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12376 unsigned int freq;
12377 struct ieee80211_channel *chan;
12378 struct ieee80211_mgmt *mgmt = NULL;
12379 struct cfg80211_bss *bss_status = NULL;
12380 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12381 int rssi = 0;
12382 hdd_context_t *pHddCtx;
12383 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012384 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012385 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012386
12387 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12388 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012389 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012390 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012391
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012392 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012393 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012394 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012395 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012396 return NULL;
12397 }
12398
12399 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12400
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012401 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012402 * Instead it wants a monotonic increasing value
12403 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012404 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012405 mgmt->u.probe_resp.timestamp =
12406 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012407
12408 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12409 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12410
12411#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12412 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12413 /* Assuming this is the last IE, copy at the end */
12414 ie_length -= sizeof(qcom_ie_age);
12415 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12416 qie_age->element_id = QCOM_VENDOR_IE_ID;
12417 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12418 qie_age->oui_1 = QCOM_OUI1;
12419 qie_age->oui_2 = QCOM_OUI2;
12420 qie_age->oui_3 = QCOM_OUI3;
12421 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012422 /*
12423 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12424 * all bss related timestamp is in units of ms. Due to this when scan
12425 * results are sent to lowi the scan age is high.To address this,
12426 * send age in units of 1/10 ms.
12427 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012428 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012429 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012430 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012431 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12432 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012433 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12434 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012435#endif
12436
12437 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12438 if (bss_desc->fProbeRsp) {
12439 mgmt->frame_control |=
12440 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12441 } else {
12442 mgmt->frame_control |=
12443 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12444 }
12445
12446 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012447 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012448 freq =
12449 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012450 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012451 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012452 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012453 freq =
12454 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012455 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012456 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012457 hdd_err("Invalid channel: %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012458 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012459 return NULL;
12460 }
12461
12462 chan = __ieee80211_get_channel(wiphy, freq);
12463 /* When the band is changed on the fly using the GUI, three things are done
12464 * 1. scan abort
12465 * 2. flush scan results from cache
12466 * 3. update the band with the new band user specified (refer to the
12467 * hdd_set_band_helper function) as part of the scan abort, message will be
12468 * queued to PE and we proceed with flushing and changinh the band.
12469 * PE will stop the scanning further and report back the results what ever
12470 * it had till now by calling the call back function.
12471 * if the time between update band and scandone call back is sufficient
12472 * enough the band change reflects in SME, SME validates the channels
12473 * and discards the channels correponding to previous band and calls back
12474 * with zero bss results. but if the time between band update and scan done
12475 * callback is very small then band change will not reflect in SME and SME
12476 * reports to HDD all the channels correponding to previous band.this is due
12477 * to race condition.but those channels are invalid to the new band and so
12478 * this function __ieee80211_get_channel will return NULL.Each time we
12479 * report scan result with this pointer null warning kernel trace is printed.
12480 * if the scan results contain large number of APs continuosly kernel
12481 * warning trace is printed and it will lead to apps watch dog bark.
12482 * So drop the bss and continue to next bss.
12483 */
12484 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012485 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12486 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012487 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012488 return NULL;
12489 }
12490
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012491 /* Based on .ini configuration, raw rssi can be reported for bss.
12492 * Raw rssi is typically used for estimating power.
12493 */
12494
12495 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12496 bss_desc->rssi;
12497
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012498 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012499 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012500
Srinivas Girigowdac06543c2017-03-09 15:10:03 -080012501 hdd_debug("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012502 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012503 (int)(rssi / 100),
12504 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012505
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012506 bss_status = wlan_hdd_cfg80211_inform_bss_frame_data(wiphy, chan, mgmt,
12507 frame_len, rssi,
12508 GFP_KERNEL,
12509 bss_desc->scansystimensec);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012510 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012511 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012512 return bss_status;
12513}
12514
12515/**
12516 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12517 * @pAdapter: Pointer to adapter
12518 * @pRoamInfo: Pointer to roam info
12519 *
12520 * This function is used to update the BSS data base of CFG8011
12521 *
12522 * Return: struct cfg80211_bss pointer
12523 */
12524struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12525 tCsrRoamInfo *pRoamInfo)
12526{
12527 tCsrRoamConnectedProfile roamProfile;
12528 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12529 struct cfg80211_bss *bss = NULL;
12530
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012531 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12532 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12533
12534 if (NULL != roamProfile.pBssDesc) {
12535 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12536 roamProfile.pBssDesc);
12537
12538 if (NULL == bss)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012539 hdd_debug("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012540
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012541 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012542 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012543 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012544 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012545 return bss;
12546}
12547/**
12548 * wlan_hdd_cfg80211_update_bss() - update bss
12549 * @wiphy: Pointer to wiphy
12550 * @pAdapter: Pointer to adapter
12551 * @scan_time: scan request timestamp
12552 *
12553 * Return: zero if success, non-zero otherwise
12554 */
12555int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12556 hdd_adapter_t *pAdapter,
12557 uint32_t scan_time)
12558{
12559 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12560 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012561 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012562 tScanResultHandle pResult;
12563 struct cfg80211_bss *bss_status = NULL;
12564 hdd_context_t *pHddCtx;
12565 int ret;
12566
12567 ENTER();
12568
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012569 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12570 hdd_err("invalid session id: %d", pAdapter->sessionId);
12571 return -EINVAL;
12572 }
12573
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012574 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012575 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12576 NO_SESSION, pAdapter->sessionId));
12577
12578 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12579 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012580 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012581 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012582
12583 /* start getting scan results and populate cgf80211 BSS database */
12584 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12585
12586 /* no scan results */
12587 if (NULL == pResult) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012588 hdd_err("No scan result Status: %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012589 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012590 }
12591
12592 pScanResult = sme_scan_result_get_first(hHal, pResult);
12593
12594 while (pScanResult) {
12595 /*
12596 * - cfg80211_inform_bss() is not updating ie field of bss
12597 * entry if entry already exists in bss data base of cfg80211
12598 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12599 * to update thebss entry instead of cfg80211_inform_bss,
12600 * But this call expects mgmt packet as input. As of now
12601 * there is no possibility to get the mgmt(probe response)
12602 * frame from PE, converting bss_desc to
12603 * ieee80211_mgmt(probe response) and passing to c
12604 * fg80211_inform_bss_frame.
12605 * - Update BSS only if beacon timestamp is later than
12606 * scan request timestamp.
12607 */
12608 if ((scan_time == 0) ||
12609 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012610 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012611 bss_status =
12612 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12613 &pScanResult->BssDescriptor);
12614
12615 if (NULL == bss_status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012616 hdd_debug("NULL returned by cfg80211_inform_bss_frame");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012617 } else {
12618 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012619 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012620 bss_status);
12621 }
12622 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012623 hdd_debug("BSSID: " MAC_ADDRESS_STR " Skipped",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012624 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12625 }
12626 pScanResult = sme_scan_result_get_next(hHal, pResult);
12627 }
12628
Archana Ramachandran2eb7a612017-03-23 22:58:42 -070012629 sme_scan_result_purge(pResult);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012630 /*
12631 * For SAP mode, scan is invoked by hostapd during SAP start
12632 * if hostapd is restarted, we need to flush previous scan
12633 * result so that it will reflect environment change
12634 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012635 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012636#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12637 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12638#endif
12639 )
12640 sme_scan_flush_result(hHal);
12641
12642 EXIT();
12643 return 0;
12644}
12645
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012646/**
12647 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12648 * @pAdapter: Pointer to adapter
12649 * @pRoamInfo: Pointer to roam info
12650 * @index: Index
12651 * @preauth: Preauth flag
12652 *
12653 * This function is used to notify the supplicant of a new PMKSA candidate.
12654 *
12655 * Return: 0 for success, non-zero for failure
12656 */
12657int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12658 tCsrRoamInfo *pRoamInfo,
12659 int index, bool preauth)
12660{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012661 struct net_device *dev = pAdapter->dev;
12662 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12663
12664 ENTER();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012665 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012666
12667 if (NULL == pRoamInfo) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012668 hdd_err("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012669 return -EINVAL;
12670 }
12671
12672 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012673 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012674 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12675 cfg80211_pmksa_candidate_notify(dev, index,
12676 pRoamInfo->bssid.bytes,
12677 preauth, GFP_KERNEL);
12678 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012679 return 0;
12680}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012681
12682#ifdef FEATURE_WLAN_LFR_METRICS
12683/**
12684 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12685 * @pAdapter: Pointer to adapter
12686 * @pRoamInfo: Pointer to roam info
12687 *
12688 * 802.11r/LFR metrics reporting function to report preauth initiation
12689 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012690 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012691 */
12692#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012693QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012694 tCsrRoamInfo *pRoamInfo)
12695{
12696 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12697 union iwreq_data wrqu;
12698
12699 ENTER();
12700
12701 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012702 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012703 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012704 }
12705
12706 /* create the event */
12707 memset(&wrqu, 0, sizeof(wrqu));
12708 memset(metrics_notification, 0, sizeof(metrics_notification));
12709
12710 wrqu.data.pointer = metrics_notification;
12711 wrqu.data.length = scnprintf(metrics_notification,
12712 sizeof(metrics_notification),
12713 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12714 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12715
12716 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12717 metrics_notification);
12718
12719 EXIT();
12720
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012721 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012722}
12723
12724/**
12725 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12726 * @pAdapter: Pointer to adapter
12727 * @pRoamInfo: Pointer to roam info
12728 * @preauth_status: Preauth status
12729 *
12730 * 802.11r/LFR metrics reporting function to report handover initiation
12731 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012732 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012733 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012734QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012735wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12736 tCsrRoamInfo *pRoamInfo,
12737 bool preauth_status)
12738{
12739 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12740 union iwreq_data wrqu;
12741
12742 ENTER();
12743
12744 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012745 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012746 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012747 }
12748
12749 /* create the event */
12750 memset(&wrqu, 0, sizeof(wrqu));
12751 memset(metrics_notification, 0, sizeof(metrics_notification));
12752
12753 scnprintf(metrics_notification, sizeof(metrics_notification),
12754 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12755 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12756
12757 if (1 == preauth_status)
12758 strlcat(metrics_notification, " true",
12759 sizeof(metrics_notification));
12760 else
12761 strlcat(metrics_notification, " false",
12762 sizeof(metrics_notification));
12763
12764 wrqu.data.pointer = metrics_notification;
12765 wrqu.data.length = strlen(metrics_notification);
12766
12767 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12768 metrics_notification);
12769
12770 EXIT();
12771
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012772 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012773}
12774
12775/**
12776 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12777 * @pAdapter: Pointer to adapter
12778 * @pRoamInfo: Pointer to roam info
12779 *
12780 * 802.11r/LFR metrics reporting function to report handover initiation
12781 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012782 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012783 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012784QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012785 tCsrRoamInfo *pRoamInfo)
12786{
12787 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12788 union iwreq_data wrqu;
12789
12790 ENTER();
12791
12792 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012793 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012794 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012795 }
12796
12797 /* create the event */
12798 memset(&wrqu, 0, sizeof(wrqu));
12799 memset(metrics_notification, 0, sizeof(metrics_notification));
12800
12801 wrqu.data.pointer = metrics_notification;
12802 wrqu.data.length = scnprintf(metrics_notification,
12803 sizeof(metrics_notification),
12804 "QCOM: LFR_PREAUTH_HANDOVER "
12805 MAC_ADDRESS_STR,
12806 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12807
12808 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12809 metrics_notification);
12810
12811 EXIT();
12812
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012813 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012814}
12815#endif
12816
12817/**
12818 * hdd_select_cbmode() - select channel bonding mode
12819 * @pAdapter: Pointer to adapter
12820 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012821 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012822 *
12823 * Return: none
12824 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012825void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
Amar Singhal5cccafe2017-02-15 12:42:58 -080012826 struct ch_params *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012827{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012828 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012829 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012830 uint8_t sec_ch = 0;
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012831 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012832
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012833 /*
12834 * CDS api expects secondary channel for calculating
12835 * the channel params
12836 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012837 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012838 (WLAN_REG_IS_24GHZ_CH(operationChannel))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012839 if (operationChannel >= 1 && operationChannel <= 5)
12840 sec_ch = operationChannel + 4;
12841 else if (operationChannel >= 6 && operationChannel <= 13)
12842 sec_ch = operationChannel - 4;
12843 }
12844
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012845 /* This call decides required channel bonding mode */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012846 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, operationChannel,
12847 sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012848
12849 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Srinivas Girigowda2fb677c2017-03-25 15:35:34 -070012850 enum hdd_dot11_mode hdd_dot11_mode;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012851 uint8_t iniDot11Mode =
12852 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
12853
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012854 hdd_debug("Dot11Mode is %u", iniDot11Mode);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012855 switch (iniDot11Mode) {
12856 case eHDD_DOT11_MODE_AUTO:
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -080012857 case eHDD_DOT11_MODE_11ax:
12858 case eHDD_DOT11_MODE_11ax_ONLY:
12859 if (sme_is_feature_supported_by_fw(DOT11AX))
12860 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
12861 else if (sme_is_feature_supported_by_fw(DOT11AC))
12862 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12863 else
12864 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12865 break;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012866 case eHDD_DOT11_MODE_11ac:
12867 case eHDD_DOT11_MODE_11ac_ONLY:
12868 if (sme_is_feature_supported_by_fw(DOT11AC))
12869 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12870 else
12871 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12872 break;
12873 case eHDD_DOT11_MODE_11n:
12874 case eHDD_DOT11_MODE_11n_ONLY:
12875 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12876 break;
12877 default:
12878 hdd_dot11_mode = iniDot11Mode;
12879 break;
12880 }
12881 ch_info->channel_width = ch_params->ch_width;
12882 ch_info->phy_mode =
12883 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012884 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012885 ch_info->cb_mode = ch_params->ch_width;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012886 hdd_debug("ch_info width %d, phymode %d channel %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012887 ch_info->channel_width, ch_info->phy_mode,
12888 ch_info->channel);
12889 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012890}
12891
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012892/**
12893 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
12894 * @adapter: STA adapter
12895 * @roam_profile: STA roam profile
12896 *
12897 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
12898 *
12899 * Return: false if sta-sap conc is not allowed, else return true
12900 */
12901static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
12902 tCsrRoamProfile *roam_profile)
12903{
12904 hdd_context_t *hdd_ctx;
12905 hdd_adapter_t *ap_adapter;
12906 hdd_ap_ctx_t *hdd_ap_ctx;
12907 hdd_hostapd_state_t *hostapd_state;
12908 uint8_t channel = 0;
12909 QDF_STATUS status;
12910
12911 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
12912 if (!hdd_ctx) {
12913 hdd_err("HDD context is NULL");
12914 return true;
12915 }
12916
12917 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
12918 /* probably no sap running, no handling required */
12919 if (ap_adapter == NULL)
12920 return true;
12921
12922 /*
12923 * sap is not in started state, so it is fine to go ahead with sta.
12924 * if sap is currently doing CAC then don't allow sta to go further.
12925 */
12926 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
12927 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
12928 return true;
12929
12930 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
12931 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
12932 return false;
12933 }
12934
12935 /*
12936 * log and return error, if we allow STA to go through, we don't
12937 * know what is going to happen better stop sta connection
12938 */
12939 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
12940 if (NULL == hdd_ap_ctx) {
12941 hdd_err("AP context not found");
12942 return false;
12943 }
12944
12945 /* sap is on non-dfs channel, nothing to handle */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012946 if (!wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev,
12947 hdd_ap_ctx->operatingChannel)) {
12948 hdd_info("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012949 return true;
12950 }
12951 /*
12952 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053012953 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012954 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080012955 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->hdd_psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012956 roam_profile, &channel);
12957
Nitesh Shah59774522016-09-16 15:14:21 +053012958 /*
12959 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
12960 * channels for roaming case.
12961 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012962 if (WLAN_REG_IS_24GHZ_CH(channel)) {
12963 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053012964 return true;
12965 }
12966
12967 /*
12968 * If channel is 0 or DFS then better to call pcl and find out the
12969 * best channel. If channel is non-dfs 5 GHz then better move SAP
12970 * to STA's channel to make scc, so we have room for 3port MCC
12971 * scenario.
12972 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070012973 if ((0 == channel) || wlan_reg_is_dfs_ch(hdd_ctx->hdd_pdev, channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080012974 channel = policy_mgr_get_nondfs_preferred_channel(
12975 hdd_ctx->hdd_psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012976
12977 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
12978 qdf_event_reset(&hostapd_state->qdf_event);
12979 status = wlansap_set_channel_change_with_csa(
12980 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
12981 hdd_ap_ctx->sapConfig.ch_width_orig);
12982
12983 if (QDF_STATUS_SUCCESS != status) {
12984 hdd_err("Set channel with CSA IE failed, can't allow STA");
12985 return false;
12986 }
12987
12988 /*
12989 * wait here for SAP to finish the channel switch. When channel
12990 * switch happens, SAP sends few beacons with CSA_IE. After
12991 * successfully Transmission of those beacons, it will move its
12992 * state from started to disconnected and move to new channel.
12993 * once it moves to new channel, sap again moves its state
12994 * machine from disconnected to started and set this event.
12995 * wait for 10 secs to finish this.
12996 */
12997 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
12998 if (!QDF_IS_STATUS_SUCCESS(status)) {
12999 hdd_err("wait for qdf_event failed, STA not allowed!!");
13000 return false;
13001 }
13002
13003 return true;
13004}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013005
Abhishek Singhcfb44482017-03-10 12:42:37 +053013006#ifdef WLAN_FEATURE_11W
13007/**
13008 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
13009 * @roam_profile: pointer to roam profile
13010 *
13011 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
13012 * or pmf=2 is an explicit configuration in the supplicant
13013 * configuration, drop the connection request.
13014 *
13015 * Return: 0 if check result is valid, otherwise return error code
13016 */
13017static int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13018{
13019 if (roam_profile->MFPEnabled &&
13020 !(roam_profile->MFPRequired ||
13021 roam_profile->MFPCapable)) {
13022 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
13023 roam_profile->MFPEnabled,
13024 roam_profile->MFPRequired,
13025 roam_profile->MFPCapable);
13026 return -EINVAL;
13027 }
13028 return 0;
13029}
13030#else
13031static inline
13032int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
13033{
13034 return 0;
13035}
13036#endif
13037
Krunal Soni31949422016-07-29 17:17:53 -070013038/**
13039 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013040 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070013041 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013042 * @ssid_len: Length of ssid
13043 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070013044 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013045 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013046 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013047 *
13048 * This function is used to start the association process
13049 *
13050 * Return: 0 for success, non-zero for failure
13051 */
Krunal Soni31949422016-07-29 17:17:53 -070013052static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013053 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070013054 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013055 u8 operatingChannel,
13056 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013057{
13058 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080013059 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013060 hdd_wext_state_t *pWextState;
13061 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013062 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013063 uint32_t roamId;
13064 tCsrRoamProfile *pRoamProfile;
13065 eCsrAuthType RSNAuthType;
13066 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053013067 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013068
13069 ENTER();
13070
13071 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13072 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053013073 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013074
13075 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013076 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013077 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013078
13079 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013080 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013081 status = -EINVAL;
13082 goto ret_status;
13083 }
13084
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013085 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013086 hdd_err("Connection refused: conn in progress");
13087 status = -EINVAL;
13088 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013089 }
13090
Kabilan Kannan1c1c4022017-04-06 22:49:26 -070013091 hdd_notify_teardown_tdls_links(pAdapter->hdd_vdev);
Nitesh Shah273e4e52017-04-03 12:53:36 +053013092 wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx);
13093
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013094 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053013095 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
13096 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013097
13098 if (pRoamProfile) {
13099 hdd_station_ctx_t *pHddStaCtx;
13100 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13101
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013102 /* Restart the opportunistic timer
13103 *
13104 * If hw_mode_change_in_progress is true, then wait
13105 * till firmware sends the callback for hw_mode change.
13106 *
13107 * Else set connect_in_progress as true and proceed.
13108 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013109 policy_mgr_restart_opportunistic_timer(
13110 pHddCtx->hdd_psoc, false);
13111 if (policy_mgr_is_hw_mode_change_in_progress(
13112 pHddCtx->hdd_psoc)) {
Abhishek Singh471652b2017-04-14 12:28:32 +053013113 qdf_status = policy_mgr_wait_for_connection_update(
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013114 pHddCtx->hdd_psoc);
Abhishek Singh471652b2017-04-14 12:28:32 +053013115 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013116 hdd_err("qdf wait for event failed!!");
13117 status = -EINVAL;
13118 goto ret_status;
13119 }
13120 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013121 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013122
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013123 if (HDD_WMM_USER_MODE_NO_QOS ==
13124 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
13125 /*QoS not enabled in cfg file */
13126 pRoamProfile->uapsd_mask = 0;
13127 } else {
13128 /*QoS enabled, update uapsd mask from cfg file */
13129 pRoamProfile->uapsd_mask =
13130 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
13131 }
13132
13133 pRoamProfile->SSIDs.numOfSSIDs = 1;
13134 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013135 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013136 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013137 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013138 ssid, ssid_len);
13139
Deepak Dhamdherea2785822016-11-17 01:17:45 -080013140 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013141 /* cleanup bssid hint */
13142 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
13143 QDF_MAC_ADDR_SIZE);
13144 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
13145 QDF_MAC_ADDR_SIZE);
13146
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013147 if (bssid) {
13148 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053013149 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013150 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013151 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013152 /*
13153 * Save BSSID in seperate variable as
13154 * pRoamProfile's BSSID is getting zeroed out in the
13155 * association process. In case of join failure
13156 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013157 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013158 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013159 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013160 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013161 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013162 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
13163 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013164 /*
13165 * Save BSSID in a separate variable as
13166 * pRoamProfile's BSSID is getting zeroed out in the
13167 * association process. In case of join failure
13168 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013169 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013170 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013171 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013172 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070013173 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013174 }
13175
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013176 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013177 pRoamProfile->SSIDs.SSIDList->SSID.length,
13178 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
13179 operatingChannel);
13180
13181 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
13182 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013183 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013184 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
13185 }
13186#ifdef FEATURE_WLAN_WAPI
13187 if (pAdapter->wapi_info.nWapiMode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013188 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013189 switch (pAdapter->wapi_info.wapiAuthMode) {
13190 case WAPI_AUTH_MODE_PSK:
13191 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013192 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013193 pAdapter->wapi_info.wapiAuthMode);
13194 pRoamProfile->AuthType.authType[0] =
13195 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
13196 break;
13197 }
13198 case WAPI_AUTH_MODE_CERT:
13199 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013200 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013201 pAdapter->wapi_info.wapiAuthMode);
13202 pRoamProfile->AuthType.authType[0] =
13203 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
13204 break;
13205 }
13206 } /* End of switch */
13207 if (pAdapter->wapi_info.wapiAuthMode ==
13208 WAPI_AUTH_MODE_PSK
13209 || pAdapter->wapi_info.wapiAuthMode ==
13210 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013211 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013212 pRoamProfile->AuthType.numEntries = 1;
13213 pRoamProfile->EncryptionType.numEntries = 1;
13214 pRoamProfile->EncryptionType.encryptionType[0] =
13215 eCSR_ENCRYPT_TYPE_WPI;
13216 pRoamProfile->mcEncryptionType.numEntries = 1;
13217 pRoamProfile->mcEncryptionType.
13218 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13219 }
13220 }
Krunal Soni31949422016-07-29 17:17:53 -070013221#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013222 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013223 pRoamProfile->csrPersona = pAdapter->device_mode;
13224
13225 if (operatingChannel) {
13226 pRoamProfile->ChannelInfo.ChannelList =
13227 &operatingChannel;
13228 pRoamProfile->ChannelInfo.numOfChannels = 1;
13229 } else {
13230 pRoamProfile->ChannelInfo.ChannelList = NULL;
13231 pRoamProfile->ChannelInfo.numOfChannels = 0;
13232 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013233 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013234 && operatingChannel) {
13235 /*
13236 * Need to post the IBSS power save parameters
13237 * to WMA. WMA will configure this parameters
13238 * to firmware if power save is enabled by the
13239 * firmware.
13240 */
Abhishek Singh471652b2017-04-14 12:28:32 +053013241 qdf_status = hdd_set_ibss_power_save_params(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013242
Abhishek Singh471652b2017-04-14 12:28:32 +053013243 if (QDF_STATUS_SUCCESS != qdf_status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013244 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013245 status = -EINVAL;
13246 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013247 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013248 pRoamProfile->ch_params.ch_width =
13249 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013250 /*
13251 * In IBSS mode while operating in 2.4 GHz,
13252 * the device supports only 20 MHz.
13253 */
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070013254 if (WLAN_REG_IS_24GHZ_CH(operatingChannel))
Nitesh Shah87335a52016-09-05 15:47:32 +053013255 pRoamProfile->ch_params.ch_width =
13256 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013257 hdd_select_cbmode(pAdapter, operatingChannel,
13258 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013259 }
13260
Abhishek Singhcfb44482017-03-10 12:42:37 +053013261 if (wlan_hdd_cfg80211_check_pmf_valid(
13262 &pWextState->roamProfile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013263 status = -EINVAL;
13264 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013265 }
13266
Krunal Soni31949422016-07-29 17:17:53 -070013267 /*
13268 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013269 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013270 * enhancements, the supplicant is not issuing the scan command
13271 * now. So the unicast frames which are sent from the host are
13272 * not having the additional IEs. If it is P2P CLIENT and there
13273 * is no additional IE present in roamProfile, then use the
13274 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013275 */
13276
Krunal Sonib4326f22016-03-10 13:05:51 -080013277 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013278 (!pRoamProfile->pAddIEScan)) {
13279 pRoamProfile->pAddIEScan =
13280 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13281 pRoamProfile->nAddIEScanLength =
13282 pAdapter->scan_info.scanAddIE.length;
13283 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013284
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013285 if ((policy_mgr_is_hw_dbs_capable(pHddCtx->hdd_psoc) == true)
13286 && (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013287 pRoamProfile))) {
13288 hdd_err("sap-sta conc will fail, can't allow sta");
13289 hdd_conn_set_connection_state(pAdapter,
13290 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013291 status = -ENOMEM;
13292 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013293 }
13294
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013295 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013296 if (!sme_config) {
13297 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013298 hdd_conn_set_connection_state(pAdapter,
13299 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013300 status = -ENOMEM;
13301 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013302 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013303 sme_get_config_param(pHddCtx->hHal, sme_config);
13304 /* These values are not sessionized. So, any change in these SME
13305 * configs on an older or parallel interface will affect the
13306 * cb mode. So, restoring the default INI params before starting
13307 * interfaces such as sta, cli etc.,
13308 */
13309 sme_config->csrConfig.channelBondingMode5GHz =
13310 pHddCtx->config->nChannelBondingMode5GHz;
13311 sme_config->csrConfig.channelBondingMode24GHz =
13312 pHddCtx->config->nChannelBondingMode24GHz;
13313 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013314 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013315 /*
13316 * Change conn_state to connecting before sme_roam_connect(),
13317 * because sme_roam_connect() has a direct path to call
13318 * hdd_sme_roam_callback(), which will change the conn_state
13319 * If direct path, conn_state will be accordingly changed to
13320 * NotConnected or Associated by either
13321 * hdd_association_completion_handler() or
13322 * hdd_dis_connect_handler() in sme_RoamCallback()if
13323 * sme_RomConnect is to be queued,
13324 * Connecting state will remain until it is completed.
13325 *
13326 * If connection state is not changed, connection state will
13327 * remain in eConnectionState_NotConnected state.
13328 * In hdd_association_completion_handler, "hddDisconInProgress"
13329 * is set to true if conn state is
13330 * eConnectionState_NotConnected.
13331 * If "hddDisconInProgress" is set to true then cfg80211 layer
13332 * is not informed of connect result indication which
13333 * is an issue.
13334 */
13335 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013336 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013337 hdd_conn_set_connection_state(pAdapter,
13338 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013339
Komal Seelama89be8d2016-09-29 11:09:26 +053013340 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13341 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013342 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013343 pAdapter->sessionId, pRoamProfile,
13344 &roamId);
Abhishek Singh471652b2017-04-14 12:28:32 +053013345 if (QDF_IS_STATUS_ERROR(qdf_status))
13346 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013347
Rajeev Kumard31e1542017-01-13 14:37:42 -080013348 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013349 (QDF_STA_MODE == pAdapter->device_mode ||
13350 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013351 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013352 "qdf_status %d. -> NotConnected",
13353 pAdapter->sessionId, qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013354 /* change back to NotAssociated */
13355 hdd_conn_set_connection_state(pAdapter,
13356 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013357 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13358 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013359 }
13360
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013361 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013362 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013363
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013364 pRoamProfile->ChannelInfo.ChannelList = NULL;
13365 pRoamProfile->ChannelInfo.numOfChannels = 0;
13366
Nitesh Shah044fd672016-10-13 18:53:25 +053013367 if ((QDF_STA_MODE == pAdapter->device_mode)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013368 && policy_mgr_is_current_hwmode_dbs(pHddCtx->hdd_psoc)
13369 && !policy_mgr_is_hw_dbs_2x2_capable(
13370 pHddCtx->hdd_psoc)) {
13371 policy_mgr_get_channel_from_scan_result(
13372 pHddCtx->hdd_psoc,
13373 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013374 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013375 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013376 policy_mgr_checkn_update_hw_mode_single_mac_mode(
13377 pHddCtx->hdd_psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053013378 }
13379
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013380 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013381 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013382 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013383 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013384 goto ret_status;
13385
13386conn_failure:
13387 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013388 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013389
13390ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013391 EXIT();
13392 return status;
13393}
13394
13395/**
13396 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13397 * @pAdapter: Pointer to adapter
13398 * @auth_type: Auth type
13399 *
13400 * This function is used to set the authentication type (OPEN/SHARED).
13401 *
13402 * Return: 0 for success, non-zero for failure
13403 */
13404static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13405 enum nl80211_auth_type auth_type)
13406{
13407 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13408 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13409
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013410 /*set authentication type */
13411 switch (auth_type) {
13412 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013413 hdd_debug("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013414 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13415 break;
13416
13417 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013418 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013419 hdd_debug("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013420 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13421 break;
13422
13423 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013424 hdd_debug("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013425 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13426 break;
13427#ifdef FEATURE_WLAN_ESE
13428 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013429 hdd_debug("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013430 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13431 break;
13432#endif
13433
13434 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013435 hdd_err("Unsupported authentication type: %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013436 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13437 return -EINVAL;
13438 }
13439
13440 pWextState->roamProfile.AuthType.authType[0] =
13441 pHddStaCtx->conn_info.authType;
13442 return 0;
13443}
13444
13445/**
13446 * wlan_hdd_set_akm_suite() - set key management type
13447 * @pAdapter: Pointer to adapter
13448 * @key_mgmt: Key management type
13449 *
13450 * This function is used to set the key mgmt type(PSK/8021x).
13451 *
13452 * Return: 0 for success, non-zero for failure
13453 */
13454static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13455{
13456 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13457
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013458#ifndef WLAN_AKM_SUITE_8021X_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013459#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013460#endif
13461#ifndef WLAN_AKM_SUITE_PSK_SHA256
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013462#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
Vidyullatha Kanchanapally7b5bee02017-04-13 14:00:56 +053013463#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013464 /*set key mgmt type */
13465 switch (key_mgmt) {
13466 case WLAN_AKM_SUITE_PSK:
13467 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013468 case WLAN_AKM_SUITE_FT_PSK:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013469 hdd_debug("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013470 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13471 break;
13472
13473 case WLAN_AKM_SUITE_8021X_SHA256:
13474 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013475 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013476 hdd_debug("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013477 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13478 break;
13479#ifdef FEATURE_WLAN_ESE
13480#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13481#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13482 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013483 hdd_debug("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013484 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13485 break;
13486#endif
13487#ifndef WLAN_AKM_SUITE_OSEN
13488#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13489#endif
13490 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013491 hdd_debug("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013492 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13493 break;
13494
13495 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013496 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013497 return -EINVAL;
13498
13499 }
13500 return 0;
13501}
13502
13503/**
13504 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13505 * @pAdapter: Pointer to adapter
13506 * @cipher: Cipher type
13507 * @ucast: Unicast flag
13508 *
13509 * This function is used to set the encryption type
13510 * (NONE/WEP40/WEP104/TKIP/CCMP).
13511 *
13512 * Return: 0 for success, non-zero for failure
13513 */
13514static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13515 u32 cipher, bool ucast)
13516{
13517 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13518 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13519 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13520
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013521 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013522 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013523 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13524 } else {
13525
13526 /*set encryption method */
13527 switch (cipher) {
13528 case IW_AUTH_CIPHER_NONE:
13529 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13530 break;
13531
13532 case WLAN_CIPHER_SUITE_WEP40:
13533 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13534 break;
13535
13536 case WLAN_CIPHER_SUITE_WEP104:
13537 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13538 break;
13539
13540 case WLAN_CIPHER_SUITE_TKIP:
13541 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13542 break;
13543
13544 case WLAN_CIPHER_SUITE_CCMP:
13545 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13546 break;
13547#ifdef FEATURE_WLAN_WAPI
13548 case WLAN_CIPHER_SUITE_SMS4:
13549 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13550 break;
13551#endif
13552
13553#ifdef FEATURE_WLAN_ESE
13554 case WLAN_CIPHER_SUITE_KRK:
13555 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13556 break;
13557#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13558 case WLAN_CIPHER_SUITE_BTK:
13559 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13560 break;
13561#endif
13562#endif
13563 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013564 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013565 return -EOPNOTSUPP;
13566 }
13567 }
13568
13569 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013570 hdd_debug("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013571 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13572 pWextState->roamProfile.EncryptionType.numEntries = 1;
13573 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13574 encryptionType;
13575 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013576 hdd_debug("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013577 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13578 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13579 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13580 encryptionType;
13581 }
13582
13583 return 0;
13584}
13585
13586/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013587 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13588 * @wext_state: Pointer to wext state
13589 * @gen_ie: Pointer to IE data
13590 * @len: length of IE data
13591 *
13592 * Return: 0 for success, non-zero for failure
13593 */
13594static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13595 const uint8_t *gen_ie, uint16_t len)
13596{
13597 uint16_t cur_add_ie_len =
13598 wext_state->assocAddIE.length;
13599
13600 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13601 (wext_state->assocAddIE.length + len)) {
13602 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13603 QDF_ASSERT(0);
13604 return -ENOMEM;
13605 }
13606 memcpy(wext_state->assocAddIE.addIEdata +
13607 cur_add_ie_len, gen_ie, len);
13608 wext_state->assocAddIE.length += len;
13609
13610 wext_state->roamProfile.pAddIEAssoc =
13611 wext_state->assocAddIE.addIEdata;
13612 wext_state->roamProfile.nAddIEAssocLength =
13613 wext_state->assocAddIE.length;
13614 return 0;
13615}
13616
13617/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013618 * wlan_hdd_cfg80211_set_ie() - set IEs
13619 * @pAdapter: Pointer to adapter
13620 * @ie: Pointer ot ie
13621 * @ie: IE length
13622 *
13623 * Return: 0 for success, non-zero for failure
13624 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013625static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013626 size_t ie_len)
13627{
13628 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13629 const uint8_t *genie = ie;
13630 uint16_t remLen = ie_len;
13631#ifdef FEATURE_WLAN_WAPI
13632 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13633 u16 *tmp;
13634 uint16_t akmsuiteCount;
13635 int *akmlist;
13636#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013637 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013638
13639 /* clear previous assocAddIE */
13640 pWextState->assocAddIE.length = 0;
13641 pWextState->roamProfile.bWPSAssociation = false;
13642 pWextState->roamProfile.bOSENAssociation = false;
13643
13644 while (remLen >= 2) {
13645 uint16_t eLen = 0;
13646 uint8_t elementId;
13647 elementId = *genie++;
13648 eLen = *genie++;
13649 remLen -= 2;
13650
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013651 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013652
13653 switch (elementId) {
13654 case DOT11F_EID_WPA:
13655 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 -070013656 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013657 return -EINVAL;
13658 } else if (0 ==
13659 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13660 uint16_t curAddIELen =
13661 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013662 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013663
13664 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13665 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013666 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013667 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013668 return -ENOMEM;
13669 }
13670 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13671 memcpy(pWextState->assocAddIE.addIEdata +
13672 curAddIELen, genie - 2, eLen + 2);
13673 pWextState->assocAddIE.length += eLen + 2;
13674
13675 pWextState->roamProfile.bWPSAssociation = true;
13676 pWextState->roamProfile.pAddIEAssoc =
13677 pWextState->assocAddIE.addIEdata;
13678 pWextState->roamProfile.nAddIEAssocLength =
13679 pWextState->assocAddIE.length;
13680 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013681 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013682 memset(pWextState->WPARSNIE, 0,
13683 MAX_WPA_RSN_IE_LEN);
13684 memcpy(pWextState->WPARSNIE, genie - 2,
13685 (eLen + 2));
13686 pWextState->roamProfile.pWPAReqIE =
13687 pWextState->WPARSNIE;
13688 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13689 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13690 P2P_OUI_TYPE_SIZE))) {
13691 uint16_t curAddIELen =
13692 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013693 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013694
13695 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13696 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013697 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013698 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013699 return -ENOMEM;
13700 }
13701 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13702 memcpy(pWextState->assocAddIE.addIEdata +
13703 curAddIELen, genie - 2, eLen + 2);
13704 pWextState->assocAddIE.length += eLen + 2;
13705
13706 pWextState->roamProfile.pAddIEAssoc =
13707 pWextState->assocAddIE.addIEdata;
13708 pWextState->roamProfile.nAddIEAssocLength =
13709 pWextState->assocAddIE.length;
13710 }
13711#ifdef WLAN_FEATURE_WFD
13712 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13713 WFD_OUI_TYPE_SIZE)) &&
13714 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013715 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013716 pAdapter->device_mode)) {
13717 uint16_t curAddIELen =
13718 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013719 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013720
13721 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13722 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013723 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013724 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013725 return -ENOMEM;
13726 }
13727 /* WFD IE is saved to Additional IE ; it should
13728 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013729 * WFD IE
13730 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013731 memcpy(pWextState->assocAddIE.addIEdata +
13732 curAddIELen, genie - 2, eLen + 2);
13733 pWextState->assocAddIE.length += eLen + 2;
13734
13735 pWextState->roamProfile.pAddIEAssoc =
13736 pWextState->assocAddIE.addIEdata;
13737 pWextState->roamProfile.nAddIEAssocLength =
13738 pWextState->assocAddIE.length;
13739 }
13740#endif
13741 /* Appending HS 2.0 Indication Element in Assiciation Request */
13742 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13743 HS20_OUI_TYPE_SIZE))) {
13744 uint16_t curAddIELen =
13745 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013746 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013747
13748 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13749 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013750 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013751 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013752 return -ENOMEM;
13753 }
13754 memcpy(pWextState->assocAddIE.addIEdata +
13755 curAddIELen, genie - 2, eLen + 2);
13756 pWextState->assocAddIE.length += eLen + 2;
13757
13758 pWextState->roamProfile.pAddIEAssoc =
13759 pWextState->assocAddIE.addIEdata;
13760 pWextState->roamProfile.nAddIEAssocLength =
13761 pWextState->assocAddIE.length;
13762 }
13763 /* Appending OSEN Information Element in Assiciation Request */
13764 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13765 OSEN_OUI_TYPE_SIZE))) {
13766 uint16_t curAddIELen =
13767 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013768 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013769
13770 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13771 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013772 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013773 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013774 return -ENOMEM;
13775 }
13776 memcpy(pWextState->assocAddIE.addIEdata +
13777 curAddIELen, genie - 2, eLen + 2);
13778 pWextState->assocAddIE.length += eLen + 2;
13779
13780 pWextState->roamProfile.bOSENAssociation = true;
13781 pWextState->roamProfile.pAddIEAssoc =
13782 pWextState->assocAddIE.addIEdata;
13783 pWextState->roamProfile.nAddIEAssocLength =
13784 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013785 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
13786 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013787 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013788 status = wlan_hdd_add_assoc_ie(pWextState,
13789 genie - 2, eLen + 2);
13790 if (status)
13791 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013792 } else {
13793 uint16_t add_ie_len =
13794 pWextState->assocAddIE.length;
13795
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013796 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013797
13798 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13799 (pWextState->assocAddIE.length + eLen)) {
13800 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013801 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013802 return -ENOMEM;
13803 }
13804
13805 memcpy(pWextState->assocAddIE.addIEdata +
13806 add_ie_len, genie - 2, eLen + 2);
13807 pWextState->assocAddIE.length += eLen + 2;
13808
13809 pWextState->roamProfile.pAddIEAssoc =
13810 pWextState->assocAddIE.addIEdata;
13811 pWextState->roamProfile.nAddIEAssocLength =
13812 pWextState->assocAddIE.length;
13813 }
13814 break;
13815 case DOT11F_EID_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013816 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013817 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
13818 memcpy(pWextState->WPARSNIE, genie - 2,
13819 (eLen + 2));
13820 pWextState->roamProfile.pRSNReqIE =
13821 pWextState->WPARSNIE;
13822 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
13823 break;
13824 /*
13825 * Appending Extended Capabilities with Interworking bit set
13826 * in Assoc Req.
13827 *
13828 * In assoc req this EXT Cap will only be taken into account if
13829 * interworkingService bit is set to 1. Currently
13830 * driver is only interested in interworkingService capability
13831 * from supplicant. If in future any other EXT Cap info is
13832 * required from supplicat, it needs to be handled while
13833 * sending Assoc Req in LIM.
13834 */
13835 case DOT11F_EID_EXTCAP:
13836 {
13837 uint16_t curAddIELen =
13838 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013839 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013840
13841 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13842 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013843 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013844 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013845 return -ENOMEM;
13846 }
13847 memcpy(pWextState->assocAddIE.addIEdata +
13848 curAddIELen, genie - 2, eLen + 2);
13849 pWextState->assocAddIE.length += eLen + 2;
13850
13851 pWextState->roamProfile.pAddIEAssoc =
13852 pWextState->assocAddIE.addIEdata;
13853 pWextState->roamProfile.nAddIEAssocLength =
13854 pWextState->assocAddIE.length;
13855 break;
13856 }
13857#ifdef FEATURE_WLAN_WAPI
13858 case WLAN_EID_WAPI:
13859 /* Setting WAPI Mode to ON=1 */
13860 pAdapter->wapi_info.nWapiMode = 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013861 hdd_debug("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013862 tmp = (u16 *) ie;
13863 tmp = tmp + 2; /* Skip element Id and Len, Version */
13864 akmsuiteCount = WPA_GET_LE16(tmp);
13865 tmp = tmp + 1;
13866 akmlist = (int *)(tmp);
13867 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
13868 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
13869 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013870 hdd_err("Invalid akmSuite count: %u",
13871 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013872 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013873 return -EINVAL;
13874 }
13875
13876 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013877 hdd_debug("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013878 pAdapter->wapi_info.wapiAuthMode =
13879 WAPI_AUTH_MODE_PSK;
13880 }
13881 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013882 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013883 pAdapter->wapi_info.wapiAuthMode =
13884 WAPI_AUTH_MODE_CERT;
13885 }
13886 break;
13887#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013888 case DOT11F_EID_SUPPOPERATINGCLASSES:
13889 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013890 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013891 status = wlan_hdd_add_assoc_ie(pWextState,
13892 genie - 2, eLen + 2);
13893 if (status)
13894 return status;
13895 break;
13896 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013897 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013898 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013899 /* when Unknown IE is received we break
13900 * and continue to the next IE in the buffer
13901 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013902 break;
13903 }
13904 genie += eLen;
13905 remLen -= eLen;
13906 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013907 return 0;
13908}
13909
13910/**
13911 * hdd_is_wpaie_present() - check for WPA ie
13912 * @ie: Pointer to ie
13913 * @ie_len: Ie length
13914 *
13915 * Parse the received IE to find the WPA IE
13916 *
13917 * Return: true if wpa ie is found else false
13918 */
13919static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
13920{
13921 uint8_t eLen = 0;
13922 uint16_t remLen = ie_len;
13923 uint8_t elementId = 0;
13924
13925 while (remLen >= 2) {
13926 elementId = *ie++;
13927 eLen = *ie++;
13928 remLen -= 2;
13929 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013930 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013931 return false;
13932 }
13933 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
13934 /* OUI - 0x00 0X50 0XF2
13935 * WPA Information Element - 0x01
13936 * WPA version - 0x01
13937 */
13938 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
13939 return true;
13940 }
13941 ie += eLen;
13942 remLen -= eLen;
13943 }
13944 return false;
13945}
13946
13947/**
13948 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
13949 * @pAdapter: Pointer to adapter
13950 * @req: Pointer to security parameters
13951 *
13952 * Return: 0 for success, non-zero for failure
13953 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013954static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
13955 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013956{
13957 int status = 0;
13958 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13959 ENTER();
13960
13961 /*set wpa version */
13962 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
13963
13964 if (req->crypto.wpa_versions) {
13965 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
13966 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
13967 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
13968 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13969 }
13970 }
13971
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013972 hdd_debug("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013973
13974 /*set authentication type */
13975 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
13976
13977 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013978 hdd_err("Failed to set authentication type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013979 return status;
13980 }
13981
13982 /*set key mgmt type */
13983 if (req->crypto.n_akm_suites) {
13984 status =
13985 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
13986 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013987 hdd_err("Failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013988 return status;
13989 }
13990 }
13991
13992 /*set pairwise cipher type */
13993 if (req->crypto.n_ciphers_pairwise) {
13994 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
13995 req->crypto.
13996 ciphers_pairwise[0],
13997 true);
13998 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013999 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014000 return status;
14001 }
14002 } else {
14003 /*Reset previous cipher suite to none */
14004 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
14005 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014006 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014007 return status;
14008 }
14009 }
14010
14011 /*set group cipher type */
14012 status =
14013 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
14014 false);
14015
14016 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014017 hdd_err("Failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014018 return status;
14019 }
14020#ifdef WLAN_FEATURE_11W
14021 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
14022#endif
14023
14024 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
14025 if (req->ie_len) {
14026 status =
14027 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
14028 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014029 hdd_err("Failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014030 return status;
14031 }
14032 }
14033
14034 /*incase of WEP set default key information */
14035 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080014036 u8 key_len = req->key_len;
14037 u8 key_idx = req->key_idx;
14038
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014039 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
14040 || (WLAN_CIPHER_SUITE_WEP104 ==
14041 req->crypto.ciphers_pairwise[0])
14042 ) {
14043 if (IW_AUTH_KEY_MGMT_802_1X
14044 ==
14045 (pWextState->
14046 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014047 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014048 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080014049 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014050
Jeff Johnson68755312017-02-10 11:46:55 -080014051 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
14052 && (CSR_MAX_NUM_KEY > key_idx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014053 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson68755312017-02-10 11:46:55 -080014054 key_idx, key_len);
14055 qdf_mem_copy(&pWextState->roamProfile.
14056 Keys.
14057 KeyMaterial[key_idx][0],
14058 req->key, key_len);
14059 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014060 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080014061 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014062 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014063 }
14064 }
14065 }
14066
14067 return status;
14068}
14069
Agrawal Ashish3d000b42017-02-07 13:44:50 +053014070int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014071{
14072 unsigned long rc;
14073 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014074 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014075 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014076
14077 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014078 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14079 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014080 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014081 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
14082 }
14083 /*
14084 * If firmware has already started roaming process, driver
14085 * needs to defer the processing of this disconnect request.
14086 *
14087 */
14088 if (hdd_is_roaming_in_progress(pAdapter)) {
14089 /*
14090 * Defer the disconnect action until firmware roaming
14091 * result is received. If STA is in connected state after
14092 * that, send the disconnect command to CSR, otherwise
14093 * CSR would have already sent disconnect event to upper
14094 * layer.
14095 */
14096
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014097 hdd_warn("Roaming in progress, <try disconnect> deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014098 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
14099 pAdapter->cfg80211_disconnect_reason =
14100 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14101 return 0;
14102 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014103
Jeff Johnson9edf9572016-10-03 15:24:49 -070014104 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053014105 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
14106 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
14107 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014108 hdd_conn_set_connection_state(pAdapter,
14109 eConnectionState_Disconnecting);
14110 /* Issue disconnect to CSR */
14111 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014112
14113 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14114 pAdapter->sessionId,
14115 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14116 /*
14117 * Wait here instead of returning directly, this will block the
14118 * next connect command and allow processing of the scan for
14119 * ssid and the previous connect command in CSR. Else we might
14120 * hit some race conditions leading to SME and HDD out of sync.
14121 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014122 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014123 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014124 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014125 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014126 (int)status);
14127 pHddStaCtx->staDebugState = status;
14128 result = -EINVAL;
14129 goto disconnected;
14130 }
14131
14132 rc = wait_for_completion_timeout(
14133 &pAdapter->disconnect_comp_var,
14134 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014135 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014136 hdd_err("Sme disconnect event timed out session Id: %d staDebugState: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014137 pAdapter->sessionId, pHddStaCtx->staDebugState);
14138 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014139 }
14140 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014141 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014142 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014143 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014144 if (!rc) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014145 hdd_err("Disconnect event timed out session Id: %d staDebugState: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014146 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014147 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014148 }
14149 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014150disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014151 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14152 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014153}
14154
14155/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014156 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14157 * @adapter: Pointer to the HDD adapter
14158 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014159 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014160 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014161 * This function will start reassociation if prev_bssid is set and bssid/
14162 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014163 *
Naveen Rawat07332902016-07-27 09:13:17 -070014164 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014165 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014166#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14167 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014168static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14169 struct cfg80211_connect_params *req,
14170 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014171{
Naveen Rawat07332902016-07-27 09:13:17 -070014172 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014173 const uint8_t *bssid = NULL;
14174 uint16_t channel = 0;
14175
14176 if (req->bssid)
14177 bssid = req->bssid;
14178 else if (req->bssid_hint)
14179 bssid = req->bssid_hint;
14180
14181 if (req->channel)
14182 channel = req->channel->hw_value;
14183 else if (req->channel_hint)
14184 channel = req->channel_hint->hw_value;
14185
14186 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014187 reassoc = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014188 hdd_debug(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014189 channel, MAC_ADDR_ARRAY(bssid));
14190 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014191 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014192 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014193 }
Naveen Rawat07332902016-07-27 09:13:17 -070014194 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014195}
14196#else
Naveen Rawat07332902016-07-27 09:13:17 -070014197static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14198 struct cfg80211_connect_params *req,
14199 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014200{
Naveen Rawat07332902016-07-27 09:13:17 -070014201 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014202}
14203#endif
14204
14205/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014206 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
14207 * @wiphy: Pointer to wiphy
14208 * @dev: Pointer to network device
14209 * @req: Pointer to cfg80211 connect request
14210 *
14211 * This function is used to start the association process
14212 *
14213 * Return: 0 for success, non-zero for failure
14214 */
14215static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14216 struct net_device *ndev,
14217 struct cfg80211_connect_params *req)
14218{
14219 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014220 u16 channel;
14221#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14222 const u8 *bssid_hint = req->bssid_hint;
14223#else
14224 const u8 *bssid_hint = NULL;
14225#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014226 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14227 hdd_context_t *pHddCtx;
14228
14229 ENTER();
14230
Anurag Chouhan6d760662016-02-20 16:05:43 +053014231 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014232 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014233 return -EINVAL;
14234 }
14235
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014236 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14237 hdd_err("invalid session id: %d", pAdapter->sessionId);
14238 return -EINVAL;
14239 }
14240
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014241 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014242 TRACE_CODE_HDD_CFG80211_CONNECT,
14243 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014244 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014245 hdd_device_mode_to_string(pAdapter->device_mode),
14246 pAdapter->device_mode);
14247
Krunal Sonib4326f22016-03-10 13:05:51 -080014248 if (pAdapter->device_mode != QDF_STA_MODE &&
14249 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014250 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014251 hdd_device_mode_to_string(pAdapter->device_mode),
14252 pAdapter->device_mode);
14253 return -EINVAL;
14254 }
14255
14256 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14257 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014258 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014259 return -EINVAL;
14260 }
14261
14262 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014263 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014264 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014265
Naveen Rawat07332902016-07-27 09:13:17 -070014266 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014267 return status;
14268
Agrawal Ashishf156e942016-08-04 14:54:47 +053014269 /* Try disconnecting if already in connected state */
14270 status = wlan_hdd_try_disconnect(pAdapter);
14271 if (0 > status) {
14272 hdd_err("Failed to disconnect the existing connection");
14273 return -EALREADY;
14274 }
14275
14276 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014277 if (req->channel) {
Ajit Pal Singh90a45a42017-04-18 18:53:46 +053014278 bool ok;
14279
14280 if (req->channel->hw_value && policy_mgr_is_chan_ok_for_dnbs(
14281 pHddCtx->hdd_psoc,
14282 req->channel->hw_value,
14283 &ok)) {
14284 hdd_warn("Unable to get channel:%d eligibility for DNBS",
14285 req->channel->hw_value);
14286 return -EINVAL;
14287 }
14288 /**
14289 * Send connection timedout, so that Android framework does not
14290 * blacklist us.
14291 */
14292 if (!ok) {
14293 struct ieee80211_channel *chan =
14294 __ieee80211_get_channel(wiphy,
14295 wlan_chan_to_freq(req->channel->hw_value));
14296 struct cfg80211_bss *bss;
14297
14298 hdd_warn("Channel:%d not OK for DNBS",
14299 req->channel->hw_value);
14300 if (chan) {
14301 bss = hdd_cfg80211_get_bss(wiphy,
14302 chan,
14303 req->bssid, req->ssid,
14304 req->ssid_len);
14305 if (bss) {
14306 cfg80211_assoc_timeout(ndev, bss);
14307 return -ETIMEDOUT;
14308 }
14309 }
14310 return -EINVAL;
14311 }
14312
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014313 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14314 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014315 pAdapter->device_mode),
14316 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014317 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014318 return -ECONNREFUSED;
14319 }
14320 } else {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014321 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14322 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014323 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014324 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014325 return -ECONNREFUSED;
14326 }
14327 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014328
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014329 /*initialise security parameters */
14330 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14331
14332 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014333 hdd_err("Failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014334 return status;
14335 }
14336
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014337 if (req->channel)
14338 channel = req->channel->hw_value;
14339 else
14340 channel = 0;
14341 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14342 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014343 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014344 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014345 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014346 return status;
14347 }
14348 EXIT();
14349 return status;
14350}
14351
14352/**
14353 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14354 * @wiphy: Pointer to wiphy
14355 * @dev: Pointer to network device
14356 * @req: Pointer to cfg80211 connect request
14357 *
14358 * Return: 0 for success, non-zero for failure
14359 */
14360static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14361 struct net_device *ndev,
14362 struct cfg80211_connect_params *req)
14363{
14364 int ret;
14365 cds_ssr_protect(__func__);
14366 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14367 cds_ssr_unprotect(__func__);
14368
14369 return ret;
14370}
14371
14372/**
14373 * wlan_hdd_disconnect() - hdd disconnect api
14374 * @pAdapter: Pointer to adapter
14375 * @reason: Disconnect reason code
14376 *
14377 * This function is used to issue a disconnect request to SME
14378 *
14379 * Return: 0 for success, non-zero for failure
14380 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014381static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014382{
14383 int status, result = 0;
14384 unsigned long rc;
14385 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14386 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014387 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014388 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014389
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014390 ENTER();
14391
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014392 status = wlan_hdd_validate_context(pHddCtx);
14393
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014394 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014395 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014396 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014397 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014398 status = sme_stop_roaming(hal, pAdapter->sessionId,
14399 eCsrHddIssued);
14400 }
14401 /*
14402 * If firmware has already started roaming process, driver
14403 * needs to defer the processing of this disconnect request.
14404 */
14405 if (hdd_is_roaming_in_progress(pAdapter)) {
14406 /*
14407 * Defer the disconnect action until firmware roaming
14408 * result is received. If STA is in connected state after
14409 * that, send the disconnect command to CSR, otherwise
14410 * CSR would have already sent disconnect event to upper
14411 * layer.
14412 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014413 hdd_warn("Roaming in progress, disconnect command deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014414 pAdapter->defer_disconnect =
14415 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14416 pAdapter->cfg80211_disconnect_reason = reason;
14417 return 0;
14418 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014419
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014420 prev_conn_state = pHddStaCtx->conn_info.connState;
14421
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014422 /* stop tx queues */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014423 hdd_debug("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014424 wlan_hdd_netif_queue_control(pAdapter,
Himanshu Agarwal865201d2017-04-12 15:45:31 +053014425 WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014426 hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014427 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14428 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14429
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014430 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014431
14432 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14433 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014434 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14435 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014436 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014437 result = 0;
14438 goto disconnected;
14439 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14440 /*
14441 * Wait here instead of returning directly, this will block the
14442 * next connect command and allow processing of the scan for
14443 * ssid and the previous connect command in CSR. Else we might
14444 * hit some race conditions leading to SME and HDD out of sync.
14445 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014446 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014447 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014448 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014449 pHddStaCtx->staDebugState = status;
14450 result = -EINVAL;
14451 goto disconnected;
14452 }
14453 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14454 msecs_to_jiffies
14455 (WLAN_WAIT_TIME_DISCONNECT));
14456
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014457 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014458 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014459 result = -ETIMEDOUT;
14460 }
14461disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014462 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14463#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14464 /* Sending disconnect event to userspace for kernel version < 3.11
14465 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14466 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014467 hdd_debug("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014468 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14469 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014470#endif
14471
14472 return result;
14473}
14474
14475/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014476 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14477 * @reason: ieee80211 reason code.
14478 *
14479 * This utility function helps log string conversion of reason code.
14480 *
14481 * Return: string conversion of reason code, if match found;
14482 * "Unknown" otherwise.
14483 */
14484static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14485{
14486 switch (reason) {
14487 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14488 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14489 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14490 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14491 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14492 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14493 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14494 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14495 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14496 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14497 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14498 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14499 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14500 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14501 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14502 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14503 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14504 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14505 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14506 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14507 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14508 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14509 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14510 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14511 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14512 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14513 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14514 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14515 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14516 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14517 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14518 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14519 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14520 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14521 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14522 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14523 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14524 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14525 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14526 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14527 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14528 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14529 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14530 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14531 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14532 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14533 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14534 default:
14535 return "Unknown";
14536 }
14537}
14538
14539/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014540 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14541 * @wiphy: Pointer to wiphy
14542 * @dev: Pointer to network device
14543 * @reason: Disconnect reason code
14544 *
14545 * This function is used to issue a disconnect request to SME
14546 *
14547 * Return: 0 for success, non-zero for failure
14548 */
14549static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14550 struct net_device *dev, u16 reason)
14551{
14552 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14553 int status;
14554 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14555 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14556#ifdef FEATURE_WLAN_TDLS
14557 uint8_t staIdx;
14558#endif
14559
14560 ENTER();
14561
Anurag Chouhan6d760662016-02-20 16:05:43 +053014562 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014563 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014564 return -EINVAL;
14565 }
14566
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014567 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014568 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014569 return -EINVAL;
14570 }
14571
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014572 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014573 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14574 pAdapter->sessionId, reason));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014575 hdd_debug("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014576 hdd_device_mode_to_string(pAdapter->device_mode),
14577 pAdapter->device_mode, reason);
14578
14579 status = wlan_hdd_validate_context(pHddCtx);
14580
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014581 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014582 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014583
14584 /* Issue disconnect request to SME, if station is in connected state */
14585 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14586 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14587 eCsrRoamDisconnectReason reasonCode =
14588 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14589 hdd_scaninfo_t *pScanInfo;
14590
14591 switch (reason) {
14592 case WLAN_REASON_MIC_FAILURE:
14593 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14594 break;
14595
14596 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14597 case WLAN_REASON_DISASSOC_AP_BUSY:
14598 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14599 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14600 break;
14601
14602 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14603 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14604 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14605 break;
14606
14607 case WLAN_REASON_DEAUTH_LEAVING:
14608 reasonCode =
14609 pHddCtx->config->
14610 gEnableDeauthToDisassocMap ?
14611 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14612 eCSR_DISCONNECT_REASON_DEAUTH;
14613 break;
14614 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14615 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14616 break;
14617 default:
14618 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14619 break;
14620 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014621 pScanInfo = &pAdapter->scan_info;
14622 if (pScanInfo->mScanPending) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014623 hdd_debug("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014624 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014625 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014626 eCSR_SCAN_ABORT_DEFAULT);
14627 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014628 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014629#ifdef FEATURE_WLAN_TDLS
14630 /* First clean up the tdls peers if any */
14631 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14632 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14633 pAdapter->sessionId)
14634 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14635 uint8_t *mac;
14636 mac =
14637 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014638 hdd_debug("call sme_delete_tdls_peer_sta staId %d sessionId %d "
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014639 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014640 pHddCtx->tdlsConnInfo[staIdx].staId,
14641 pAdapter->sessionId,
14642 MAC_ADDR_ARRAY(mac));
14643 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14644 (pAdapter),
14645 pAdapter->sessionId, mac);
14646 }
14647 }
14648#endif
Srinivas Girigowdaf620d482017-04-06 19:03:20 -070014649 hdd_info("Disconnect request from user space with reason: %d (%s) internal reason code: %d",
14650 reason, hdd_ieee80211_reason_code_to_str(reason), reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014651 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14652 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014653 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014654 return -EINVAL;
14655 }
14656 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014657 hdd_err("Unexpected cfg disconnect called while in state: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014658 pHddStaCtx->conn_info.connState);
14659 }
14660
14661 return status;
14662}
14663
14664/**
14665 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14666 * @wiphy: Pointer to wiphy
14667 * @dev: Pointer to network device
14668 * @reason: Disconnect reason code
14669 *
14670 * Return: 0 for success, non-zero for failure
14671 */
14672static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14673 struct net_device *dev, u16 reason)
14674{
14675 int ret;
14676 cds_ssr_protect(__func__);
14677 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14678 cds_ssr_unprotect(__func__);
14679
14680 return ret;
14681}
14682
14683/**
14684 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14685 * @pAdapter: Pointer to adapter
14686 * @param: Pointer to IBSS parameters
14687 *
14688 * This function is used to initialize the security settings in IBSS mode
14689 *
14690 * Return: 0 for success, non-zero for failure
14691 */
14692static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14693 struct cfg80211_ibss_params
14694 *params)
14695{
14696 int status = 0;
14697 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14698 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14699 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14700
14701 ENTER();
14702
14703 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014704 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014705 pHddStaCtx->ibss_enc_key_installed = 0;
14706
14707 if (params->ie_len && (NULL != params->ie)) {
14708 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14709 params->ie_len, WLAN_EID_RSN)) {
14710 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14711 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14712 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14713 tDot11fIEWPA dot11WPAIE;
14714 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14715 u8 *ie;
14716
14717 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14718 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14719 params->ie_len,
14720 DOT11F_EID_WPA);
14721 if (NULL != ie) {
14722 pWextState->wpaVersion =
14723 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014724 /* Unpack the WPA IE
14725 * Skip past the EID byte and length byte
14726 * and four byte WiFi OUI
14727 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014728 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
Selvaraj, Sridhar75afbeb2017-04-03 17:08:59 +053014729 &ie[2 + 4], ie[1] - 4,
14730 &dot11WPAIE, false);
14731 /*
14732 * Extract the multicast cipher, the
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014733 * encType for unicast cipher for
14734 * wpa-none is none
14735 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014736 encryptionType =
14737 hdd_translate_wpa_to_csr_encryption_type
14738 (dot11WPAIE.multicast_cipher);
14739 }
14740 }
14741
14742 status =
14743 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14744 params->ie_len);
14745
14746 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014747 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014748 return status;
14749 }
14750 }
14751
14752 pWextState->roamProfile.AuthType.authType[0] =
14753 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14754
14755 if (params->privacy) {
14756 /* Security enabled IBSS, At this time there is no information
14757 * available about the security paramters, so initialise the
14758 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14759 * The correct security parameters will be updated later in
14760 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14761 * set inorder enable privacy bit in beacons
14762 */
14763
14764 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14765 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014766 hdd_debug("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014767 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14768 pWextState->roamProfile.EncryptionType.numEntries = 1;
14769 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14770 encryptionType;
14771 return status;
14772}
14773
14774/**
14775 * __wlan_hdd_cfg80211_join_ibss() - join ibss
14776 * @wiphy: Pointer to wiphy
14777 * @dev: Pointer to network device
14778 * @param: Pointer to IBSS join parameters
14779 *
14780 * This function is used to create/join an IBSS network
14781 *
14782 * Return: 0 for success, non-zero for failure
14783 */
14784static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14785 struct net_device *dev,
14786 struct cfg80211_ibss_params *params)
14787{
14788 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14789 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14790 tCsrRoamProfile *pRoamProfile;
14791 int status;
14792 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14793 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053014794 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014795 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014796
14797 ENTER();
14798
Anurag Chouhan6d760662016-02-20 16:05:43 +053014799 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014800 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014801 return -EINVAL;
14802 }
14803
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014804 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014805 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014806 return -EINVAL;
14807 }
14808
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014809 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014810 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
14811 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014812 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014813 hdd_device_mode_to_string(pAdapter->device_mode),
14814 pAdapter->device_mode);
14815
14816 status = wlan_hdd_validate_context(pHddCtx);
14817
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014818 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014819 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014820
14821 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053014822 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014823 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14824 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
14825 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14826 int indx;
14827
14828 /* Get channel number */
14829 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014830 params->
14831 chandef.
14832 chan->
14833 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014834
14835 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14836 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014837 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014838 return -EOPNOTSUPP;
14839 }
14840
14841 for (indx = 0; indx < numChans; indx++) {
14842 if (channelNum == validChan[indx]) {
14843 break;
14844 }
14845 }
14846 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014847 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014848 return -EINVAL;
14849 }
14850 }
14851
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014852 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14853 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014854 hdd_err("This concurrency combination is not allowed");
14855 return -ECONNREFUSED;
14856 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014857
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014858 status = policy_mgr_reset_connection_update(pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014859 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014860 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014861
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014862 status = policy_mgr_current_connections_update(pHddCtx->hdd_psoc,
14863 pAdapter->sessionId, channelNum,
Krunal Soni3091bcc2016-06-23 12:28:21 -070014864 SIR_UPDATE_REASON_JOIN_IBSS);
14865 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014866 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070014867 return -EINVAL;
14868 }
14869
14870 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014871 status = policy_mgr_wait_for_connection_update(
14872 pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014873 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014874 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014875 return -EINVAL;
14876 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014877 }
14878
14879 /*Try disconnecting if already in connected state */
14880 status = wlan_hdd_try_disconnect(pAdapter);
14881 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014882 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014883 return -EALREADY;
14884 }
14885
14886 pRoamProfile = &pWextState->roamProfile;
14887
14888 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014889 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014890 return -EINVAL;
14891 }
14892
14893 /* enable selected protection checks in IBSS mode */
14894 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
14895
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014896 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014897 WNI_CFG_IBSS_ATIM_WIN_SIZE,
14898 pHddCtx->config->
14899 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014900 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014901 }
14902
14903 /* BSSID is provided by upper layers hence no need to AUTO generate */
14904 if (NULL != params->bssid) {
14905 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014906 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014907 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014908 return -EIO;
14909 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014910 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014911 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
14912 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014913 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014914 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014915 return -EIO;
14916 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053014917 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014918 }
14919 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
14920 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
14921 pRoamProfile->beaconInterval = params->beacon_interval;
14922 else {
14923 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014924 hdd_debug("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014925 params->beacon_interval, pRoamProfile->beaconInterval);
14926 }
14927
14928 /* Set Channel */
14929 if (channelNum) {
14930 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014931 hdd_debug("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014932 pRoamProfile->ChannelInfo.numOfChannels = 1;
14933 pHddStaCtx->conn_info.operationChannel = channelNum;
14934 pRoamProfile->ChannelInfo.ChannelList =
14935 &pHddStaCtx->conn_info.operationChannel;
14936 }
14937
14938 /* Initialize security parameters */
14939 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
14940 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014941 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014942 return status;
14943 }
14944
14945 /* Issue connect start */
14946 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
14947 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014948 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014949 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014950 operationChannel,
14951 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014952
14953 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014954 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014955 return status;
14956 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014957 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014958 return 0;
14959}
14960
14961/**
14962 * wlan_hdd_cfg80211_join_ibss() - join ibss
14963 * @wiphy: Pointer to wiphy
14964 * @dev: Pointer to network device
14965 * @param: Pointer to IBSS join parameters
14966 *
14967 * This function is used to create/join an IBSS network
14968 *
14969 * Return: 0 for success, non-zero for failure
14970 */
14971static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14972 struct net_device *dev,
14973 struct cfg80211_ibss_params *params)
14974{
14975 int ret = 0;
14976
14977 cds_ssr_protect(__func__);
14978 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
14979 cds_ssr_unprotect(__func__);
14980
14981 return ret;
14982}
14983
14984/**
14985 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
14986 * @wiphy: Pointer to wiphy
14987 * @dev: Pointer to network device
14988 *
14989 * This function is used to leave an IBSS network
14990 *
14991 * Return: 0 for success, non-zero for failure
14992 */
14993static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14994 struct net_device *dev)
14995{
14996 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14997 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14998 tCsrRoamProfile *pRoamProfile;
14999 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15000 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015001 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053015002 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015003 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015004
15005 ENTER();
15006
Anurag Chouhan6d760662016-02-20 16:05:43 +053015007 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015008 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015009 return -EINVAL;
15010 }
15011
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015012 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015013 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015014 return -EINVAL;
15015 }
15016
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015017 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015018 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
15019 pAdapter->sessionId,
15020 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
15021 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015022 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015023 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015024
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015025 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015026 hdd_device_mode_to_string(pAdapter->device_mode),
15027 pAdapter->device_mode);
15028 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015029 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015030 return -EIO;
15031 }
15032
15033 pRoamProfile = &pWextState->roamProfile;
15034
15035 /* Issue disconnect only if interface type is set to IBSS */
15036 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015037 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015038 return -EINVAL;
15039 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015040 /* Clearing add IE of beacon */
15041 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
15042 sizeof(tSirMacAddr));
15043 updateIE.smeSessionId = pAdapter->sessionId;
15044 updateIE.ieBufferlength = 0;
15045 updateIE.pAdditionIEBuffer = NULL;
15046 updateIE.append = true;
15047 updateIE.notify = true;
15048 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
15049 &updateIE,
15050 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015051 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080015052 }
15053
15054 /* Reset WNI_CFG_PROBE_RSP Flags */
15055 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015056
15057 /* Issue Disconnect request */
15058 INIT_COMPLETION(pAdapter->disconnect_comp_var);
15059 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
15060 pAdapter->sessionId,
15061 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015062 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015063 hdd_err("sme_roam_disconnect failed status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015064 hal_status);
15065 return -EAGAIN;
15066 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053015067
15068 /* wait for mc thread to cleanup and then return to upper stack
15069 * so by the time upper layer calls the change interface, we are
15070 * all set to proceed further
15071 */
15072 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
15073 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
15074 if (!rc) {
15075 hdd_err("Failed to disconnect, timed out");
15076 return -ETIMEDOUT;
15077 }
15078
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015079 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015080 return 0;
15081}
15082
15083/**
15084 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
15085 * @wiphy: Pointer to wiphy
15086 * @dev: Pointer to network device
15087 *
15088 * This function is used to leave an IBSS network
15089 *
15090 * Return: 0 for success, non-zero for failure
15091 */
15092static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
15093 struct net_device *dev)
15094{
15095 int ret = 0;
15096
15097 cds_ssr_protect(__func__);
15098 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
15099 cds_ssr_unprotect(__func__);
15100
15101 return ret;
15102}
15103
15104/**
15105 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15106 * @wiphy: Pointer to wiphy
15107 * @changed: Parameters changed
15108 *
15109 * This function is used to set the phy parameters. RTS Threshold/FRAG
15110 * Threshold/Retry Count etc.
15111 *
15112 * Return: 0 for success, non-zero for failure
15113 */
15114static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
15115 u32 changed)
15116{
15117 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15118 tHalHandle hHal = pHddCtx->hHal;
15119 int status;
15120
15121 ENTER();
15122
Anurag Chouhan6d760662016-02-20 16:05:43 +053015123 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015124 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015125 return -EINVAL;
15126 }
15127
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015128 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015129 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
15130 NO_SESSION, wiphy->rts_threshold));
15131 status = wlan_hdd_validate_context(pHddCtx);
15132
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015133 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015134 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015135
15136 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
15137 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
15138 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
15139
15140 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
15141 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015142 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015143 rts_threshold);
15144 return -EINVAL;
15145 }
15146
15147 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
15148 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015149 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015150 rts_threshold);
15151 return -EIO;
15152 }
15153
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015154 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015155 }
15156
15157 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
15158 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
15159 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
15160 wiphy->frag_threshold;
15161
15162 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
15163 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015164 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015165 frag_threshold);
15166 return -EINVAL;
15167 }
15168
15169 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15170 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015171 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015172 frag_threshold);
15173 return -EIO;
15174 }
15175
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015176 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015177 }
15178
15179 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15180 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15181 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15182 wiphy->retry_short : wiphy->retry_long;
15183
15184 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15185 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015186 hdd_err("Invalid Retry count: %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015187 return -EINVAL;
15188 }
15189
15190 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15191 if (0 != sme_cfg_set_int(hHal,
15192 WNI_CFG_LONG_RETRY_LIMIT,
15193 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015194 hdd_err("sme_cfg_set_int failed for long retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015195 retry_value);
15196 return -EIO;
15197 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015198 hdd_debug("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015199 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15200 if (0 != sme_cfg_set_int(hHal,
15201 WNI_CFG_SHORT_RETRY_LIMIT,
15202 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015203 hdd_err("sme_cfg_set_int failed for short retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015204 retry_value);
15205 return -EIO;
15206 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015207 hdd_debug("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015208 }
15209 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015210 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015211 return 0;
15212}
15213
15214/**
15215 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15216 * @wiphy: Pointer to wiphy
15217 * @changed: Parameters changed
15218 *
15219 * Return: 0 for success, non-zero for failure
15220 */
15221static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15222{
15223 int ret;
15224
15225 cds_ssr_protect(__func__);
15226 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15227 cds_ssr_unprotect(__func__);
15228
15229 return ret;
15230}
15231
15232/**
15233 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15234 * key
15235 * @wiphy: Pointer to wiphy
15236 * @dev: Pointer to network device
15237 * @key_index: Key index
15238 *
15239 * Return: 0
15240 */
15241static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15242 struct net_device *netdev,
15243 u8 key_index)
15244{
15245 ENTER();
15246 return 0;
15247}
15248
15249/**
15250 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15251 * wlan_hdd_set_default_mgmt_key
15252 * @wiphy: pointer to wiphy
15253 * @netdev: pointer to net_device structure
15254 * @key_index: key index
15255 *
15256 * Return: 0 on success, error number on failure
15257 */
15258static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15259 struct net_device *netdev,
15260 u8 key_index)
15261{
15262 int ret;
15263
15264 cds_ssr_protect(__func__);
15265 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15266 cds_ssr_unprotect(__func__);
15267
15268 return ret;
15269}
15270
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015271/**
15272 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15273 * @wiphy: Pointer to wiphy
15274 * @dev: Pointer to network device
15275 * @params: Pointer to tx queue parameters
15276 *
15277 * Return: 0
15278 */
15279static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15280 struct net_device *dev,
15281 struct ieee80211_txq_params *params)
15282{
15283 ENTER();
15284 return 0;
15285}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015286
15287/**
15288 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15289 * @wiphy: pointer to wiphy
15290 * @netdev: pointer to net_device structure
15291 * @params: pointer to ieee80211_txq_params
15292 *
15293 * Return: 0 on success, error number on failure
15294 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015295static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15296 struct net_device *dev,
15297 struct ieee80211_txq_params *params)
15298{
15299 int ret;
15300
15301 cds_ssr_protect(__func__);
15302 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15303 cds_ssr_unprotect(__func__);
15304
15305 return ret;
15306}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015307
15308/**
15309 * __wlan_hdd_cfg80211_del_station() - delete station v2
15310 * @wiphy: Pointer to wiphy
15311 * @param: Pointer to delete station parameter
15312 *
15313 * Return: 0 for success, non-zero for failure
15314 */
15315static
15316int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15317 struct net_device *dev,
15318 struct tagCsrDelStaParams *pDelStaParams)
15319{
15320 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15321 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015322 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015323 hdd_hostapd_state_t *hapd_state;
15324 int status;
15325 uint8_t staId;
15326 uint8_t *mac;
15327
15328 ENTER();
15329
Anurag Chouhan6d760662016-02-20 16:05:43 +053015330 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015331 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015332 return -EINVAL;
15333 }
15334
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015335 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015336 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015337 return -EINVAL;
15338 }
15339
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015340 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015341 TRACE_CODE_HDD_CFG80211_DEL_STA,
15342 pAdapter->sessionId, pAdapter->device_mode));
15343
15344 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15345 status = wlan_hdd_validate_context(pHddCtx);
15346
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015347 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015348 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015349
15350 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15351
Krunal Sonib4326f22016-03-10 13:05:51 -080015352 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15353 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015354
15355 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15356 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015357 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015358 return 0;
15359 }
15360
Anurag Chouhanc5548422016-02-24 18:33:27 +053015361 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015362 uint16_t i;
15363 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15364 if ((pAdapter->aStaInfo[i].isUsed) &&
15365 (!pAdapter->aStaInfo[i].
15366 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015367 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015368 mac,
15369 pAdapter->aStaInfo[i].
15370 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015371 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015372 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15373 hdd_ipa_wlan_evt(pAdapter,
15374 pAdapter->
15375 aStaInfo[i].
15376 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015377 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015378 mac);
15379 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015380 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015381 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015382 MAC_ADDR_ARRAY(mac));
15383
15384 if (pHddCtx->dev_dfs_cac_status ==
15385 DFS_CAC_IN_PROGRESS)
15386 goto fn_end;
15387
Wei Song2f76f642016-11-18 16:32:53 +080015388 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015389 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015390 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015391 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015392 hdd_softap_sta_deauth(pAdapter,
15393 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015394 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015395 pAdapter->aStaInfo[i].
15396 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015397 qdf_status =
15398 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015399 &hapd_state->
15400 qdf_sta_disassoc_event,
15401 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015402 if (!QDF_IS_STATUS_SUCCESS(
15403 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015404 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015405 }
15406 }
15407 }
15408 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015409 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015410 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015411 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015412 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015413 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015414 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015415 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015416 MAC_ADDR_ARRAY(mac));
15417 return -ENOENT;
15418 }
15419
15420 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15421 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015422 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015423 }
15424
15425 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15426 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015427 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015428 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015429 MAC_ADDR_ARRAY(mac));
15430 return -ENOENT;
15431 }
15432
15433 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15434
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015435 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015436 MAC_ADDR_ARRAY(mac));
15437
15438 /* Case: SAP in ACS selected DFS ch and client connected
15439 * Now Radar detected. Then if random channel is another
15440 * DFS ch then new CAC is initiated and no TX allowed.
15441 * So do not send any mgmt frames as it will timeout
15442 * during CAC.
15443 */
15444
15445 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15446 goto fn_end;
15447
Wei Song2f76f642016-11-18 16:32:53 +080015448 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015449 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15450 (pAdapter), pAdapter->sessionId,
15451 (uint8_t *)&pDelStaParams->peerMacAddr,
15452 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015453 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015454 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015455 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015456 pAdapter->aStaInfo[staId].isDeauthInProgress =
15457 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015458 hdd_debug("STA removal failed for ::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015459 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015460 MAC_ADDR_ARRAY(mac));
15461 return -ENOENT;
15462 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015463 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015464 &hapd_state->
15465 qdf_sta_disassoc_event,
15466 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015467 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015468 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015469 }
15470 }
15471 }
15472
15473fn_end:
15474 EXIT();
15475 return 0;
15476}
15477
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015478#if defined(USE_CFG80211_DEL_STA_V2)
15479/**
15480 * wlan_hdd_del_station() - delete station wrapper
15481 * @adapter: pointer to the hdd adapter
15482 *
15483 * Return: None
15484 */
15485void wlan_hdd_del_station(hdd_adapter_t *adapter)
15486{
15487 struct station_del_parameters del_sta;
15488 del_sta.mac = NULL;
15489 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15490 del_sta.reason_code = eCsrForcedDeauthSta;
15491
15492 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15493 &del_sta);
15494}
15495#else
15496void wlan_hdd_del_station(hdd_adapter_t *adapter)
15497{
15498 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15499}
15500#endif
15501
15502#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015503/**
15504 * wlan_hdd_cfg80211_del_station() - delete station v2
15505 * @wiphy: Pointer to wiphy
15506 * @param: Pointer to delete station parameter
15507 *
15508 * Return: 0 for success, non-zero for failure
15509 */
15510int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15511 struct net_device *dev,
15512 struct station_del_parameters *param)
15513#else
15514/**
15515 * wlan_hdd_cfg80211_del_station() - delete station
15516 * @wiphy: Pointer to wiphy
15517 * @mac: Pointer to station mac address
15518 *
15519 * Return: 0 for success, non-zero for failure
15520 */
15521#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15522int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15523 struct net_device *dev,
15524 const uint8_t *mac)
15525#else
15526int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15527 struct net_device *dev,
15528 uint8_t *mac)
15529#endif
15530#endif
15531{
15532 int ret;
15533 struct tagCsrDelStaParams delStaParams;
15534
15535 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015536#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015537 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015538 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015539 return -EINVAL;
15540 }
15541 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15542 param->subtype, &delStaParams);
15543#else
15544 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15545 (SIR_MAC_MGMT_DEAUTH >> 4),
15546 &delStaParams);
15547#endif
15548 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15549 cds_ssr_unprotect(__func__);
15550
15551 return ret;
15552}
15553
15554/**
15555 * __wlan_hdd_cfg80211_add_station() - add station
15556 * @wiphy: Pointer to wiphy
15557 * @mac: Pointer to station mac address
15558 * @pmksa: Pointer to add station parameter
15559 *
15560 * Return: 0 for success, non-zero for failure
15561 */
15562static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15563 struct net_device *dev,
15564 const uint8_t *mac,
15565 struct station_parameters *params)
15566{
15567 int status = -EPERM;
15568#ifdef FEATURE_WLAN_TDLS
15569 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15570 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15571 u32 mask, set;
15572
15573 ENTER();
15574
Anurag Chouhan6d760662016-02-20 16:05:43 +053015575 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015576 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015577 return -EINVAL;
15578 }
15579
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015580 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015581 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015582 return -EINVAL;
15583 }
15584
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015585 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015586 TRACE_CODE_HDD_CFG80211_ADD_STA,
15587 pAdapter->sessionId, params->listen_interval));
15588
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015589 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015590 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015591
15592 mask = params->sta_flags_mask;
15593
15594 set = params->sta_flags_set;
15595
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015596 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015597 MAC_ADDR_ARRAY(mac));
15598
15599 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15600 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Frank Liud4b2fa02017-03-29 11:46:48 +080015601#if defined(CONVERGED_TDLS_ENABLE)
15602 status = wlan_cfg80211_tdls_add_peer(pHddCtx->hdd_pdev,
15603 dev, mac);
15604#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015605 status =
15606 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
Frank Liud4b2fa02017-03-29 11:46:48 +080015607#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015608 }
15609 }
15610#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015611 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015612 return status;
15613}
15614
15615/**
15616 * wlan_hdd_cfg80211_add_station() - add station
15617 * @wiphy: Pointer to wiphy
15618 * @mac: Pointer to station mac address
15619 * @pmksa: Pointer to add station parameter
15620 *
15621 * Return: 0 for success, non-zero for failure
15622 */
15623#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15624static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15625 struct net_device *dev,
15626 const uint8_t *mac,
15627 struct station_parameters *params)
15628#else
15629static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15630 struct net_device *dev, uint8_t *mac,
15631 struct station_parameters *params)
15632#endif
15633{
15634 int ret;
15635
15636 cds_ssr_protect(__func__);
15637 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15638 cds_ssr_unprotect(__func__);
15639
15640 return ret;
15641}
15642
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015643/**
15644 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15645 * @wiphy: Pointer to wiphy
15646 * @dev: Pointer to network device
15647 * @pmksa: Pointer to set pmksa parameter
15648 *
15649 * Return: 0 for success, non-zero for failure
15650 */
15651static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15652 struct net_device *dev,
15653 struct cfg80211_pmksa *pmksa)
15654{
15655 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15656 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15657 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015658 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015659 int status;
15660 tPmkidCacheInfo pmk_id;
15661
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015662 ENTER();
15663
Anurag Chouhan6d760662016-02-20 16:05:43 +053015664 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015665 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015666 return -EINVAL;
15667 }
15668
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015669 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015670 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015671 return -EINVAL;
15672 }
15673
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015674 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015675 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015676 return -EINVAL;
15677 }
15678
15679 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015680 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015681 pmksa->bssid, pmksa->pmkid);
15682 return -EINVAL;
15683 }
15684
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015685 hdd_debug("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015686 MAC_ADDR_ARRAY(pmksa->bssid));
15687
15688 status = wlan_hdd_validate_context(pHddCtx);
15689
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015690 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015691 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015692
15693 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15694
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015695 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15696 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015697
15698 /* Add to the PMKSA ID Cache in CSR */
15699 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15700 &pmk_id, 1, false);
15701
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015702 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015703 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
15704 pAdapter->sessionId, result));
15705
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015706 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015707 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015708}
15709
15710/**
15711 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15712 * @wiphy: Pointer to wiphy
15713 * @dev: Pointer to network device
15714 * @pmksa: Pointer to set pmksa parameter
15715 *
15716 * Return: 0 for success, non-zero for failure
15717 */
15718static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15719 struct net_device *dev,
15720 struct cfg80211_pmksa *pmksa)
15721{
15722 int ret;
15723
15724 cds_ssr_protect(__func__);
15725 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15726 cds_ssr_unprotect(__func__);
15727
15728 return ret;
15729}
15730
15731/**
15732 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15733 * @wiphy: Pointer to wiphy
15734 * @dev: Pointer to network device
15735 * @pmksa: Pointer to pmksa parameter
15736 *
15737 * Return: 0 for success, non-zero for failure
15738 */
15739static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15740 struct net_device *dev,
15741 struct cfg80211_pmksa *pmksa)
15742{
15743 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15744 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15745 tHalHandle halHandle;
15746 int status = 0;
15747
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015748 ENTER();
15749
Anurag Chouhan6d760662016-02-20 16:05:43 +053015750 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015751 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015752 return -EINVAL;
15753 }
15754
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015755 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15756 hdd_err("invalid session id: %d", pAdapter->sessionId);
15757 return -EINVAL;
15758 }
15759
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015760 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015761 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015762 return -EINVAL;
15763 }
15764
15765 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015766 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015767 return -EINVAL;
15768 }
15769
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015770 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015771 MAC_ADDR_ARRAY(pmksa->bssid));
15772
15773 status = wlan_hdd_validate_context(pHddCtx);
15774
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015775 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015776 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015777
15778 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15779
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015780 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015781 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
15782 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015783 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015784 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015785 sme_roam_del_pmkid_from_cache(halHandle,
15786 pAdapter->sessionId, pmksa->bssid,
15787 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015788 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015789 MAC_ADDR_ARRAY(pmksa->bssid));
15790 status = -EINVAL;
15791 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015792 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015793 return status;
15794}
15795
15796/**
15797 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15798 * @wiphy: Pointer to wiphy
15799 * @dev: Pointer to network device
15800 * @pmksa: Pointer to pmksa parameter
15801 *
15802 * Return: 0 for success, non-zero for failure
15803 */
15804static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15805 struct net_device *dev,
15806 struct cfg80211_pmksa *pmksa)
15807{
15808 int ret;
15809
15810 cds_ssr_protect(__func__);
15811 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
15812 cds_ssr_unprotect(__func__);
15813
15814 return ret;
15815
15816}
15817
15818/**
15819 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15820 * @wiphy: Pointer to wiphy
15821 * @dev: Pointer to network device
15822 *
15823 * Return: 0 for success, non-zero for failure
15824 */
15825static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15826 struct net_device *dev)
15827{
15828 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15829 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15830 tHalHandle halHandle;
15831 int status = 0;
15832
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015833 ENTER();
15834
Anurag Chouhan6d760662016-02-20 16:05:43 +053015835 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015836 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015837 return -EINVAL;
15838 }
15839
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015840 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15841 hdd_err("invalid session id: %d", pAdapter->sessionId);
15842 return -EINVAL;
15843 }
15844
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015845 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015846
15847 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15848 status = wlan_hdd_validate_context(pHddCtx);
15849
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015850 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015851 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015852
15853 /* Retrieve halHandle */
15854 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15855
15856 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015857 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015858 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
15859 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015860 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015861 status = -EINVAL;
15862 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015863 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015864 return status;
15865}
15866
15867/**
15868 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15869 * @wiphy: Pointer to wiphy
15870 * @dev: Pointer to network device
15871 *
15872 * Return: 0 for success, non-zero for failure
15873 */
15874static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15875 struct net_device *dev)
15876{
15877 int ret;
15878
15879 cds_ssr_protect(__func__);
15880 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
15881 cds_ssr_unprotect(__func__);
15882
15883 return ret;
15884}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015885
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015886#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015887/**
15888 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15889 * @wiphy: Pointer to wiphy
15890 * @dev: Pointer to network device
15891 * @ftie: Pointer to fast transition ie parameter
15892 *
15893 * Return: 0 for success, non-zero for failure
15894 */
15895static int
15896__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15897 struct net_device *dev,
15898 struct cfg80211_update_ft_ies_params *ftie)
15899{
15900 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15901 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15902 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15903 int status;
15904
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015905 ENTER();
15906
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015907 status = wlan_hdd_validate_context(hdd_ctx);
15908 if (status)
15909 return status;
15910
Anurag Chouhan6d760662016-02-20 16:05:43 +053015911 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015912 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015913 return -EINVAL;
15914 }
15915
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015916 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15917 hdd_err("invalid session id: %d", pAdapter->sessionId);
15918 return -EINVAL;
15919 }
15920
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015921 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015922 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
15923 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
15924 /* Added for debug on reception of Re-assoc Req. */
15925 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015926 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015927 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015928 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015929 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015930 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015931 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015932
15933 /* Pass the received FT IEs to SME */
15934 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
15935 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015936 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015937 return 0;
15938}
15939
15940/**
15941 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15942 * @wiphy: Pointer to wiphy
15943 * @dev: Pointer to network device
15944 * @ftie: Pointer to fast transition ie parameter
15945 *
15946 * Return: 0 for success, non-zero for failure
15947 */
15948static int
15949wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15950 struct net_device *dev,
15951 struct cfg80211_update_ft_ies_params *ftie)
15952{
15953 int ret;
15954
15955 cds_ssr_protect(__func__);
15956 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
15957 cds_ssr_unprotect(__func__);
15958
15959 return ret;
15960}
15961#endif
15962
Mukul Sharma3d36c392017-01-18 18:39:12 +053015963void wlan_hdd_cfg80211_update_replay_counter_callback(
15964 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
15965
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015966{
Mukul Sharma3d36c392017-01-18 18:39:12 +053015967 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
15968 uint8_t temp_replay_counter[8];
15969 int i;
15970 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015971
15972 ENTER();
15973
Mukul Sharma3d36c392017-01-18 18:39:12 +053015974 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015975 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015976 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015977 }
15978
Mukul Sharma3d36c392017-01-18 18:39:12 +053015979 if (!gtk_rsp_param) {
15980 hdd_err("gtk_rsp_param is Null");
15981 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015982 }
15983
Mukul Sharma3d36c392017-01-18 18:39:12 +053015984 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015985 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015986 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015987 }
15988
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015989 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053015990 gtk_rsp_param->replay_counter);
15991 /* convert little to big endian since supplicant works on big endian */
15992 p = (uint8_t *)&gtk_rsp_param->replay_counter;
15993 for (i = 0; i < 8; i++)
15994 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015995
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015996 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015997 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015998 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015999 gtk_rsp_param->bssid.bytes,
16000 temp_replay_counter, GFP_KERNEL);
16001out:
16002 EXIT();
16003
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016004}
16005
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016006static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016007int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053016008 struct net_device *dev,
16009 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016010{
16011 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053016012 int result, i;
16013 struct pmo_gtk_req *gtk_req = NULL;
16014 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
16015 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016016 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016017
16018 ENTER();
16019
Anurag Chouhan6d760662016-02-20 16:05:43 +053016020 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016021 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053016022 result = -EINVAL;
16023 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016024 }
16025
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016026 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16027 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053016028 result = -EINVAL;
16029 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016030 }
16031
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016032 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016033 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
16034 pAdapter->sessionId, pAdapter->device_mode));
16035
Mukul Sharma3d36c392017-01-18 18:39:12 +053016036 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016037 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053016038 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016039
Mukul Sharma3d36c392017-01-18 18:39:12 +053016040 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
16041 if (!gtk_req) {
16042 hdd_err("cannot allocate gtk_req");
16043 result = -ENOMEM;
16044 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016045 }
16046
Mukul Sharma3d36c392017-01-18 18:39:12 +053016047 /* convert big to little endian since driver work on little endian */
16048 buf = (uint8_t *)&gtk_req->replay_counter;
16049 for (i = 0; i < 8; i++)
16050 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016051
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016052 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053016053 gtk_req->replay_counter);
16054 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
16055 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
16056 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
16057 if (status != QDF_STATUS_SUCCESS) {
16058 hdd_err("Failed to cache GTK Offload");
16059 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016060 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053016061out:
16062 if (gtk_req)
16063 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016064 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053016065
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016066 return result;
16067}
16068
16069/**
16070 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
16071 * @wiphy: Pointer to wiphy
16072 * @dev: Pointer to network device
16073 * @data: Pointer to rekey data
16074 *
16075 * This function is used to offload GTK rekeying job to the firmware.
16076 *
16077 * Return: 0 for success, non-zero for failure
16078 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016079static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016080int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
16081 struct net_device *dev,
16082 struct cfg80211_gtk_rekey_data *data)
16083{
16084 int ret;
16085
16086 cds_ssr_protect(__func__);
16087 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
16088 cds_ssr_unprotect(__func__);
16089
16090 return ret;
16091}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016092
16093/**
16094 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
16095 * @wiphy: Pointer to wiphy
16096 * @dev: Pointer to network device
16097 * @param: Pointer to access control parameter
16098 *
16099 * Return: 0 for success, non-zero for failure
16100 */
16101static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16102 struct net_device *dev,
16103 const struct cfg80211_acl_data *params)
16104{
16105 int i;
16106 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16107 hdd_hostapd_state_t *pHostapdState;
16108 tsap_Config_t *pConfig;
16109 v_CONTEXT_t p_cds_context = NULL;
16110 hdd_context_t *pHddCtx;
16111 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016112 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016113
16114 ENTER();
16115
Anurag Chouhan6d760662016-02-20 16:05:43 +053016116 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016117 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016118 return -EINVAL;
16119 }
16120
16121 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016122 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016123 return -EINVAL;
16124 }
16125
16126 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16127 status = wlan_hdd_validate_context(pHddCtx);
16128
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016129 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016130 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016131
16132 p_cds_context = pHddCtx->pcds_context;
16133 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
16134
16135 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016136 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016137 return -EINVAL;
16138 }
16139
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016140 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016141 params->n_acl_entries);
16142
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016143 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016144 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
16145 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080016146 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016147 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
16148
16149 /* default value */
16150 pConfig->num_accept_mac = 0;
16151 pConfig->num_deny_mac = 0;
16152
16153 /**
16154 * access control policy
16155 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16156 * listed in hostapd.deny file.
16157 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16158 * listed in hostapd.accept file.
16159 */
16160 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
16161 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16162 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
16163 params->acl_policy) {
16164 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16165 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016166 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016167 params->acl_policy);
16168 return -ENOTSUPP;
16169 }
16170
16171 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16172 pConfig->num_accept_mac = params->n_acl_entries;
16173 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016174 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016175 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016176 MAC_ADDR_ARRAY(
16177 params->mac_addrs[i].addr));
16178
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016179 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016180 params->mac_addrs[i].addr,
16181 sizeof(qcmacaddr));
16182 }
16183 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16184 pConfig->num_deny_mac = params->n_acl_entries;
16185 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016186 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016187 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016188 MAC_ADDR_ARRAY(
16189 params->mac_addrs[i].addr));
16190
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016191 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016192 params->mac_addrs[i].addr,
16193 sizeof(qcmacaddr));
16194 }
16195 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016196 qdf_status = wlansap_set_mac_acl(
16197 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016198 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016199 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016200 return -EINVAL;
16201 }
16202 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016203 hdd_debug("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016204 hdd_device_mode_to_string(pAdapter->device_mode),
16205 pAdapter->device_mode);
16206 return -EINVAL;
16207 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016208 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016209 return 0;
16210}
16211
16212/**
16213 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16214 * __wlan_hdd_cfg80211_set_mac_acl
16215 * @wiphy: pointer to wiphy structure
16216 * @dev: pointer to net_device
16217 * @params: pointer to cfg80211_acl_data
16218 *
16219 * Return; 0 on success, error number otherwise
16220 */
16221static int
16222wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16223 struct net_device *dev,
16224 const struct cfg80211_acl_data *params)
16225{
16226 int ret;
16227
16228 cds_ssr_protect(__func__);
16229 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16230 cds_ssr_unprotect(__func__);
16231
16232 return ret;
16233}
16234
16235#ifdef WLAN_NL80211_TESTMODE
16236#ifdef FEATURE_WLAN_LPHB
16237/**
16238 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16239 * @pHddCtx: Pointer to hdd context
16240 * @lphbInd: Pointer to low power heart beat indication parameter
16241 *
16242 * Return: none
16243 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016244static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016245 struct pmo_lphb_rsp *lphb_ind)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016246{
16247 struct sk_buff *skb;
16248
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016249 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016250
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016251 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016252 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016253
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016254 if (!lphb_ind) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016255 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016256 return;
16257 }
16258
16259 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016260 wiphy, sizeof(*lphb_ind), GFP_ATOMIC);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016261 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016262 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016263 return;
16264 }
16265
16266 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016267 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016268 goto nla_put_failure;
16269 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016270 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphb_ind->protocol_type)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016271 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016272 goto nla_put_failure;
16273 }
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016274 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(*lphb_ind),
16275 lphb_ind)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016276 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016277 goto nla_put_failure;
16278 }
16279 cfg80211_testmode_event(skb, GFP_ATOMIC);
16280 return;
16281
16282nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016283 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016284 kfree_skb(skb);
16285
16286 return;
16287}
16288#endif /* FEATURE_WLAN_LPHB */
16289
16290/**
16291 * __wlan_hdd_cfg80211_testmode() - test mode
16292 * @wiphy: Pointer to wiphy
16293 * @data: Data pointer
16294 * @len: Data length
16295 *
16296 * Return: 0 for success, non-zero for failure
16297 */
16298static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16299 void *data, int len)
16300{
16301 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16302 int err;
16303 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16304
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016305 ENTER();
16306
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016307 err = wlan_hdd_validate_context(pHddCtx);
16308 if (err)
16309 return err;
16310
16311 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16312 len, wlan_hdd_tm_policy);
16313 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016314 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016315 return err;
16316 }
16317
16318 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016319 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016320 return -EINVAL;
16321 }
16322
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016323 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016324 TRACE_CODE_HDD_CFG80211_TESTMODE,
16325 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016326 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16327#ifdef FEATURE_WLAN_LPHB
16328 /* Low Power Heartbeat configuration request */
16329 case WLAN_HDD_TM_CMD_WLAN_HB:
16330 {
16331 int buf_len;
16332 void *buf;
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016333 struct pmo_lphb_req *hb_params = NULL;
16334 struct pmo_lphb_req *hb_params_temp = NULL;
16335 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016336
16337 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016338 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016339 return -EINVAL;
16340 }
16341
16342 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16343 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16344
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016345 hb_params_temp = (struct pmo_lphb_req *) buf;
16346 if ((hb_params_temp->cmd == pmo_lphb_set_tcp_pararm_indid)
16347 && (hb_params_temp->params.lphb_tcp_params.
16348 time_period_sec == 0))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016349 return -EINVAL;
16350
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016351 hb_params = (struct pmo_lphb_req *)qdf_mem_malloc(
16352 sizeof(*hb_params));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016353 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016354 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016355 return -ENOMEM;
16356 }
16357
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016358 qdf_mem_copy(hb_params, buf, buf_len);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016359 status = pmo_ucfg_lphb_config_req(pHddCtx->hdd_psoc,
16360 hb_params, (void *)pHddCtx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016361 wlan_hdd_cfg80211_lphb_ind_handler);
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016362 if (status != QDF_STATUS_SUCCESS)
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016363 hdd_err("LPHB Config Fail, disable");
Mukul Sharmafcd57f52017-03-20 18:18:59 +053016364
16365 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016366 return 0;
16367 }
16368#endif /* FEATURE_WLAN_LPHB */
16369
16370#if defined(QCA_WIFI_FTM)
16371 case WLAN_HDD_TM_CMD_WLAN_FTM:
16372 {
16373 int buf_len;
16374 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016375 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016376 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016377 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016378 return -EINVAL;
16379 }
16380
16381 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16382 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16383
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016384 hdd_debug("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016385
16386 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16387
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016388 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016389 err = -EBUSY;
16390 break;
16391 }
16392#endif
16393
16394 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016395 hdd_err("command: %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016396 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16397 return -EOPNOTSUPP;
16398 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016399 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016400 return err;
16401}
16402
16403/**
16404 * wlan_hdd_cfg80211_testmode() - test mode
16405 * @wiphy: Pointer to wiphy
16406 * @dev: Pointer to network device
16407 * @data: Data pointer
16408 * @len: Data length
16409 *
16410 * Return: 0 for success, non-zero for failure
16411 */
16412static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16413#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16414 struct wireless_dev *wdev,
16415#endif
16416 void *data, int len)
16417{
16418 int ret;
16419
16420 cds_ssr_protect(__func__);
16421 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16422 cds_ssr_unprotect(__func__);
16423
16424 return ret;
16425}
16426
16427#if defined(QCA_WIFI_FTM)
16428/**
16429 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16430 * @buf: Pointer to buffer
16431 * @buf_len: Buffer length
16432 *
16433 * Return: none
16434 */
16435void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16436{
16437 struct sk_buff *skb;
16438 hdd_context_t *hdd_ctx;
16439
16440 if (!buf || !buf_len) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016441 hdd_err("buf or buf_len invalid, buf: %p buf_len: %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016442 return;
16443 }
16444
Anurag Chouhan6d760662016-02-20 16:05:43 +053016445 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016446 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016447 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016448 return;
16449 }
16450
16451 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16452 buf_len, GFP_KERNEL);
16453 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016454 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016455 return;
16456 }
16457
16458 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16459 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16460 goto nla_put_failure;
16461
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016462 hdd_debug("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016463
16464 cfg80211_testmode_event(skb, GFP_KERNEL);
16465 return;
16466
16467nla_put_failure:
16468 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016469 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016470}
16471#endif
16472#endif /* CONFIG_NL80211_TESTMODE */
16473
16474#ifdef QCA_HT_2040_COEX
16475/**
16476 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16477 * @wiphy: Pointer to wiphy
16478 * @dev: Pointer to network device
16479 * @chandef: Pointer to channel definition parameter
16480 *
16481 * Return: 0 for success, non-zero for failure
16482 */
16483static int
16484__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16485 struct net_device *dev,
16486 struct cfg80211_chan_def *chandef)
16487{
16488 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16489 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016490 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016491 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016492 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016493
Anurag Chouhan6d760662016-02-20 16:05:43 +053016494 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016495 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016496 return -EINVAL;
16497 }
16498
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016499 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16500 hdd_err("invalid session id: %d", pAdapter->sessionId);
16501 return -EINVAL;
16502 }
16503
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016504 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16505 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016506 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016507 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016508
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016509 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016510 sme_get_config_param(pHddCtx->hHal, &sme_config);
16511 switch (chandef->width) {
16512 case NL80211_CHAN_WIDTH_20:
Ashish Kumar Dhanotiya2b4fd752017-04-19 15:42:27 +053016513 case NL80211_CHAN_WIDTH_20_NOHT:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016514 if (sme_config.csrConfig.channelBondingMode24GHz !=
16515 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16516 sme_config.csrConfig.channelBondingMode24GHz =
16517 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16518 sme_update_config(pHddCtx->hHal, &sme_config);
16519 cbModeChange = true;
16520 }
16521 break;
16522
16523 case NL80211_CHAN_WIDTH_40:
16524 if (sme_config.csrConfig.channelBondingMode24GHz ==
16525 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16526 if (NL80211_CHAN_HT40MINUS ==
16527 cfg80211_get_chandef_type(chandef))
16528 sme_config.csrConfig.channelBondingMode24GHz =
16529 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16530 else
16531 sme_config.csrConfig.channelBondingMode24GHz =
16532 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16533 sme_update_config(pHddCtx->hHal, &sme_config);
16534 cbModeChange = true;
16535 }
16536 break;
16537
16538 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016539 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016540 return -EINVAL;
16541 }
16542
16543 if (!cbModeChange)
16544 return 0;
16545
Krunal Sonib4326f22016-03-10 13:05:51 -080016546 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016547 return 0;
16548
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016549 hdd_debug("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016550 sme_config.csrConfig.channelBondingMode24GHz);
16551
16552 /* Change SAP ht2040 mode */
16553 status = hdd_set_sap_ht2040_mode(pAdapter,
16554 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016555 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016556 hdd_err("Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016557 return -EINVAL;
16558 }
16559
16560 return 0;
16561}
16562
16563/**
16564 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16565 * @wiphy: Pointer to wiphy
16566 * @dev: Pointer to network device
16567 * @chandef: Pointer to channel definition parameter
16568 *
16569 * Return: 0 for success, non-zero for failure
16570 */
16571static int
16572wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16573 struct net_device *dev,
16574 struct cfg80211_chan_def *chandef)
16575{
16576 int ret;
16577
16578 cds_ssr_protect(__func__);
16579 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16580 cds_ssr_unprotect(__func__);
16581
16582 return ret;
16583}
16584#endif
16585
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016586#ifdef CHANNEL_SWITCH_SUPPORTED
16587/**
16588 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16589 * channel in SAP/GO
16590 * @wiphy: wiphy pointer
16591 * @dev: dev pointer.
16592 * @csa_params: Change channel params
16593 *
16594 * This function is called to switch channel in SAP/GO
16595 *
16596 * Return: 0 if success else return non zero
16597 */
16598static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16599 struct net_device *dev,
16600 struct cfg80211_csa_settings *csa_params)
16601{
16602 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16603 hdd_context_t *hdd_ctx;
16604 uint8_t channel;
16605 uint16_t freq;
16606 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016607 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016608
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016609 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016610 csa_params->chandef.chan->center_freq);
16611
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016612 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16613 hdd_err("invalid session id: %d", adapter->sessionId);
16614 return -EINVAL;
16615 }
16616
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016617 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16618 ret = wlan_hdd_validate_context(hdd_ctx);
16619
16620 if (0 != ret)
16621 return ret;
16622
Krunal Sonib4326f22016-03-10 13:05:51 -080016623 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16624 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016625 return -ENOTSUPP;
16626
16627 freq = csa_params->chandef.chan->center_freq;
16628 channel = cds_freq_to_chan(freq);
16629
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016630 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16631
16632 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016633 return ret;
16634}
16635
16636/**
16637 * wlan_hdd_cfg80211_channel_switch()- function to switch
16638 * channel in SAP/GO
16639 * @wiphy: wiphy pointer
16640 * @dev: dev pointer.
16641 * @csa_params: Change channel params
16642 *
16643 * This function is called to switch channel in SAP/GO
16644 *
16645 * Return: 0 if success else return non zero
16646 */
16647static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16648 struct net_device *dev,
16649 struct cfg80211_csa_settings *csa_params)
16650{
16651 int ret;
16652
16653 cds_ssr_protect(__func__);
16654 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16655 cds_ssr_unprotect(__func__);
16656 return ret;
16657}
16658#endif
16659
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016660/**
16661 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16662 * translation from NL to policy manager type
16663 * @type: Generic connection mode type defined in NL
16664 *
16665 *
16666 * This function provides the type translation
16667 *
16668 * Return: cds_con_mode enum
16669 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016670enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016671 enum nl80211_iftype type)
16672{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016673 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016674 switch (type) {
16675 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016676 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016677 break;
16678 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016679 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016680 break;
16681 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016682 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016683 break;
16684 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016685 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016686 break;
16687 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016688 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016689 break;
16690 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016691 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016692 }
16693 return mode;
16694}
16695
16696/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016697 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16698 * @wiphy: Handle to struct wiphy to get handle to module context.
16699 * @chandef: Contains information about the capture channel to be set.
16700 *
16701 * This interface is called if and only if monitor mode interface alone is
16702 * active.
16703 *
16704 * Return: 0 success or error code on failure.
16705 */
16706static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16707 struct cfg80211_chan_def *chandef)
16708{
16709 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16710 hdd_adapter_t *adapter;
16711 hdd_station_ctx_t *sta_ctx;
16712 struct hdd_mon_set_ch_info *ch_info;
16713 QDF_STATUS status;
16714 tHalHandle hal_hdl;
16715 struct qdf_mac_addr bssid;
16716 tCsrRoamProfile roam_profile;
Amar Singhal5cccafe2017-02-15 12:42:58 -080016717 struct ch_params ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016718 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016719 int ret;
16720 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16721
16722 ENTER();
16723
16724 ret = wlan_hdd_validate_context(hdd_ctx);
16725 if (ret)
16726 return ret;
16727
16728 hal_hdl = hdd_ctx->hHal;
16729
16730 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16731 if (!adapter)
16732 return -EIO;
16733
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016734 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016735 adapter->dev->name, chan_num, chandef->chan->center_freq);
16736
16737 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16738 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016739 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16740 roam_profile.ChannelInfo.numOfChannels = 1;
16741 roam_profile.phyMode = ch_info->phy_mode;
16742 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016743 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016744
16745 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16746 QDF_MAC_ADDR_SIZE);
16747
16748 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016749 /*
16750 * CDS api expects secondary channel for calculating
16751 * the channel params
16752 */
16753 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070016754 (WLAN_REG_IS_24GHZ_CH(chan_num))) {
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016755 if (chan_num >= 1 && chan_num <= 5)
16756 sec_ch = chan_num + 4;
16757 else if (chan_num >= 6 && chan_num <= 13)
16758 sec_ch = chan_num - 4;
16759 }
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070016760 wlan_reg_set_channel_params(hdd_ctx->hdd_pdev, chan_num,
16761 sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016762 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16763 &roam_profile);
16764 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016765 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016766 status);
16767 ret = qdf_status_to_os_return(status);
16768 return ret;
16769 }
16770 EXIT();
16771 return 0;
16772}
16773
16774/**
16775 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16776 * @wiphy: Handle to struct wiphy to get handle to module context.
16777 * @chandef: Contains information about the capture channel to be set.
16778 *
16779 * This interface is called if and only if monitor mode interface alone is
16780 * active.
16781 *
16782 * Return: 0 success or error code on failure.
16783 */
16784static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16785 struct cfg80211_chan_def *chandef)
16786{
16787 int ret;
16788
16789 cds_ssr_protect(__func__);
16790 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
16791 cds_ssr_unprotect(__func__);
16792 return ret;
16793}
16794
16795/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016796 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
16797 * @adapter: pointer to adapter
16798 *
16799 * Wrapper function to clear link layer stats.
16800 * return - void
16801 */
16802void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
16803{
16804 tSirLLStatsClearReq link_layer_stats_clear_req;
16805 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
16806
Mukul Sharma491021c2016-09-29 21:39:19 +053016807 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
16808 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016809 link_layer_stats_clear_req.stopReq = 0;
16810 link_layer_stats_clear_req.reqId = 1;
16811 link_layer_stats_clear_req.staId = adapter->sessionId;
16812 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
16813
16814 return;
16815}
16816
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016817/**
16818 * hdd_process_defer_disconnect() - Handle the deferred disconnect
16819 * @adapter: HDD Adapter
16820 *
16821 * If roaming is in progress and there is a request to
16822 * disconnect the session, then it is deferred. Once
16823 * roaming is complete/aborted, then this routine is
16824 * used to resume the disconnect that was deferred
16825 *
16826 * Return: None
16827 */
16828void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
16829{
16830 switch (adapter->defer_disconnect) {
16831 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
16832 adapter->defer_disconnect = 0;
16833 wlan_hdd_disconnect(adapter,
16834 adapter->cfg80211_disconnect_reason);
16835 break;
16836 case DEFER_DISCONNECT_TRY_DISCONNECT:
16837 wlan_hdd_try_disconnect(adapter);
16838 adapter->defer_disconnect = 0;
16839 break;
16840 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016841 hdd_debug("Invalid source to defer:%d. Hence not handling it",
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016842 adapter->defer_disconnect);
16843 break;
16844 }
16845}
16846
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016847#define CNT_DIFF(cur, prev) \
16848 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
16849#define MAX_COUNT 0xffffffff
16850static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
16851 struct scan_chan_info *chan,
16852 struct scan_chan_info *info, uint32_t cmd_flag)
16853{
16854 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
16855 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
16856 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
16857
16858 mutex_lock(&hdd_ctx->chan_info_lock);
16859
16860 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
16861 qdf_mem_zero(chan, sizeof(*chan));
16862
16863 chan->freq = info->freq;
16864 chan->noise_floor = info->noise_floor;
16865 chan->clock_freq = info->clock_freq;
16866 chan->cmd_flag = info->cmd_flag;
16867 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
16868
16869 chan->rx_clear_count =
16870 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
16871
16872 chan->tx_frame_count =
16873 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
16874
16875 mutex_unlock(&hdd_ctx->chan_info_lock);
16876
16877}
16878#undef CNT_DIFF
16879#undef MAX_COUNT
16880
16881/**
16882 * wlan_hdd_chan_info_cb() - channel info callback
16883 * @chan_info: struct scan_chan_info
16884 *
16885 * Store channel info into HDD context
16886 *
16887 * Return: None.
16888 */
16889static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
16890{
16891 hdd_context_t *hdd_ctx;
16892 struct scan_chan_info *chan;
16893 uint8_t idx;
16894
16895 ENTER();
16896
16897 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
16898 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
16899 hdd_err("hdd_ctx is invalid");
16900 return;
16901 }
16902
16903 if (!hdd_ctx->chan_info) {
16904 hdd_err("chan_info is NULL");
16905 return;
16906 }
16907
16908 chan = hdd_ctx->chan_info;
16909 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
16910 if (chan[idx].freq == info->freq) {
16911 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
16912 info->cmd_flag);
16913 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
16914 chan[idx].cmd_flag, chan[idx].freq,
16915 chan[idx].noise_floor,
16916 chan[idx].cycle_count, chan[idx].rx_clear_count,
16917 chan[idx].clock_freq, chan[idx].cmd_flag,
16918 chan[idx].tx_frame_count, idx);
16919 if (chan[idx].freq == 0)
16920 break;
16921
16922 }
16923 }
16924
16925 EXIT();
16926}
16927
16928/**
16929 * wlan_hdd_init_chan_info() - init chan info in hdd context
16930 * @hdd_ctx: HDD context pointer
16931 *
16932 * Return: none
16933 */
16934void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
16935{
16936 uint8_t num_2g, num_5g, index = 0;
16937
16938 if (!hdd_ctx->config->fEnableSNRMonitoring) {
16939 hdd_info("SNR monitoring is disabled");
16940 return;
16941 }
16942
16943 hdd_ctx->chan_info =
16944 qdf_mem_malloc(sizeof(struct scan_chan_info)
16945 * QDF_MAX_NUM_CHAN);
16946 if (hdd_ctx->chan_info == NULL) {
16947 hdd_err("Failed to malloc for chan info");
16948 return;
16949 }
16950 mutex_init(&hdd_ctx->chan_info_lock);
16951
16952 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
16953 for (; index < num_2g; index++) {
16954 hdd_ctx->chan_info[index].freq =
16955 hdd_channels_2_4_ghz[index].center_freq;
16956 }
16957
16958 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
16959 for (; (index - num_2g) < num_5g; index++) {
Kiran Kumar Lokerea3de2262017-04-12 12:15:04 -070016960 if (WLAN_REG_IS_11P_CH(
16961 hdd_channels_5_ghz[index - num_2g].hw_value))
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016962 continue;
16963 hdd_ctx->chan_info[index].freq =
16964 hdd_channels_5_ghz[index - num_2g].center_freq;
16965 }
16966 sme_set_chan_info_callback(hdd_ctx->hHal,
16967 &wlan_hdd_chan_info_cb);
16968}
16969
16970/**
16971 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
16972 * @hdd_ctx: hdd context pointer
16973 *
16974 * Return: none
16975 */
16976void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
16977{
16978 struct scan_chan_info *chan;
16979
16980 chan = hdd_ctx->chan_info;
16981 hdd_ctx->chan_info = NULL;
16982 if (chan)
16983 qdf_mem_free(chan);
16984}
16985
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016986/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016987 * struct cfg80211_ops - cfg80211_ops
16988 *
16989 * @add_virtual_intf: Add virtual interface
16990 * @del_virtual_intf: Delete virtual interface
16991 * @change_virtual_intf: Change virtual interface
16992 * @change_station: Change station
16993 * @add_beacon: Add beacon in sap mode
16994 * @del_beacon: Delete beacon in sap mode
16995 * @set_beacon: Set beacon in sap mode
16996 * @start_ap: Start ap
16997 * @change_beacon: Change beacon
16998 * @stop_ap: Stop ap
16999 * @change_bss: Change bss
17000 * @add_key: Add key
17001 * @get_key: Get key
17002 * @del_key: Delete key
17003 * @set_default_key: Set default key
17004 * @set_channel: Set channel
17005 * @scan: Scan
17006 * @connect: Connect
17007 * @disconnect: Disconnect
17008 * @join_ibss = Join ibss
17009 * @leave_ibss = Leave ibss
17010 * @set_wiphy_params = Set wiphy params
17011 * @set_tx_power = Set tx power
17012 * @get_tx_power = get tx power
17013 * @remain_on_channel = Remain on channel
17014 * @cancel_remain_on_channel = Cancel remain on channel
17015 * @mgmt_tx = Tx management frame
17016 * @mgmt_tx_cancel_wait = Cancel management tx wait
17017 * @set_default_mgmt_key = Set default management key
17018 * @set_txq_params = Set tx queue parameters
17019 * @get_station = Get station
17020 * @set_power_mgmt = Set power management
17021 * @del_station = Delete station
17022 * @add_station = Add station
17023 * @set_pmksa = Set pmksa
17024 * @del_pmksa = Delete pmksa
17025 * @flush_pmksa = Flush pmksa
17026 * @update_ft_ies = Update FT IEs
17027 * @tdls_mgmt = Tdls management
17028 * @tdls_oper = Tdls operation
17029 * @set_rekey_data = Set rekey data
17030 * @sched_scan_start = Scheduled scan start
17031 * @sched_scan_stop = Scheduled scan stop
17032 * @resume = Resume wlan
17033 * @suspend = Suspend wlan
17034 * @set_mac_acl = Set mac acl
17035 * @testmode_cmd = Test mode command
17036 * @set_ap_chanwidth = Set AP channel bandwidth
17037 * @dump_survey = Dump survey
17038 * @key_mgmt_set_pmk = Set pmk key management
17039 */
17040static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
17041 .add_virtual_intf = wlan_hdd_add_virtual_intf,
17042 .del_virtual_intf = wlan_hdd_del_virtual_intf,
17043 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
17044 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017045 .start_ap = wlan_hdd_cfg80211_start_ap,
17046 .change_beacon = wlan_hdd_cfg80211_change_beacon,
17047 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017048 .change_bss = wlan_hdd_cfg80211_change_bss,
17049 .add_key = wlan_hdd_cfg80211_add_key,
17050 .get_key = wlan_hdd_cfg80211_get_key,
17051 .del_key = wlan_hdd_cfg80211_del_key,
17052 .set_default_key = wlan_hdd_cfg80211_set_default_key,
17053 .scan = wlan_hdd_cfg80211_scan,
17054 .connect = wlan_hdd_cfg80211_connect,
17055 .disconnect = wlan_hdd_cfg80211_disconnect,
17056 .join_ibss = wlan_hdd_cfg80211_join_ibss,
17057 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
17058 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
17059 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
17060 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
17061 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
17062 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
17063 .mgmt_tx = wlan_hdd_mgmt_tx,
17064 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
17065 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
17066 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053017067 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017068 .get_station = wlan_hdd_cfg80211_get_station,
17069 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
17070 .del_station = wlan_hdd_cfg80211_del_station,
17071 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017072 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
17073 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
17074 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080017075#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017076 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
17077#endif
17078#ifdef FEATURE_WLAN_TDLS
17079 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
17080 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
17081#endif
17082#ifdef WLAN_FEATURE_GTK_OFFLOAD
17083 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
17084#endif /* WLAN_FEATURE_GTK_OFFLOAD */
17085#ifdef FEATURE_WLAN_SCAN_PNO
17086 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
17087 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
17088#endif /*FEATURE_WLAN_SCAN_PNO */
17089 .resume = wlan_hdd_cfg80211_resume_wlan,
17090 .suspend = wlan_hdd_cfg80211_suspend_wlan,
17091 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
17092#ifdef WLAN_NL80211_TESTMODE
17093 .testmode_cmd = wlan_hdd_cfg80211_testmode,
17094#endif
17095#ifdef QCA_HT_2040_COEX
17096 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
17097#endif
17098 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053017099#ifdef CHANNEL_SWITCH_SUPPORTED
17100 .channel_switch = wlan_hdd_cfg80211_channel_switch,
17101#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070017102 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053017103#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
17104 defined(CFG80211_ABORT_SCAN)
17105 .abort_scan = wlan_hdd_cfg80211_abort_scan,
17106#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080017107};