blob: 9ae9abdacd6311835d3d9e440d9ab173a4df6430 [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"
Paul Zhang3a210c52016-12-08 10:18:12 +080077#ifdef WLAN_UMAC_CONVERGENCE
78#include "wlan_cfg80211.h"
79#endif
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -080080#include <cdp_txrx_handle.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -080081#include <wlan_cfg80211_scan.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080082
83#ifdef FEATURE_WLAN_EXTSCAN
84#include "wlan_hdd_ext_scan.h"
85#endif
86
87#ifdef WLAN_FEATURE_LINK_LAYER_STATS
88#include "wlan_hdd_stats.h"
89#endif
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -080090#include "cds_api.h"
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080091#include "wlan_policy_mgr_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080092#include "qwlan_version.h"
93#include "wlan_hdd_memdump.h"
94
95#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070096#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080097
Ravi Joshideb5a8d2015-11-09 19:11:43 -080098#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +053099#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700100#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700101#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530102#include "wlan_hdd_disa.h"
Jeff Johnsoncd113fc2017-01-26 14:42:44 -0800103#include "wlan_hdd_request_manager.h"
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -0800104#include "wlan_hdd_he.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800105
Leo Changfdb45c32016-10-28 11:09:23 -0700106#include <cdp_txrx_cmn.h>
107#include <cdp_txrx_misc.h>
Sandeep Puligillafdd201e2017-02-02 18:43:46 -0800108#include <qca_vendor.h>
Mukul Sharma3d36c392017-01-18 18:39:12 +0530109#include "wlan_pmo_ucfg_api.h"
Naveen Rawat5f040ba2017-03-06 12:20:25 -0800110#include "os_if_wifi_pos.h"
Leo Changfdb45c32016-10-28 11:09:23 -0700111
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800112#define g_mode_rates_size (12)
113#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800114#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
115 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
116
117/*
118 * Android CTS verifier needs atleast this much wait time (in msec)
119 */
120#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
121
122/*
123 * Refer @tCfgProtection structure for definition of the bit map.
124 * below value is obtained by setting the following bit-fields.
125 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
126 */
127#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
128
129#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700130 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800131 .center_freq = (freq), \
132 .hw_value = (chan), \
133 .flags = (flag), \
134 .max_antenna_gain = 0, \
135 .max_power = 30, \
136}
137
138#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700139 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800140 .center_freq = (freq), \
141 .hw_value = (chan), \
142 .flags = (flag), \
143 .max_antenna_gain = 0, \
144 .max_power = 30, \
145}
146
147#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
148 { \
149 .bitrate = rate, \
150 .hw_value = rate_id, \
151 .flags = flag, \
152 }
153
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800154#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
155#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800156
157#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800158
Agrawal Ashish65634612016-08-18 13:24:32 +0530159#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
160 mode <= DFS_MODE_DEPRIORITIZE))
161#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
162 || (channel >= 36 && channel <= 184))
163
Peng Xu4d67c8f2015-10-16 16:02:26 -0700164#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530165#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700166
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800167static const u32 hdd_cipher_suites[] = {
168 WLAN_CIPHER_SUITE_WEP40,
169 WLAN_CIPHER_SUITE_WEP104,
170 WLAN_CIPHER_SUITE_TKIP,
171#ifdef FEATURE_WLAN_ESE
172#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
173#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
174 WLAN_CIPHER_SUITE_BTK,
175 WLAN_CIPHER_SUITE_KRK,
176 WLAN_CIPHER_SUITE_CCMP,
177#else
178 WLAN_CIPHER_SUITE_CCMP,
179#endif
180#ifdef FEATURE_WLAN_WAPI
181 WLAN_CIPHER_SUITE_SMS4,
182#endif
183#ifdef WLAN_FEATURE_11W
184 WLAN_CIPHER_SUITE_AES_CMAC,
185#endif
186};
187
Abhishek Singhf512bf32016-05-04 16:47:46 +0530188static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800189 HDD2GHZCHAN(2412, 1, 0),
190 HDD2GHZCHAN(2417, 2, 0),
191 HDD2GHZCHAN(2422, 3, 0),
192 HDD2GHZCHAN(2427, 4, 0),
193 HDD2GHZCHAN(2432, 5, 0),
194 HDD2GHZCHAN(2437, 6, 0),
195 HDD2GHZCHAN(2442, 7, 0),
196 HDD2GHZCHAN(2447, 8, 0),
197 HDD2GHZCHAN(2452, 9, 0),
198 HDD2GHZCHAN(2457, 10, 0),
199 HDD2GHZCHAN(2462, 11, 0),
200 HDD2GHZCHAN(2467, 12, 0),
201 HDD2GHZCHAN(2472, 13, 0),
202 HDD2GHZCHAN(2484, 14, 0),
203};
204
Abhishek Singhf512bf32016-05-04 16:47:46 +0530205static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800206 HDD5GHZCHAN(5180, 36, 0),
207 HDD5GHZCHAN(5200, 40, 0),
208 HDD5GHZCHAN(5220, 44, 0),
209 HDD5GHZCHAN(5240, 48, 0),
210 HDD5GHZCHAN(5260, 52, 0),
211 HDD5GHZCHAN(5280, 56, 0),
212 HDD5GHZCHAN(5300, 60, 0),
213 HDD5GHZCHAN(5320, 64, 0),
214 HDD5GHZCHAN(5500, 100, 0),
215 HDD5GHZCHAN(5520, 104, 0),
216 HDD5GHZCHAN(5540, 108, 0),
217 HDD5GHZCHAN(5560, 112, 0),
218 HDD5GHZCHAN(5580, 116, 0),
219 HDD5GHZCHAN(5600, 120, 0),
220 HDD5GHZCHAN(5620, 124, 0),
221 HDD5GHZCHAN(5640, 128, 0),
222 HDD5GHZCHAN(5660, 132, 0),
223 HDD5GHZCHAN(5680, 136, 0),
224 HDD5GHZCHAN(5700, 140, 0),
225 HDD5GHZCHAN(5720, 144, 0),
226 HDD5GHZCHAN(5745, 149, 0),
227 HDD5GHZCHAN(5765, 153, 0),
228 HDD5GHZCHAN(5785, 157, 0),
229 HDD5GHZCHAN(5805, 161, 0),
230 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800231 HDD5GHZCHAN(5852, 170, 0),
232 HDD5GHZCHAN(5855, 171, 0),
233 HDD5GHZCHAN(5860, 172, 0),
234 HDD5GHZCHAN(5865, 173, 0),
235 HDD5GHZCHAN(5870, 174, 0),
236 HDD5GHZCHAN(5875, 175, 0),
237 HDD5GHZCHAN(5880, 176, 0),
238 HDD5GHZCHAN(5885, 177, 0),
239 HDD5GHZCHAN(5890, 178, 0),
240 HDD5GHZCHAN(5895, 179, 0),
241 HDD5GHZCHAN(5900, 180, 0),
242 HDD5GHZCHAN(5905, 181, 0),
243 HDD5GHZCHAN(5910, 182, 0),
244 HDD5GHZCHAN(5915, 183, 0),
245 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800246};
247
248static struct ieee80211_rate g_mode_rates[] = {
249 HDD_G_MODE_RATETAB(10, 0x1, 0),
250 HDD_G_MODE_RATETAB(20, 0x2, 0),
251 HDD_G_MODE_RATETAB(55, 0x4, 0),
252 HDD_G_MODE_RATETAB(110, 0x8, 0),
253 HDD_G_MODE_RATETAB(60, 0x10, 0),
254 HDD_G_MODE_RATETAB(90, 0x20, 0),
255 HDD_G_MODE_RATETAB(120, 0x40, 0),
256 HDD_G_MODE_RATETAB(180, 0x80, 0),
257 HDD_G_MODE_RATETAB(240, 0x100, 0),
258 HDD_G_MODE_RATETAB(360, 0x200, 0),
259 HDD_G_MODE_RATETAB(480, 0x400, 0),
260 HDD_G_MODE_RATETAB(540, 0x800, 0),
261};
262
263static struct ieee80211_rate a_mode_rates[] = {
264 HDD_G_MODE_RATETAB(60, 0x10, 0),
265 HDD_G_MODE_RATETAB(90, 0x20, 0),
266 HDD_G_MODE_RATETAB(120, 0x40, 0),
267 HDD_G_MODE_RATETAB(180, 0x80, 0),
268 HDD_G_MODE_RATETAB(240, 0x100, 0),
269 HDD_G_MODE_RATETAB(360, 0x200, 0),
270 HDD_G_MODE_RATETAB(480, 0x400, 0),
271 HDD_G_MODE_RATETAB(540, 0x800, 0),
272};
273
274static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530275 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800276 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700277 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800278 .bitrates = g_mode_rates,
279 .n_bitrates = g_mode_rates_size,
280 .ht_cap.ht_supported = 1,
281 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
282 | IEEE80211_HT_CAP_GRN_FLD
283 | IEEE80211_HT_CAP_DSSSCCK40
284 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
285 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
286 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
287 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
288 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
289 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
290 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
291};
292
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800293static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530294 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800295 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700296 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800297 .bitrates = a_mode_rates,
298 .n_bitrates = a_mode_rates_size,
299 .ht_cap.ht_supported = 1,
300 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
301 | IEEE80211_HT_CAP_GRN_FLD
302 | IEEE80211_HT_CAP_DSSSCCK40
303 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
304 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
305 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
306 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
307 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
308 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
309 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
310 .vht_cap.vht_supported = 1,
311};
312
313/* This structure contain information what kind of frame are expected in
Jeff Johnsonf3826e12017-01-12 09:49:40 -0800314 * TX/RX direction for each kind of interface
315 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800316static const struct ieee80211_txrx_stypes
317 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
318 [NL80211_IFTYPE_STATION] = {
319 .tx = 0xffff,
320 .rx = BIT(SIR_MAC_MGMT_ACTION) |
321 BIT(SIR_MAC_MGMT_PROBE_REQ),
322 },
323 [NL80211_IFTYPE_AP] = {
324 .tx = 0xffff,
325 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
326 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
327 BIT(SIR_MAC_MGMT_PROBE_REQ) |
328 BIT(SIR_MAC_MGMT_DISASSOC) |
329 BIT(SIR_MAC_MGMT_AUTH) |
330 BIT(SIR_MAC_MGMT_DEAUTH) |
331 BIT(SIR_MAC_MGMT_ACTION),
332 },
333 [NL80211_IFTYPE_ADHOC] = {
334 .tx = 0xffff,
335 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
336 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
337 BIT(SIR_MAC_MGMT_PROBE_REQ) |
338 BIT(SIR_MAC_MGMT_DISASSOC) |
339 BIT(SIR_MAC_MGMT_AUTH) |
340 BIT(SIR_MAC_MGMT_DEAUTH) |
341 BIT(SIR_MAC_MGMT_ACTION),
342 },
343 [NL80211_IFTYPE_P2P_CLIENT] = {
344 .tx = 0xffff,
345 .rx = BIT(SIR_MAC_MGMT_ACTION) |
346 BIT(SIR_MAC_MGMT_PROBE_REQ),
347 },
348 [NL80211_IFTYPE_P2P_GO] = {
349 /* This is also same as for SoftAP */
350 .tx = 0xffff,
351 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
352 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
353 BIT(SIR_MAC_MGMT_PROBE_REQ) |
354 BIT(SIR_MAC_MGMT_DISASSOC) |
355 BIT(SIR_MAC_MGMT_AUTH) |
356 BIT(SIR_MAC_MGMT_DEAUTH) |
357 BIT(SIR_MAC_MGMT_ACTION),
358 },
359};
360
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800361/* Interface limits and combinations registered by the driver */
362
363/* STA ( + STA ) combination */
364static const struct ieee80211_iface_limit
365 wlan_hdd_sta_iface_limit[] = {
366 {
367 .max = 3, /* p2p0 is a STA as well */
368 .types = BIT(NL80211_IFTYPE_STATION),
369 },
370};
371
372/* ADHOC (IBSS) limit */
373static const struct ieee80211_iface_limit
374 wlan_hdd_adhoc_iface_limit[] = {
375 {
376 .max = 1,
377 .types = BIT(NL80211_IFTYPE_STATION),
378 },
379 {
380 .max = 1,
381 .types = BIT(NL80211_IFTYPE_ADHOC),
382 },
383};
384
385/* AP ( + AP ) combination */
386static const struct ieee80211_iface_limit
387 wlan_hdd_ap_iface_limit[] = {
388 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530389 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800390 .types = BIT(NL80211_IFTYPE_AP),
391 },
392};
393
394/* P2P limit */
395static const struct ieee80211_iface_limit
396 wlan_hdd_p2p_iface_limit[] = {
397 {
398 .max = 1,
399 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
400 },
401 {
402 .max = 1,
403 .types = BIT(NL80211_IFTYPE_P2P_GO),
404 },
405};
406
407static const struct ieee80211_iface_limit
408 wlan_hdd_sta_ap_iface_limit[] = {
409 {
410 /* We need 1 extra STA interface for OBSS scan when SAP starts
411 * with HT40 in STA+SAP concurrency mode
412 */
413 .max = (1 + SAP_MAX_OBSS_STA_CNT),
414 .types = BIT(NL80211_IFTYPE_STATION),
415 },
416 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530417 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800418 .types = BIT(NL80211_IFTYPE_AP),
419 },
420};
421
422/* STA + P2P combination */
423static const struct ieee80211_iface_limit
424 wlan_hdd_sta_p2p_iface_limit[] = {
425 {
426 /* One reserved for dedicated P2PDEV usage */
427 .max = 2,
428 .types = BIT(NL80211_IFTYPE_STATION)
429 },
430 {
431 /* Support for two identical (GO + GO or CLI + CLI)
432 * or dissimilar (GO + CLI) P2P interfaces
433 */
434 .max = 2,
435 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
436 },
437};
438
439/* STA + AP + P2PGO combination */
440static const struct ieee80211_iface_limit
441wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
442 /* Support for AP+P2PGO interfaces */
443 {
444 .max = 2,
445 .types = BIT(NL80211_IFTYPE_STATION)
446 },
447 {
448 .max = 1,
449 .types = BIT(NL80211_IFTYPE_P2P_GO)
450 },
451 {
452 .max = 1,
453 .types = BIT(NL80211_IFTYPE_AP)
454 }
455};
456
457/* SAP + P2P combination */
458static const struct ieee80211_iface_limit
459wlan_hdd_sap_p2p_iface_limit[] = {
460 {
461 /* 1 dedicated for p2p0 which is a STA type */
462 .max = 1,
463 .types = BIT(NL80211_IFTYPE_STATION)
464 },
465 {
466 /* The p2p interface in SAP+P2P can be GO/CLI.
467 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
468 */
469 .max = 1,
470 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
471 },
472 {
473 /* SAP+GO to support only one SAP interface */
474 .max = 1,
475 .types = BIT(NL80211_IFTYPE_AP)
476 }
477};
478
479/* P2P + P2P combination */
480static const struct ieee80211_iface_limit
481wlan_hdd_p2p_p2p_iface_limit[] = {
482 {
483 /* 1 dedicated for p2p0 which is a STA type */
484 .max = 1,
485 .types = BIT(NL80211_IFTYPE_STATION)
486 },
487 {
488 /* The p2p interface in P2P+P2P can be GO/CLI.
489 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
490 */
491 .max = 2,
492 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
493 },
494};
495
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700496static const struct ieee80211_iface_limit
497 wlan_hdd_mon_iface_limit[] = {
498 {
499 .max = 3, /* Monitor interface */
500 .types = BIT(NL80211_IFTYPE_MONITOR),
501 },
502};
503
504static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800505 wlan_hdd_iface_combination[] = {
506 /* STA */
507 {
508 .limits = wlan_hdd_sta_iface_limit,
509 .num_different_channels = 2,
510 .max_interfaces = 3,
511 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
512 },
513 /* ADHOC */
514 {
515 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700516 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800517 .max_interfaces = 2,
518 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
519 },
520 /* AP */
521 {
522 .limits = wlan_hdd_ap_iface_limit,
523 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530524 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800525 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
526 },
527 /* P2P */
528 {
529 .limits = wlan_hdd_p2p_iface_limit,
530 .num_different_channels = 2,
531 .max_interfaces = 2,
532 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
533 },
534 /* STA + AP */
535 {
536 .limits = wlan_hdd_sta_ap_iface_limit,
537 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530538 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800539 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
540 .beacon_int_infra_match = true,
541 },
542 /* STA + P2P */
543 {
544 .limits = wlan_hdd_sta_p2p_iface_limit,
545 .num_different_channels = 2,
546 /* one interface reserved for P2PDEV dedicated usage */
547 .max_interfaces = 4,
548 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
549 .beacon_int_infra_match = true,
550 },
551 /* STA + P2P GO + SAP */
552 {
553 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
554 /* we can allow 3 channels for three different persona
555 * but due to firmware limitation, allow max 2 concrnt channels.
556 */
557 .num_different_channels = 2,
558 /* one interface reserved for P2PDEV dedicated usage */
559 .max_interfaces = 4,
560 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
561 .beacon_int_infra_match = true,
562 },
563 /* SAP + P2P */
564 {
565 .limits = wlan_hdd_sap_p2p_iface_limit,
566 .num_different_channels = 2,
567 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
568 .max_interfaces = 3,
569 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
570 .beacon_int_infra_match = true,
571 },
572 /* P2P + P2P */
573 {
574 .limits = wlan_hdd_p2p_p2p_iface_limit,
575 .num_different_channels = 2,
576 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
577 .max_interfaces = 3,
578 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
579 .beacon_int_infra_match = true,
580 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530581 /* Monitor */
582 {
583 .limits = wlan_hdd_mon_iface_limit,
584 .max_interfaces = 3,
585 .num_different_channels = 2,
586 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
587 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800588};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800589
590static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800591
592#ifdef WLAN_NL80211_TESTMODE
593enum wlan_hdd_tm_attr {
594 WLAN_HDD_TM_ATTR_INVALID = 0,
595 WLAN_HDD_TM_ATTR_CMD = 1,
596 WLAN_HDD_TM_ATTR_DATA = 2,
597 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
598 WLAN_HDD_TM_ATTR_TYPE = 4,
599 /* keep last */
600 WLAN_HDD_TM_ATTR_AFTER_LAST,
601 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
602};
603
604enum wlan_hdd_tm_cmd {
605 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
606 WLAN_HDD_TM_CMD_WLAN_HB = 1,
607};
608
609#define WLAN_HDD_TM_DATA_MAX_LEN 5000
610
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530611enum wlan_hdd_vendor_ie_access_policy {
612 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
613 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
614};
615
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800616static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
617 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
618 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
619 .len = WLAN_HDD_TM_DATA_MAX_LEN},
620};
621#endif /* WLAN_NL80211_TESTMODE */
622
623#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
624static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
625 .flags = WIPHY_WOWLAN_MAGIC_PKT,
626 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
627 .pattern_min_len = 1,
628 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
629};
630#endif
631
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800632/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530633 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
634 * @flags: Pointer to the flags to Add channel switch flag.
635 *
636 * This Function adds Channel Switch support flag, if channel switch is
637 * supported by kernel.
638 * Return: void.
639 */
640#ifdef CHANNEL_SWITCH_SUPPORTED
641static inline void hdd_add_channel_switch_support(uint32_t *flags)
642{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800643 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530644 return;
645}
646#else
647static inline void hdd_add_channel_switch_support(uint32_t *flags)
648{
649 return;
650}
651#endif
652
Manikandan Mohan22b83722015-12-15 15:03:23 -0800653#ifdef FEATURE_WLAN_TDLS
654
655/* TDLS capabilities params */
656#define PARAM_MAX_TDLS_SESSION \
657 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
658#define PARAM_TDLS_FEATURE_SUPPORT \
659 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
660
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530661/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800662 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
663 * @wiphy: WIPHY structure pointer
664 * @wdev: Wireless device structure pointer
665 * @data: Pointer to the data received
666 * @data_len: Length of the data received
667 *
668 * This function provides TDLS capabilities
669 *
670 * Return: 0 on success and errno on failure
671 */
672static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
673 struct wireless_dev *wdev,
674 const void *data,
675 int data_len)
676{
677 int status;
678 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
679 struct sk_buff *skb;
680 uint32_t set = 0;
681
Jeff Johnson1f61b612016-02-12 16:28:33 -0800682 ENTER_DEV(wdev->netdev);
683
Anurag Chouhan6d760662016-02-20 16:05:43 +0530684 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800685 hdd_err("Command not allowed in FTM mode");
686 return -EPERM;
687 }
688
689 status = wlan_hdd_validate_context(hdd_ctx);
690 if (status)
691 return status;
692
693 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
694 NLMSG_HDRLEN);
695 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700696 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800697 goto fail;
698 }
699
700 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800701 hdd_debug("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800702 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
703 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700704 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800705 goto fail;
706 }
707 } else {
708 set = set | WIFI_TDLS_SUPPORT;
709 set = set | (hdd_ctx->config->fTDLSExternalControl ?
710 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
711 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
712 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Srinivas Girigowda13d39252017-03-06 16:12:15 -0800713 hdd_debug("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800714 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
715 hdd_ctx->max_num_tdls_sta) ||
716 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
717 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700718 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800719 goto fail;
720 }
721 }
722 return cfg80211_vendor_cmd_reply(skb);
723fail:
724 if (skb)
725 kfree_skb(skb);
726 return -EINVAL;
727}
728
729/**
730 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
731 * @wiphy: WIPHY structure pointer
732 * @wdev: Wireless device structure pointer
733 * @data: Pointer to the data received
734 * @data_len: Length of the data received
735 *
736 * This function provides TDLS capabilities
737 *
738 * Return: 0 on success and errno on failure
739 */
740static int
741wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
742 struct wireless_dev *wdev,
743 const void *data,
744 int data_len)
745{
746 int ret;
747
748 cds_ssr_protect(__func__);
749 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
750 data, data_len);
751 cds_ssr_unprotect(__func__);
752
753 return ret;
754}
755#endif
756
757#ifdef QCA_HT_2040_COEX
758static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
759#endif
760
761#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
762/*
763 * FUNCTION: wlan_hdd_send_avoid_freq_event
764 * This is called when wlan driver needs to send vendor specific
765 * avoid frequency range event to userspace
766 */
767int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
768 tHddAvoidFreqList *pAvoidFreqList)
769{
770 struct sk_buff *vendor_event;
771
772 ENTER();
773
774 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700775 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800776 return -EINVAL;
777 }
778
779 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700780 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800781 return -EINVAL;
782 }
783
784 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
785 NULL,
786 sizeof(tHddAvoidFreqList),
787 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
788 GFP_KERNEL);
789 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700790 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800791 return -EINVAL;
792 }
793
794 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
795 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
796
797 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
798
799 EXIT();
800 return 0;
801}
802#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
803
804/* vendor specific events */
805static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
806#ifdef FEATURE_WLAN_CH_AVOID
807 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
808 .vendor_id =
809 QCA_NL80211_VENDOR_ID,
810 .subcmd =
811 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
812 },
813#endif /* FEATURE_WLAN_CH_AVOID */
814
815#ifdef WLAN_FEATURE_NAN
816 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
817 .vendor_id =
818 QCA_NL80211_VENDOR_ID,
819 .subcmd =
820 QCA_NL80211_VENDOR_SUBCMD_NAN
821 },
822#endif
823
824#ifdef WLAN_FEATURE_STATS_EXT
825 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
826 .vendor_id =
827 QCA_NL80211_VENDOR_ID,
828 .subcmd =
829 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
830 },
831#endif /* WLAN_FEATURE_STATS_EXT */
832#ifdef FEATURE_WLAN_EXTSCAN
833 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
834 .vendor_id =
835 QCA_NL80211_VENDOR_ID,
836 .subcmd =
837 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
838 },
839 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
840 .vendor_id =
841 QCA_NL80211_VENDOR_ID,
842 .subcmd =
843 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
844 },
845 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
846 .
847 vendor_id
848 =
849 QCA_NL80211_VENDOR_ID,
850 .subcmd =
851 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
852 },
853 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
854 .
855 vendor_id
856 =
857 QCA_NL80211_VENDOR_ID,
858 .
859 subcmd =
860 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
861 },
862 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
863 .
864 vendor_id
865 =
866 QCA_NL80211_VENDOR_ID,
867 .
868 subcmd
869 =
870 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
871 },
872 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
873 .
874 vendor_id
875 =
876 QCA_NL80211_VENDOR_ID,
877 .subcmd =
878 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
879 },
880 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
881 .vendor_id =
882 QCA_NL80211_VENDOR_ID,
883 .subcmd =
884 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
885 },
886 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
887 .
888 vendor_id
889 =
890 QCA_NL80211_VENDOR_ID,
891 .subcmd =
892 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
893 },
894 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
895 .
896 vendor_id
897 =
898 QCA_NL80211_VENDOR_ID,
899 .subcmd =
900 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
901 },
902 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
903 .
904 vendor_id
905 =
906 QCA_NL80211_VENDOR_ID,
907 .
908 subcmd
909 =
910 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
911 },
912 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
913 .
914 vendor_id
915 =
916 QCA_NL80211_VENDOR_ID,
917 .
918 subcmd =
919 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
920 },
921 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
922 .
923 vendor_id
924 =
925 QCA_NL80211_VENDOR_ID,
926 .
927 subcmd
928 =
929 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
930 },
931 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
932 .
933 vendor_id
934 =
935 QCA_NL80211_VENDOR_ID,
936 .
937 subcmd
938 =
939 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
940 },
941 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
942 .vendor_id = QCA_NL80211_VENDOR_ID,
943 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
944 },
945 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
946 .vendor_id = QCA_NL80211_VENDOR_ID,
947 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
948 },
949#endif /* FEATURE_WLAN_EXTSCAN */
950
951#ifdef WLAN_FEATURE_LINK_LAYER_STATS
952 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
953 .vendor_id =
954 QCA_NL80211_VENDOR_ID,
955 .subcmd =
956 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
957 },
958 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
959 .vendor_id =
960 QCA_NL80211_VENDOR_ID,
961 .subcmd =
962 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
963 },
964 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
965 .vendor_id =
966 QCA_NL80211_VENDOR_ID,
967 .subcmd =
968 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
969 },
970 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
971 .vendor_id =
972 QCA_NL80211_VENDOR_ID,
973 .subcmd =
974 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
975 },
976 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
977 .vendor_id =
978 QCA_NL80211_VENDOR_ID,
979 .subcmd =
980 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
981 },
982 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
983 .vendor_id =
984 QCA_NL80211_VENDOR_ID,
985 .subcmd =
986 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
987 },
988#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 },
1046 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1047 .vendor_id = QCA_NL80211_VENDOR_ID,
1048 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1049 },
1050 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1051 .vendor_id = QCA_NL80211_VENDOR_ID,
1052 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1053 },
1054 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1055 .vendor_id = QCA_NL80211_VENDOR_ID,
1056 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1057 },
1058#endif /* FEATURE_WLAN_EXTSCAN */
1059 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1060 .vendor_id = QCA_NL80211_VENDOR_ID,
1061 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1062 },
1063#ifdef WLAN_FEATURE_MEMDUMP
1064 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1065 .vendor_id = QCA_NL80211_VENDOR_ID,
1066 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1067 },
1068#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001069#ifdef WLAN_FEATURE_TSF
1070 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1071 .vendor_id = QCA_NL80211_VENDOR_ID,
1072 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1073 },
1074#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001075 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1076 .vendor_id = QCA_NL80211_VENDOR_ID,
1077 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1078 },
1079 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1080 .vendor_id = QCA_NL80211_VENDOR_ID,
1081 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1082 },
1083 /* OCB events */
1084 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1085 .vendor_id = QCA_NL80211_VENDOR_ID,
1086 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1087 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001088#ifdef FEATURE_LFR_SUBNET_DETECTION
1089 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1090 .vendor_id = QCA_NL80211_VENDOR_ID,
1091 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1092 },
1093#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001094
1095#ifdef WLAN_FEATURE_NAN_DATAPATH
1096 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1097 .vendor_id = QCA_NL80211_VENDOR_ID,
1098 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1099 },
1100#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001101
1102 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1103 .vendor_id = QCA_NL80211_VENDOR_ID,
1104 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1105 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301106 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1107 .vendor_id = QCA_NL80211_VENDOR_ID,
1108 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1109 },
Kapil Gupta8878ad92017-02-13 11:56:04 +05301110 [QCA_NL80211_VENDOR_SUBCMD_UPDATE_EXTERNAL_ACS_CONFIG] = {
1111 .vendor_id = QCA_NL80211_VENDOR_ID,
1112 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS
1113 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001114#ifdef WLAN_UMAC_CONVERGENCE
1115 COMMON_VENDOR_EVENTS
1116#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001117};
1118
1119/**
1120 * __is_driver_dfs_capable() - get driver DFS capability
1121 * @wiphy: pointer to wireless wiphy structure.
1122 * @wdev: pointer to wireless_dev structure.
1123 * @data: Pointer to the data to be passed via vendor interface
1124 * @data_len:Length of the data to be passed
1125 *
1126 * This function is called by userspace to indicate whether or not
1127 * the driver supports DFS offload.
1128 *
1129 * Return: 0 on success, negative errno on failure
1130 */
1131static int __is_driver_dfs_capable(struct wiphy *wiphy,
1132 struct wireless_dev *wdev,
1133 const void *data,
1134 int data_len)
1135{
1136 u32 dfs_capability = 0;
1137 struct sk_buff *temp_skbuff;
1138 int ret_val;
1139 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1140
Jeff Johnson1f61b612016-02-12 16:28:33 -08001141 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001142
1143 ret_val = wlan_hdd_validate_context(hdd_ctx);
1144 if (ret_val)
1145 return ret_val;
1146
Anurag Chouhan6d760662016-02-20 16:05:43 +05301147 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001148 hdd_err("Command not allowed in FTM mode");
1149 return -EPERM;
1150 }
1151
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001152 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001153
1154 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1155 NLMSG_HDRLEN);
1156
1157 if (temp_skbuff != NULL) {
1158 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1159 dfs_capability);
1160 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001161 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001162 kfree_skb(temp_skbuff);
1163
1164 return ret_val;
1165 }
1166
1167 return cfg80211_vendor_cmd_reply(temp_skbuff);
1168 }
1169
Jeff Johnson020db452016-06-29 14:37:26 -07001170 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001171 return -ENOMEM;
1172}
1173
1174/**
1175 * is_driver_dfs_capable() - get driver DFS capability
1176 * @wiphy: pointer to wireless wiphy structure.
1177 * @wdev: pointer to wireless_dev structure.
1178 * @data: Pointer to the data to be passed via vendor interface
1179 * @data_len:Length of the data to be passed
1180 *
1181 * This function is called by userspace to indicate whether or not
1182 * the driver supports DFS offload. This is an SSR-protected
1183 * wrapper function.
1184 *
1185 * Return: 0 on success, negative errno on failure
1186 */
1187static int is_driver_dfs_capable(struct wiphy *wiphy,
1188 struct wireless_dev *wdev,
1189 const void *data,
1190 int data_len)
1191{
1192 int ret;
1193
1194 cds_ssr_protect(__func__);
1195 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1196 cds_ssr_unprotect(__func__);
1197
1198 return ret;
1199}
1200
1201/**
1202 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1203 *
1204 * @adapter: SAP adapter pointer
1205 *
1206 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1207 * radio. So in case of DFS MCC scenario override current SAP given config
1208 * to follow concurrent SAP DFS config
1209 *
1210 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1211 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001212int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1213{
1214 hdd_adapter_t *con_sap_adapter;
1215 tsap_Config_t *sap_config, *con_sap_config;
1216 int con_ch;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001217 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001218
1219 /*
1220 * Check if AP+AP case, once primary AP chooses a DFS
1221 * channel secondary AP should always follow primary APs channel
1222 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08001223 if (!policy_mgr_concurrent_beaconing_sessions_running(
1224 hdd_ctx->hdd_psoc))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001225 return 0;
1226
1227 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1228 if (!con_sap_adapter)
1229 return 0;
1230
1231 sap_config = &adapter->sessionCtx.ap.sapConfig;
1232 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1233 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1234
1235 if (!CDS_IS_DFS_CH(con_ch))
1236 return 0;
1237
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001238 hdd_debug("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001239 sap_config->channel, con_ch);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08001240 hdd_debug("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001241 sap_config->channel = con_ch;
1242
1243 if (con_sap_config->acs_cfg.acs_mode == true) {
1244 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1245 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001246 hdd_err("Primary AP channel config error");
1247 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001248 con_ch, con_sap_config->acs_cfg.pri_ch,
1249 con_sap_config->acs_cfg.ht_sec_ch);
1250 return -EINVAL;
1251 }
1252 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1253 * MCC restriction. So free ch list allocated in do_acs
1254 * func for Sec AP and realloc for Pri AP ch list size
1255 */
1256 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301257 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001258
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301259 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001260 &con_sap_config->acs_cfg,
1261 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301262 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001263 sizeof(uint8_t) *
1264 con_sap_config->acs_cfg.ch_list_count);
1265 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001266 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001267 return -ENOMEM;
1268 }
1269
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301270 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001271 con_sap_config->acs_cfg.ch_list,
1272 con_sap_config->acs_cfg.ch_list_count);
1273
1274 } else {
1275 sap_config->acs_cfg.pri_ch = con_ch;
1276 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1277 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1278 }
1279
1280 return con_ch;
1281}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001282
1283/**
1284 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1285 * @sap_cfg: pointer to SAP config struct
1286 *
1287 * This function sets the default ACS start and end channel for the given band
1288 * and also parses the given ACS channel list.
1289 *
1290 * Return: None
1291 */
1292
1293static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1294 bool vht_enabled)
1295{
1296 int i;
1297 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1298 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001299 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1300 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001301 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1302 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001303 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1304 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001305 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1306 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001307 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1308 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001309 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1310 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001311 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1312 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001313 }
1314
1315 if (ht_enabled)
1316 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1317
1318 if (vht_enabled)
1319 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1320
1321
1322 /* Parse ACS Chan list from hostapd */
1323 if (!sap_cfg->acs_cfg.ch_list)
1324 return;
1325
1326 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1327 sap_cfg->acs_cfg.end_ch =
1328 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1329 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301330 /* avoid channel as start channel */
1331 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1332 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001333 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1334 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1335 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1336 }
1337}
1338
1339
1340static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1341
1342/**
1343 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1344 * @adapter: pointer to SAP adapter struct
1345 *
1346 * This function starts the ACS procedure if there are no
1347 * constraints like MBSSID DFS restrictions.
1348 *
1349 * Return: Status of ACS Start procedure
1350 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301351int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001352{
1353
1354 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1355 tsap_Config_t *sap_config;
1356 tpWLAN_SAPEventCB acs_event_callback;
1357 int status;
1358
1359 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301360 if (hdd_ctx->acs_policy.acs_channel)
1361 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1362 else
1363 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001364
1365 status = wlan_hdd_sap_cfg_dfs_override(adapter);
Jeff Johnson68755312017-02-10 11:46:55 -08001366 if (status < 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001367 return status;
Jeff Johnson68755312017-02-10 11:46:55 -08001368
1369 if (status > 0) {
1370 /*notify hostapd about channel override */
1371 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1372 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1373 return 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001374 }
Jeff Johnson68755312017-02-10 11:46:55 -08001375
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001376 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1377 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001378 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001379 return -EINVAL;
1380 }
1381
1382 acs_event_callback = hdd_hostapd_sap_event_cb;
1383
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301384 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301385 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Kapil Gupta8878ad92017-02-13 11:56:04 +05301386 hdd_notice("ACS Started for %s", adapter->dev->name);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001387 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001388 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001389 acs_event_callback, sap_config, adapter->dev);
1390
1391
1392 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001393 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001394 return -EINVAL;
1395 }
bings394afdd2017-01-09 11:22:38 +08001396 if (sap_is_auto_channel_select(WLAN_HDD_GET_SAP_CTX_PTR(adapter)))
1397 sap_config->acs_cfg.acs_mode = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001398 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1399
1400 return 0;
1401}
1402
1403/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05301404 * wlan_hdd_sap_get_nol() - Get SAPs NOL
1405 * @ap_adapter: AP adapter
1406 * @nol: Non-occupancy list
1407 * @nol_len: Length of NOL
1408 *
1409 * Get the NOL for SAP
1410 *
1411 * Return: Zero on success, non-zero on failure
1412 */
1413static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
1414 uint32_t *nol_len)
1415{
1416 QDF_STATUS ret;
1417
1418 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
1419 nol, nol_len);
1420 if (QDF_IS_STATUS_ERROR(ret))
1421 return -EINVAL;
1422
1423 return 0;
1424}
1425
1426/**
Kapil Gupta8878ad92017-02-13 11:56:04 +05301427 * hdd_update_vendor_pcl_list() - This API will return unsorted pcl list
1428 * @hdd_ctx: hdd context
1429 * @acs_chan_params: external acs channel params
1430 * @sap_config: SAP config
1431 *
1432 * This API provides unsorted pcl list.
1433 * this list is a subset of the valid channel list given by hostapd.
1434 * if channel is not present in pcl, weightage will be given as zero
1435 *
1436 * Return: Zero on success, non-zero on failure
1437 */
1438static void hdd_update_vendor_pcl_list(hdd_context_t *hdd_ctx,
1439 struct hdd_vendor_acs_chan_params *acs_chan_params,
1440 tsap_Config_t *sap_config)
1441{
1442 int i, j;
1443
1444 for (i = 0; i < acs_chan_params->channel_count; i++) {
1445 for (j = 0; j < sap_config->acs_cfg.pcl_ch_count; j++) {
1446 if (acs_chan_params->channel_list[i] ==
1447 sap_config->acs_cfg.pcl_channels[j]) {
1448 acs_chan_params->vendor_pcl_list[i] =
1449 sap_config->acs_cfg.pcl_channels[j];
1450 acs_chan_params->vendor_weight_list[i] =
1451 sap_config->acs_cfg.
1452 pcl_channels_weight_list[j];
1453 break;
1454 } else {
1455 acs_chan_params->vendor_pcl_list[i] =
1456 acs_chan_params->channel_list[i];
1457 acs_chan_params->vendor_weight_list[i] = 0;
1458 }
1459 }
1460 }
1461 if (hdd_ctx->unsafe_channel_count == 0)
1462 return;
1463 /* Update unsafe channel weight as zero */
1464 for (i = 0; i < acs_chan_params->channel_count; i++) {
1465 for (j = 0; j < hdd_ctx->unsafe_channel_count; j++) {
1466 if (acs_chan_params->channel_list[i] ==
1467 hdd_ctx->unsafe_channel_list[j]) {
1468 acs_chan_params->vendor_weight_list[i] = 0;
1469 }
1470 }
1471 }
1472}
1473
1474/**
Kapil Gupta086c6202016-12-11 18:17:06 +05301475 * hdd_update_reg_chan_info : This API contructs channel info
1476 * for all the given channel
1477 * @adapter: pointer to SAP adapter struct
1478 * @channel_count: channel count
1479 * @channel_list: channel list
1480 *
1481 * Return: Status of of channel information updation
1482 */
Kapil Gupta8878ad92017-02-13 11:56:04 +05301483static int hdd_update_reg_chan_info(hdd_adapter_t *adapter,
Kapil Gupta086c6202016-12-11 18:17:06 +05301484 uint32_t channel_count,
1485 uint8_t *channel_list)
1486{
1487 int i;
1488 struct hdd_channel_info *icv;
Kapil Gupta8878ad92017-02-13 11:56:04 +05301489 struct ch_params_s ch_params = {0};
Kapil Gupta086c6202016-12-11 18:17:06 +05301490 uint8_t bw_offset = 0, chan = 0;
1491 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1492 tsap_Config_t *sap_config = &adapter->sessionCtx.ap.sapConfig;
1493
1494 /* memory allocation */
1495 sap_config->channel_info = qdf_mem_malloc(
1496 sizeof(struct hdd_channel_info) *
1497 channel_count);
1498 if (!sap_config->channel_info) {
1499 hdd_err("memory allocation failed");
1500 return -ENOMEM;
1501
1502 }
1503 for (i = 0; i < channel_count; i++) {
1504 icv = &sap_config->channel_info[i];
1505 chan = channel_list[i];
1506
1507 if (chan == 0)
1508 continue;
1509
1510 if (sap_config->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1511 bw_offset = 1 << BW_40_OFFSET_BIT;
1512 else if (sap_config->acs_cfg.ch_width == CH_WIDTH_20MHZ)
1513 bw_offset = 1 << BW_20_OFFSET_BIT;
1514 icv->freq = cds_get_channel_freq(chan);
1515 icv->ieee_chan_number = chan;
1516 icv->max_reg_power = cds_get_channel_reg_power(chan);
1517
1518 /* filling demo values */
1519 icv->max_radio_power = HDD_MAX_TX_POWER;
1520 icv->min_radio_power = HDD_MIN_TX_POWER;
1521 /* not supported in current driver */
1522 icv->max_antenna_gain = 0;
1523
1524 icv->reg_class_id = wlan_hdd_find_opclass(
1525 WLAN_HDD_GET_HAL_CTX(adapter),
1526 chan, bw_offset);
1527
1528 if (CDS_IS_CHANNEL_5GHZ(chan)) {
1529 ch_params.ch_width = sap_config->acs_cfg.ch_width;
1530 cds_set_channel_params(chan, 0, &ch_params);
1531 icv->vht_center_freq_seg0 = ch_params.center_freq_seg0;
1532 icv->vht_center_freq_seg1 = ch_params.center_freq_seg1;
1533 }
1534 icv->flags = 0;
1535 icv->flags = cds_get_vendor_reg_flags(chan,
1536 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
2825 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2826 data, data_len,
2827 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002828 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002829 return -EINVAL;
2830 }
2831 /* Parse and fetch Command Type*/
2832 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002833 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002834 goto fail;
2835 }
2836 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302837 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002838 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2839 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002840 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002841 goto fail;
2842 }
2843 req_id = nla_get_u32(
2844 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002845 hdd_debug("Req Id (%d)", req_id);
2846 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002847 switch (cmd_type) {
2848 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2849 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302850 if (tb[PARAM_NUM_NW]) {
2851 count = nla_get_u32(
2852 tb[PARAM_NUM_NW]);
2853 } else {
2854 hdd_err("Number of networks is not provided");
2855 goto fail;
2856 }
2857
2858 if (count &&
2859 tb[PRAM_SSID_LIST]) {
2860 nla_for_each_nested(curr_attr,
2861 tb[PRAM_SSID_LIST], rem) {
2862 if (nla_parse(tb2,
2863 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2864 nla_data(curr_attr), nla_len(curr_attr),
2865 NULL)) {
2866 hdd_err("nla_parse failed");
2867 goto fail;
2868 }
2869 /* Parse and Fetch allowed SSID list*/
2870 if (!tb2[PARAM_LIST_SSID]) {
2871 hdd_err("attr allowed ssid failed");
2872 goto fail;
2873 }
2874 buf_len = nla_len(tb2[PARAM_LIST_SSID]);
2875 /*
2876 * Upper Layers include a null termination
2877 * character. Check for the actual permissible
2878 * length of SSID and also ensure not to copy
2879 * the NULL termination character to the driver
2880 * buffer.
2881 */
2882 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2883 ((buf_len - 1) <=
2884 SIR_MAC_MAX_SSID_LENGTH)) {
2885 nla_memcpy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002886 roam_params.ssid_allowed_list[i].ssId,
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302887 tb2[PARAM_LIST_SSID], buf_len - 1);
2888 roam_params.ssid_allowed_list[i].length
2889 = buf_len - 1;
2890 hdd_debug("SSID[%d]: %.*s,length = %d",
2891 i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002892 roam_params.ssid_allowed_list[i].length,
2893 roam_params.ssid_allowed_list[i].ssId,
2894 roam_params.ssid_allowed_list[i].length);
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302895 i++;
2896 } else {
2897 hdd_err("Invalid buffer length");
2898 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002899 }
2900 }
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05302901 if (i != count) {
2902 hdd_err("Invalid number of SSIDs i = %d, count = %d",
2903 i, count);
2904 goto fail;
2905 }
2906
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002907 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002908 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002909 roam_params.num_ssid_allowed_list);
2910 sme_update_roam_params(pHddCtx->hHal, session_id,
2911 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2912 break;
2913 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2914 /* Parse and fetch 5G Boost Threshold */
2915 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002916 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002917 goto fail;
2918 }
2919 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2920 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002921 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002922 roam_params.raise_rssi_thresh_5g);
2923 /* Parse and fetch 5G Penalty Threshold */
2924 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002925 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002926 goto fail;
2927 }
2928 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2929 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002930 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002931 roam_params.drop_rssi_thresh_5g);
2932 /* Parse and fetch 5G Boost Factor */
2933 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002934 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002935 goto fail;
2936 }
2937 roam_params.raise_factor_5g = nla_get_u32(
2938 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002939 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002940 roam_params.raise_factor_5g);
2941 /* Parse and fetch 5G Penalty factor */
2942 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002943 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002944 goto fail;
2945 }
2946 roam_params.drop_factor_5g = nla_get_u32(
2947 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002948 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002949 roam_params.drop_factor_5g);
2950 /* Parse and fetch 5G Max Boost */
2951 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002952 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002953 goto fail;
2954 }
2955 roam_params.max_raise_rssi_5g = nla_get_u32(
2956 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002957 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002958 roam_params.max_raise_rssi_5g);
2959 /* Parse and fetch Rssi Diff */
2960 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002961 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002962 goto fail;
2963 }
2964 roam_params.rssi_diff = nla_get_s32(
2965 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002966 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002967 roam_params.rssi_diff);
2968 /* Parse and fetch Alert Rssi Threshold */
2969 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002970 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002971 goto fail;
2972 }
2973 roam_params.alert_rssi_threshold = nla_get_u32(
2974 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002975 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002976 roam_params.alert_rssi_threshold);
2977 sme_update_roam_params(pHddCtx->hHal, session_id,
2978 roam_params,
2979 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2980 break;
2981 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2982 /* Parse and fetch Activate Good Rssi Roam */
2983 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002984 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002985 goto fail;
2986 }
2987 roam_params.good_rssi_roam = nla_get_s32(
2988 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002989 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002990 roam_params.good_rssi_roam);
2991 sme_update_roam_params(pHddCtx->hHal, session_id,
2992 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2993 break;
2994 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2995 /* Parse and fetch number of preferred BSSID */
2996 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002997 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002998 goto fail;
2999 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003000 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003001 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003002 if (count > MAX_BSSID_FAVORED) {
3003 hdd_err("Preferred BSSID count %u exceeds max %u",
3004 count, MAX_BSSID_FAVORED);
3005 goto fail;
3006 }
3007 hdd_debug("Num of Preferred BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003008 i = 0;
3009 nla_for_each_nested(curr_attr,
3010 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
3011 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003012
3013 if (i == count) {
3014 hdd_warn("Ignoring excess Preferred BSSID");
3015 break;
3016 }
3017
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003018 if (nla_parse(tb2,
3019 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3020 nla_data(curr_attr), nla_len(curr_attr),
3021 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003022 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003023 goto fail;
3024 }
3025 /* Parse and fetch MAC address */
3026 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003027 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003028 goto fail;
3029 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003030 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003031 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05303032 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08003033 hdd_debug(MAC_ADDRESS_STR,
3034 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003035 /* Parse and fetch preference factor*/
3036 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003037 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003038 goto fail;
3039 }
3040 roam_params.bssid_favored_factor[i] = nla_get_u32(
3041 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07003042 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003043 roam_params.bssid_favored_factor[i]);
3044 i++;
3045 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003046 if (i < count)
3047 hdd_warn("Num Preferred BSSID %u less than expected %u",
3048 i, count);
3049 roam_params.num_bssid_favored = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003050 sme_update_roam_params(pHddCtx->hHal, session_id,
3051 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
3052 break;
3053 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
3054 /* Parse and fetch number of blacklist BSSID */
3055 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07003056 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003057 goto fail;
3058 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003059 count = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003060 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Prakash Dhavali075334e2016-11-29 07:22:08 -08003061 if (count > MAX_BSSID_AVOID_LIST) {
3062 hdd_err("Blacklist BSSID count %u exceeds max %u",
3063 count, MAX_BSSID_AVOID_LIST);
3064 goto fail;
3065 }
3066 hdd_debug("Num of blacklist BSSID (%d)", count);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003067 i = 0;
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303068
3069 if (count &&
3070 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS]) {
3071 nla_for_each_nested(curr_attr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003072 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
3073 rem) {
Prakash Dhavali075334e2016-11-29 07:22:08 -08003074
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303075 if (i == count) {
3076 hdd_warn("Ignoring excess Blacklist BSSID");
3077 break;
3078 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003079
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303080 if (nla_parse(tb2,
3081 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
3082 nla_data(curr_attr), nla_len(curr_attr),
3083 NULL)) {
3084 hdd_err("nla_parse failed");
3085 goto fail;
3086 }
3087 /* Parse and fetch MAC address */
3088 if (!tb2[PARAM_SET_BSSID]) {
3089 hdd_err("attr blacklist addr failed");
3090 goto fail;
3091 }
3092 nla_memcpy(
3093 roam_params.bssid_avoid_list[i].bytes,
3094 tb2[PARAM_SET_BSSID], QDF_MAC_ADDR_SIZE);
3095 hdd_debug(MAC_ADDRESS_STR,
3096 MAC_ADDR_ARRAY(
3097 roam_params.bssid_avoid_list[i].bytes));
3098 i++;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003099 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003100 }
Prakash Dhavali075334e2016-11-29 07:22:08 -08003101 if (i < count)
3102 hdd_warn("Num Blacklist BSSID %u less than expected %u",
3103 i, count);
3104 roam_params.num_bssid_avoid_list = i;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003105 sme_update_roam_params(pHddCtx->hHal, session_id,
3106 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
3107 break;
3108 }
3109 return 0;
3110fail:
3111 return -EINVAL;
3112}
Hanumanth Reddy Pothulaa1259ef2017-02-21 17:14:43 +05303113#undef PARAM_NUM_NW
3114#undef PARAM_SET_BSSID
3115#undef PRAM_SSID_LIST
3116#undef PARAM_LIST_SSID
3117
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003118
3119/**
3120 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
3121 * @wiphy: pointer to wireless wiphy structure.
3122 * @wdev: pointer to wireless_dev structure.
3123 * @data: Pointer to the data to be passed via vendor interface
3124 * @data_len:Length of the data to be passed
3125 *
3126 * Return: Return the Success or Failure code.
3127 */
3128static int
3129wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
3130 struct wireless_dev *wdev,
3131 const void *data,
3132 int data_len)
3133{
3134 int ret;
3135
3136 cds_ssr_protect(__func__);
3137 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
3138 data, data_len);
3139 cds_ssr_unprotect(__func__);
3140
3141 return ret;
3142}
3143
3144static const struct nla_policy
3145wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
3146 +1] = {
3147 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
3148};
3149
3150/**
3151 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
3152 * @hdd_ctx: HDD context
3153 * @device_mode: device mode
3154 * Return: bool
3155 */
3156static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08003157 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003158{
3159 hdd_adapter_t *adapter;
3160 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
3161 hdd_ap_ctx_t *ap_ctx;
3162 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303163 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003164
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303165 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003166 &adapter_node);
3167
3168 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303169 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003170 adapter = adapter_node->pAdapter;
3171
3172 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003173 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003174 ap_ctx =
3175 WLAN_HDD_GET_AP_CTX_PTR(adapter);
3176
3177 /*
3178 * if there is SAP already running on DFS channel,
3179 * do not disable scan on dfs channels. Note that
3180 * with SAP on DFS, there cannot be conurrency on
3181 * single radio. But then we can have multiple
3182 * radios !!
3183 */
3184 if (CHANNEL_STATE_DFS ==
3185 cds_get_channel_state(
3186 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003187 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003188 return true;
3189 }
3190 }
3191
3192 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08003193 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003194 sta_ctx =
3195 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3196
3197 /*
3198 * if STA is already connected on DFS channel,
3199 * do not disable scan on dfs channels
3200 */
3201 if (hdd_conn_is_connected(sta_ctx) &&
3202 (CHANNEL_STATE_DFS ==
3203 cds_get_channel_state(
3204 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07003205 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003206 return true;
3207 }
3208 }
3209
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303210 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003211 adapter_node,
3212 &next);
3213 adapter_node = next;
3214 }
3215
3216 return false;
3217}
3218
3219/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003220 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
3221 * @hdd_ctx: HDD context within host driver
3222 * @adapter: Adapter pointer
3223 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
3224 *
3225 * Loops through devices to see who is operating on DFS channels
3226 * and then disables/enables DFS channels by calling SME API.
3227 * Fails the disable request if any device is active on a DFS channel.
3228 *
3229 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003230 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003231
3232int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
3233 hdd_adapter_t *adapter,
3234 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003235{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003236 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303237 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003238 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003239
3240 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
3241 if (no_dfs_flag) {
3242 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003243 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003244
3245 if (true == status)
3246 return -EOPNOTSUPP;
3247
3248 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08003249 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003250
3251 if (true == status)
3252 return -EOPNOTSUPP;
3253 }
3254
3255 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
3256
3257 hdd_abort_mac_scan_all_adapters(hdd_ctx);
3258
3259 /*
3260 * call the SME API to tunnel down the new channel list
3261 * to the firmware
3262 */
3263 status = sme_handle_dfs_chan_scan(
3264 h_hal, hdd_ctx->config->enableDFSChnlScan);
3265
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303266 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003267 ret_val = 0;
3268
3269 /*
3270 * Clear the SME scan cache also. Note that the
3271 * clearing of scan results is independent of session;
3272 * so no need to iterate over
3273 * all sessions
3274 */
3275 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303276 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003277 ret_val = -EPERM;
3278 }
3279
3280 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003281 hdd_debug(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003282 ret_val = 0;
3283 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003284 return ret_val;
3285}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003286
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003287/**
3288 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
3289 * @wiphy: corestack handler
3290 * @wdev: wireless device
3291 * @data: data
3292 * @data_len: data length
3293 * Return: success(0) or reason code for failure
3294 */
3295static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3296 struct wireless_dev *wdev,
3297 const void *data,
3298 int data_len)
3299{
3300 struct net_device *dev = wdev->netdev;
3301 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3302 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3303 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
3304 int ret_val;
3305 uint32_t no_dfs_flag = 0;
3306
Jeff Johnson1f61b612016-02-12 16:28:33 -08003307 ENTER_DEV(dev);
3308
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003309 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303310 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003311 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003312
3313 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
3314 data, data_len,
3315 wlan_hdd_set_no_dfs_flag_config_policy)) {
3316 hdd_err("invalid attr");
3317 return -EINVAL;
3318 }
3319
3320 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
3321 hdd_err("attr dfs flag failed");
3322 return -EINVAL;
3323 }
3324
3325 no_dfs_flag = nla_get_u32(
3326 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
3327
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003328 hdd_debug("DFS flag: %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003329
3330 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07003331 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08003332 return -EINVAL;
3333 }
3334
3335 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
3336 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003337 return ret_val;
3338}
3339
3340/**
3341 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
3342 *
3343 * @wiphy: wiphy device pointer
3344 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07003345 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003346 * @data_len: Buffer length
3347 *
3348 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
3349 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
3350 *
3351 * Return: EOK or other error codes.
3352 */
3353
3354static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
3355 struct wireless_dev *wdev,
3356 const void *data,
3357 int data_len)
3358{
3359 int ret;
3360
3361 cds_ssr_protect(__func__);
3362 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
3363 data, data_len);
3364 cds_ssr_unprotect(__func__);
3365
3366 return ret;
3367}
3368
Manikandan Mohan80dea792016-04-28 16:36:48 -07003369static const struct nla_policy
3370wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
3371 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
3372};
3373
3374/**
3375 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3376 * @wiphy: wiphy device pointer
3377 * @wdev: wireless device pointer
3378 * @data: Vendor command data buffer
3379 * @data_len: Buffer length
3380 *
3381 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3382 * setup WISA Mode features.
3383 *
3384 * Return: Success(0) or reason code for failure
3385 */
3386static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3387 struct wireless_dev *wdev, const void *data, int data_len)
3388{
3389 struct net_device *dev = wdev->netdev;
3390 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3391 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3392 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
3393 struct sir_wisa_params wisa;
3394 int ret_val;
3395 QDF_STATUS status;
3396 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07003397 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
3398 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003399
3400 ENTER_DEV(dev);
3401 ret_val = wlan_hdd_validate_context(hdd_ctx);
3402 if (ret_val)
3403 goto err;
3404
3405 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3406 hdd_err("Command not allowed in FTM mode");
3407 return -EPERM;
3408 }
3409
3410 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
3411 wlan_hdd_wisa_cmd_policy)) {
3412 hdd_err("Invalid WISA cmd attributes");
3413 ret_val = -EINVAL;
3414 goto err;
3415 }
3416 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
3417 hdd_err("Invalid WISA mode");
3418 ret_val = -EINVAL;
3419 goto err;
3420 }
3421
3422 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08003423 hdd_debug("WISA Mode: %d", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003424 wisa.mode = wisa_mode;
3425 wisa.vdev_id = adapter->sessionId;
3426 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003427 if (!QDF_IS_STATUS_SUCCESS(status)) {
3428 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003429 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07003430 }
3431 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07003432 cdp_set_wisa_mode(soc,
Venkata Sharath Chandra Manchala0d44d452016-11-23 17:48:15 -08003433 (struct cdp_vdev *)cdp_get_vdev_from_vdev_id(soc,
3434 (struct cdp_pdev *)pdev,
Leo Changfdb45c32016-10-28 11:09:23 -07003435 adapter->sessionId),
3436 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07003437err:
3438 EXIT();
3439 return ret_val;
3440}
3441
3442/**
3443 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
3444 * @wiphy: corestack handler
3445 * @wdev: wireless device
3446 * @data: data
3447 * @data_len: data length
3448 *
3449 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
3450 * setup WISA mode features.
3451 *
3452 * Return: Success(0) or reason code for failure
3453 */
3454static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
3455 struct wireless_dev *wdev,
3456 const void *data,
3457 int data_len)
3458{
3459 int ret;
3460
3461 cds_ssr_protect(__func__);
3462 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
3463 cds_ssr_unprotect(__func__);
3464
3465 return ret;
3466}
3467
Anurag Chouhan96919482016-07-13 16:36:57 +05303468/*
3469 * define short names for the global vendor params
3470 * used by __wlan_hdd_cfg80211_get_station_cmd()
3471 */
3472#define STATION_INVALID \
3473 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
3474#define STATION_INFO \
3475 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
3476#define STATION_ASSOC_FAIL_REASON \
3477 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
3478#define STATION_MAX \
3479 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
3480
3481static const struct nla_policy
3482hdd_get_station_policy[STATION_MAX + 1] = {
3483 [STATION_INFO] = {.type = NLA_FLAG},
3484 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
3485};
3486
3487/**
3488 * hdd_get_station_assoc_fail() - Handle get station assoc fail
3489 * @hdd_ctx: HDD context within host driver
3490 * @wdev: wireless device
3491 *
3492 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
3493 * Validate cmd attributes and send the station info to upper layers.
3494 *
3495 * Return: Success(0) or reason code for failure
3496 */
3497static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
3498 hdd_adapter_t *adapter)
3499{
3500 struct sk_buff *skb = NULL;
3501 uint32_t nl_buf_len;
3502 hdd_station_ctx_t *hdd_sta_ctx;
3503
3504 nl_buf_len = NLMSG_HDRLEN;
3505 nl_buf_len += sizeof(uint32_t);
3506 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3507
3508 if (!skb) {
3509 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
3510 return -ENOMEM;
3511 }
3512
3513 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3514
3515 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
3516 hdd_sta_ctx->conn_info.assoc_status_code)) {
3517 hdd_err("put fail");
3518 goto fail;
3519 }
3520 return cfg80211_vendor_cmd_reply(skb);
3521fail:
3522 if (skb)
3523 kfree_skb(skb);
3524 return -EINVAL;
3525}
3526
3527/**
3528 * hdd_map_auth_type() - transform auth type specific to
3529 * vendor command
3530 * @auth_type: csr auth type
3531 *
3532 * Return: Success(0) or reason code for failure
3533 */
3534static int hdd_convert_auth_type(uint32_t auth_type)
3535{
3536 uint32_t ret_val;
3537
3538 switch (auth_type) {
3539 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3540 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3541 break;
3542 case eCSR_AUTH_TYPE_SHARED_KEY:
3543 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3544 break;
3545 case eCSR_AUTH_TYPE_WPA:
3546 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3547 break;
3548 case eCSR_AUTH_TYPE_WPA_PSK:
3549 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3550 break;
3551 case eCSR_AUTH_TYPE_AUTOSWITCH:
3552 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3553 break;
3554 case eCSR_AUTH_TYPE_WPA_NONE:
3555 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3556 break;
3557 case eCSR_AUTH_TYPE_RSN:
3558 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3559 break;
3560 case eCSR_AUTH_TYPE_RSN_PSK:
3561 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3562 break;
3563 case eCSR_AUTH_TYPE_FT_RSN:
3564 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3565 break;
3566 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3567 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3568 break;
3569 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3570 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3571 break;
3572 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3573 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3574 break;
3575 case eCSR_AUTH_TYPE_CCKM_WPA:
3576 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3577 break;
3578 case eCSR_AUTH_TYPE_CCKM_RSN:
3579 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3580 break;
3581 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3582 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3583 break;
3584 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3585 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3586 break;
3587 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3588 case eCSR_AUTH_TYPE_FAILED:
3589 case eCSR_AUTH_TYPE_NONE:
3590 default:
3591 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3592 break;
3593 }
3594 return ret_val;
3595}
3596
3597/**
3598 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3599 * vendor command
3600 * @dot11mode: dot11mode
3601 *
3602 * Return: Success(0) or reason code for failure
3603 */
3604static int hdd_convert_dot11mode(uint32_t dot11mode)
3605{
3606 uint32_t ret_val;
3607
3608 switch (dot11mode) {
3609 case eCSR_CFG_DOT11_MODE_11A:
3610 ret_val = QCA_WLAN_802_11_MODE_11A;
3611 break;
3612 case eCSR_CFG_DOT11_MODE_11B:
3613 ret_val = QCA_WLAN_802_11_MODE_11B;
3614 break;
3615 case eCSR_CFG_DOT11_MODE_11G:
3616 ret_val = QCA_WLAN_802_11_MODE_11G;
3617 break;
3618 case eCSR_CFG_DOT11_MODE_11N:
3619 ret_val = QCA_WLAN_802_11_MODE_11N;
3620 break;
3621 case eCSR_CFG_DOT11_MODE_11AC:
3622 ret_val = QCA_WLAN_802_11_MODE_11AC;
3623 break;
3624 case eCSR_CFG_DOT11_MODE_AUTO:
3625 case eCSR_CFG_DOT11_MODE_ABG:
3626 default:
3627 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3628 }
3629 return ret_val;
3630}
3631
3632/**
3633 * hdd_add_tx_bitrate() - add tx bitrate attribute
3634 * @skb: pointer to sk buff
3635 * @hdd_sta_ctx: pointer to hdd station context
3636 * @idx: attribute index
3637 *
3638 * Return: Success(0) or reason code for failure
3639 */
3640static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3641 hdd_station_ctx_t *hdd_sta_ctx,
3642 int idx)
3643{
3644 struct nlattr *nla_attr;
3645 uint32_t bitrate, bitrate_compat;
3646
3647 nla_attr = nla_nest_start(skb, idx);
3648 if (!nla_attr)
3649 goto fail;
3650 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3651 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3652
3653 /* report 16-bit bitrate only if we can */
3654 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3655 if (bitrate > 0 &&
3656 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3657 hdd_err("put fail");
3658 goto fail;
3659 }
3660 if (bitrate_compat > 0 &&
3661 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3662 hdd_err("put fail");
3663 goto fail;
3664 }
3665 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3666 hdd_sta_ctx->conn_info.txrate.nss)) {
3667 hdd_err("put fail");
3668 goto fail;
3669 }
3670 nla_nest_end(skb, nla_attr);
3671 return 0;
3672fail:
3673 return -EINVAL;
3674}
3675
3676/**
3677 * hdd_add_sta_info() - add station info attribute
3678 * @skb: pointer to sk buff
3679 * @hdd_sta_ctx: pointer to hdd station context
3680 * @idx: attribute index
3681 *
3682 * Return: Success(0) or reason code for failure
3683 */
3684static int32_t hdd_add_sta_info(struct sk_buff *skb,
3685 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3686{
3687 struct nlattr *nla_attr;
3688
3689 nla_attr = nla_nest_start(skb, idx);
3690 if (!nla_attr)
3691 goto fail;
3692 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3693 (hdd_sta_ctx->conn_info.signal + 100))) {
3694 hdd_err("put fail");
3695 goto fail;
3696 }
3697 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3698 goto fail;
3699 nla_nest_end(skb, nla_attr);
3700 return 0;
3701fail:
3702 return -EINVAL;
3703}
3704
3705/**
3706 * hdd_add_survey_info() - add survey info attribute
3707 * @skb: pointer to sk buff
3708 * @hdd_sta_ctx: pointer to hdd station context
3709 * @idx: attribute index
3710 *
3711 * Return: Success(0) or reason code for failure
3712 */
3713static int32_t hdd_add_survey_info(struct sk_buff *skb,
3714 hdd_station_ctx_t *hdd_sta_ctx,
3715 int idx)
3716{
3717 struct nlattr *nla_attr;
3718
3719 nla_attr = nla_nest_start(skb, idx);
3720 if (!nla_attr)
3721 goto fail;
3722 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3723 hdd_sta_ctx->conn_info.freq) ||
3724 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3725 (hdd_sta_ctx->conn_info.noise + 100))) {
3726 hdd_err("put fail");
3727 goto fail;
3728 }
3729 nla_nest_end(skb, nla_attr);
3730 return 0;
3731fail:
3732 return -EINVAL;
3733}
3734
3735/**
3736 * hdd_add_link_standard_info() - add link info attribute
3737 * @skb: pointer to sk buff
3738 * @hdd_sta_ctx: pointer to hdd station context
3739 * @idx: attribute index
3740 *
3741 * Return: Success(0) or reason code for failure
3742 */
3743static int32_t
3744hdd_add_link_standard_info(struct sk_buff *skb,
3745 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3746{
3747 struct nlattr *nla_attr;
3748
3749 nla_attr = nla_nest_start(skb, idx);
3750 if (!nla_attr)
3751 goto fail;
3752 if (nla_put(skb,
3753 NL80211_ATTR_SSID,
3754 hdd_sta_ctx->conn_info.SSID.SSID.length,
3755 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3756 hdd_err("put fail");
3757 goto fail;
3758 }
3759 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3760 goto fail;
3761 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3762 goto fail;
3763 nla_nest_end(skb, nla_attr);
3764 return 0;
3765fail:
3766 return -EINVAL;
3767}
3768
3769/**
3770 * hdd_add_ap_standard_info() - add ap info attribute
3771 * @skb: pointer to sk buff
3772 * @hdd_sta_ctx: pointer to hdd station context
3773 * @idx: attribute index
3774 *
3775 * Return: Success(0) or reason code for failure
3776 */
3777static int32_t
3778hdd_add_ap_standard_info(struct sk_buff *skb,
3779 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3780{
3781 struct nlattr *nla_attr;
3782
3783 nla_attr = nla_nest_start(skb, idx);
3784 if (!nla_attr)
3785 goto fail;
3786 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3787 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3788 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3789 &hdd_sta_ctx->conn_info.vht_caps)) {
3790 hdd_err("put fail");
3791 goto fail;
3792 }
3793 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3794 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3795 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3796 &hdd_sta_ctx->conn_info.ht_caps)) {
3797 hdd_err("put fail");
3798 goto fail;
3799 }
3800 nla_nest_end(skb, nla_attr);
3801 return 0;
3802fail:
3803 return -EINVAL;
3804}
3805
3806/**
3807 * hdd_get_station_info() - send BSS information to supplicant
3808 * @hdd_ctx: pointer to hdd context
3809 * @adapter: pointer to adapter
3810 *
3811 * Return: 0 if success else error status
3812 */
3813static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3814 hdd_adapter_t *adapter)
3815{
3816 struct sk_buff *skb = NULL;
3817 uint8_t *tmp_hs20 = NULL;
3818 uint32_t nl_buf_len;
3819 hdd_station_ctx_t *hdd_sta_ctx;
3820
3821 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3822
3823 nl_buf_len = NLMSG_HDRLEN;
3824 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3825 sizeof(hdd_sta_ctx->conn_info.freq) +
3826 sizeof(hdd_sta_ctx->conn_info.noise) +
3827 sizeof(hdd_sta_ctx->conn_info.signal) +
3828 (sizeof(uint32_t) * 2) +
3829 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3830 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3831 sizeof(hdd_sta_ctx->conn_info.authType) +
3832 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3833 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3834 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3835 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3836 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3837 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3838 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3839 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3840 1);
3841 }
3842 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3843 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3844 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3845 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3846
3847
3848 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3849 if (!skb) {
3850 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3851 return -ENOMEM;
3852 }
3853
3854 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3855 LINK_INFO_STANDARD_NL80211_ATTR)) {
3856 hdd_err("put fail");
3857 goto fail;
3858 }
3859 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3860 AP_INFO_STANDARD_NL80211_ATTR)) {
3861 hdd_err("put fail");
3862 goto fail;
3863 }
3864 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3865 hdd_sta_ctx->conn_info.roam_count) ||
3866 nla_put_u32(skb, INFO_AKM,
3867 hdd_convert_auth_type(
3868 hdd_sta_ctx->conn_info.authType)) ||
3869 nla_put_u32(skb, WLAN802_11_MODE,
3870 hdd_convert_dot11mode(
3871 hdd_sta_ctx->conn_info.dot11Mode))) {
3872 hdd_err("put fail");
3873 goto fail;
3874 }
3875 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3876 if (nla_put(skb, HT_OPERATION,
3877 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3878 &hdd_sta_ctx->conn_info.ht_operation)) {
3879 hdd_err("put fail");
3880 goto fail;
3881 }
3882 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3883 if (nla_put(skb, VHT_OPERATION,
3884 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3885 &hdd_sta_ctx->conn_info.vht_operation)) {
3886 hdd_err("put fail");
3887 goto fail;
3888 }
3889 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3890 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3891 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3892 tmp_hs20 + 1)) {
3893 hdd_err("put fail");
3894 goto fail;
3895 }
3896
3897 return cfg80211_vendor_cmd_reply(skb);
3898fail:
3899 if (skb)
3900 kfree_skb(skb);
3901 return -EINVAL;
3902}
3903
3904/**
3905 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3906 * @wiphy: corestack handler
3907 * @wdev: wireless device
3908 * @data: data
3909 * @data_len: data length
3910 *
3911 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3912 * Validate cmd attributes and send the station info to upper layers.
3913 *
3914 * Return: Success(0) or reason code for failure
3915 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303916static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303917__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3918 struct wireless_dev *wdev,
3919 const void *data,
3920 int data_len)
3921{
3922 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3923 struct net_device *dev = wdev->netdev;
3924 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3925 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3926 int32_t status;
3927
3928 ENTER_DEV(dev);
3929 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3930 hdd_err("Command not allowed in FTM mode");
3931 status = -EPERM;
3932 goto out;
3933 }
3934
3935 status = wlan_hdd_validate_context(hdd_ctx);
3936 if (0 != status)
3937 goto out;
3938
3939
3940 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3941 data, data_len, NULL);
3942 if (status) {
3943 hdd_err("Invalid ATTR");
3944 goto out;
3945 }
3946
3947 /* Parse and fetch Command Type*/
3948 if (tb[STATION_INFO]) {
3949 status = hdd_get_station_info(hdd_ctx, adapter);
3950 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3951 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3952 } else {
3953 hdd_err("get station info cmd type failed");
3954 status = -EINVAL;
3955 goto out;
3956 }
3957 EXIT();
3958out:
3959 return status;
3960}
3961
3962/**
3963 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3964 * @wiphy: corestack handler
3965 * @wdev: wireless device
3966 * @data: data
3967 * @data_len: data length
3968 *
3969 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3970 * Validate cmd attributes and send the station info to upper layers.
3971 *
3972 * Return: Success(0) or reason code for failure
3973 */
3974static int32_t
3975hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3976 struct wireless_dev *wdev,
3977 const void *data,
3978 int data_len)
3979{
3980 int ret;
3981
3982 cds_ssr_protect(__func__);
3983 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3984 cds_ssr_unprotect(__func__);
3985
3986 return ret;
3987}
3988
3989/*
3990 * undef short names defined for get station command
3991 * used by __wlan_hdd_cfg80211_get_station_cmd()
3992 */
3993#undef STATION_INVALID
3994#undef STATION_INFO
3995#undef STATION_ASSOC_FAIL_REASON
3996#undef STATION_MAX
3997
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003998#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3999/**
4000 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4001 * @wiphy: pointer to wireless wiphy structure.
4002 * @wdev: pointer to wireless_dev structure.
4003 * @data: Pointer to the Key data
4004 * @data_len:Length of the data passed
4005 *
4006 * This is called when wlan driver needs to save the keys received via
4007 * vendor specific command.
4008 *
4009 * Return: Return the Success or Failure code.
4010 */
4011static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4012 struct wireless_dev *wdev,
4013 const void *data, int data_len)
4014{
4015 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
4016 struct net_device *dev = wdev->netdev;
4017 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
4018 hdd_context_t *hdd_ctx_ptr;
4019 int status;
4020
Jeff Johnson1f61b612016-02-12 16:28:33 -08004021 ENTER_DEV(dev);
4022
Anurag Chouhan6d760662016-02-20 16:05:43 +05304023 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004024 hdd_err("Command not allowed in FTM mode");
4025 return -EPERM;
4026 }
4027
4028 if ((data == NULL) || (data_len == 0) ||
4029 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004030 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004031 return -EINVAL;
4032 }
4033
4034 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
4035 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07004036 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004037 return -EINVAL;
4038 }
4039
4040 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304041 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004042 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004043 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
4044 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07004045 true,
4046 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304047 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
4048 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004049 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
4050 hdd_adapter_ptr->sessionId, local_pmk, data_len);
4051 return 0;
4052}
4053
4054/**
4055 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
4056 * @wiphy: pointer to wireless wiphy structure.
4057 * @wdev: pointer to wireless_dev structure.
4058 * @data: Pointer to the Key data
4059 * @data_len:Length of the data passed
4060 *
4061 * This is called when wlan driver needs to save the keys received via
4062 * vendor specific command.
4063 *
4064 * Return: Return the Success or Failure code.
4065 */
4066static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
4067 struct wireless_dev *wdev,
4068 const void *data, int data_len)
4069{
4070 int ret;
4071
4072 cds_ssr_protect(__func__);
4073 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
4074 cds_ssr_unprotect(__func__);
4075
4076 return ret;
4077}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004078#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004079
4080static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
4081 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
4082 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
4083 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07004084 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004085};
4086
4087/**
4088 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4089 * @wiphy: pointer to wireless wiphy structure.
4090 * @wdev: pointer to wireless_dev structure.
4091 * @data: Pointer to the data to be passed via vendor interface
4092 * @data_len:Length of the data to be passed
4093 *
4094 * This is called when wlan driver needs to send wifi driver related info
4095 * (driver/fw version) to the user space application upon request.
4096 *
4097 * Return: Return the Success or Failure code.
4098 */
4099static int
4100__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4101 struct wireless_dev *wdev,
4102 const void *data, int data_len)
4103{
4104 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4105 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07004106 tSirVersionString driver_version;
4107 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004108 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004109 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07004110 struct sk_buff *reply_skb;
4111 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004112
Jeff Johnson1f61b612016-02-12 16:28:33 -08004113 ENTER_DEV(wdev->netdev);
4114
Anurag Chouhan6d760662016-02-20 16:05:43 +05304115 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004116 hdd_err("Command not allowed in FTM mode");
4117 return -EPERM;
4118 }
4119
4120 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304121 if (status)
4122 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004123
4124 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
4125 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004126 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004127 return -EINVAL;
4128 }
4129
4130 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004131 hdd_err("Rcvd req for Driver version");
4132 strlcpy(driver_version, QWLAN_VERSIONSTR,
4133 sizeof(driver_version));
4134 skb_len += strlen(driver_version) + 1;
4135 count++;
4136 }
4137
4138 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004139 hdd_debug("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004140 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
4141 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004142 snprintf(firmware_version, sizeof(firmware_version),
4143 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
4144 skb_len += strlen(firmware_version) + 1;
4145 count++;
4146 }
4147
4148 if (count == 0) {
4149 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004150 return -EINVAL;
4151 }
4152
Ryan Hsu7ac88852016-04-28 10:20:34 -07004153 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
4154 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
4155
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004156 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004157 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004158 return -ENOMEM;
4159 }
4160
Ryan Hsu7ac88852016-04-28 10:20:34 -07004161 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
4162 if (nla_put_string(reply_skb,
4163 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
4164 driver_version))
4165 goto error_nla_fail;
4166 }
4167
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05304168 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07004169 if (nla_put_string(reply_skb,
4170 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
4171 firmware_version))
4172 goto error_nla_fail;
4173 }
4174
4175 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
4176 if (nla_put_u32(reply_skb,
4177 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
4178 hdd_ctx->radio_index))
4179 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004180 }
4181
4182 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07004183
4184error_nla_fail:
4185 hdd_err("nla put fail");
4186 kfree_skb(reply_skb);
4187 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004188}
4189
4190/**
4191 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
4192 * @wiphy: pointer to wireless wiphy structure.
4193 * @wdev: pointer to wireless_dev structure.
4194 * @data: Pointer to the data to be passed via vendor interface
4195 * @data_len:Length of the data to be passed
4196 *
4197 * This is called when wlan driver needs to send wifi driver related info
4198 * (driver/fw version) to the user space application upon request.
4199 *
4200 * Return: Return the Success or Failure code.
4201 */
4202static int
4203wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
4204 struct wireless_dev *wdev,
4205 const void *data, int data_len)
4206{
4207 int ret;
4208
4209 cds_ssr_protect(__func__);
4210 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
4211 cds_ssr_unprotect(__func__);
4212
4213 return ret;
4214}
4215
4216/**
4217 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4218 * @wiphy: pointer to wireless wiphy structure.
4219 * @wdev: pointer to wireless_dev structure.
4220 * @data: Pointer to the data to be passed via vendor interface
4221 * @data_len:Length of the data to be passed
4222 *
4223 * This is called by userspace to know the supported logger features
4224 *
4225 * Return: Return the Success or Failure code.
4226 */
4227static int
4228__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4229 struct wireless_dev *wdev,
4230 const void *data, int data_len)
4231{
4232 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4233 int status;
4234 uint32_t features;
4235 struct sk_buff *reply_skb = NULL;
4236
Jeff Johnson1f61b612016-02-12 16:28:33 -08004237 ENTER_DEV(wdev->netdev);
4238
Anurag Chouhan6d760662016-02-20 16:05:43 +05304239 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004240 hdd_err("Command not allowed in FTM mode");
4241 return -EPERM;
4242 }
4243
4244 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304245 if (status)
4246 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004247
4248 features = 0;
4249
4250 if (hdd_is_memdump_supported())
4251 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
4252 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
4253 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
4254 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
4255
4256 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
4257 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
4258 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004259 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004260 return -ENOMEM;
4261 }
4262
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004263 hdd_debug("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004264 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
4265 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004266 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004267 kfree_skb(reply_skb);
4268 return -EINVAL;
4269 }
4270
4271 return cfg80211_vendor_cmd_reply(reply_skb);
4272}
4273
4274/**
4275 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
4276 * @wiphy: pointer to wireless wiphy structure.
4277 * @wdev: pointer to wireless_dev structure.
4278 * @data: Pointer to the data to be passed via vendor interface
4279 * @data_len:Length of the data to be passed
4280 *
4281 * This is called by userspace to know the supported logger features
4282 *
4283 * Return: Return the Success or Failure code.
4284 */
4285static int
4286wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
4287 struct wireless_dev *wdev,
4288 const void *data, int data_len)
4289{
4290 int ret;
4291
4292 cds_ssr_protect(__func__);
4293 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
4294 data, data_len);
4295 cds_ssr_unprotect(__func__);
4296
4297 return ret;
4298}
4299
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004300#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004301/**
4302 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
Prakash Dhavali989127d2016-11-29 14:56:44 +05304303 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004304 * @bssid: pointer to bssid of roamed AP.
4305 * @req_rsn_ie: Pointer to request RSN IE
4306 * @req_rsn_len: Length of the request RSN IE
4307 * @rsp_rsn_ie: Pointer to response RSN IE
4308 * @rsp_rsn_len: Length of the response RSN IE
4309 * @roam_info_ptr: Pointer to the roaming related information
4310 *
4311 * This is called when wlan driver needs to send the roaming and
4312 * authorization information after roaming.
4313 *
4314 * The information that would be sent is the request RSN IE, response
4315 * RSN IE and BSSID of the newly roamed AP.
4316 *
4317 * If the Authorized status is authenticated, then additional parameters
4318 * like PTK's KCK and KEK and Replay Counter would also be passed to the
4319 * supplicant.
4320 *
4321 * The supplicant upon receiving this event would ignore the legacy
4322 * cfg80211_roamed call and use the entire information from this event.
4323 * The cfg80211_roamed should still co-exist since the kernel will
4324 * make use of the parameters even if the supplicant ignores it.
4325 *
4326 * Return: Return the Success or Failure code.
4327 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05304328int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004329 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
4330 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
4331{
Prakash Dhavali989127d2016-11-29 14:56:44 +05304332 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004333 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004334 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004335 ENTER();
4336
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304337 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004338 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004339
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07004340 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08004341 !roam_info_ptr->roamSynchInProgress)
4342 return 0;
4343
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004344 /*
4345 * The user space has issued a disconnect when roaming is in
4346 * progress. The disconnect should be honored gracefully.
4347 * If the roaming is complete and the roam event is sent
4348 * back to the user space, it will get confused as it is
4349 * expecting a disconnect event. So, do not send the event
4350 * and handle the disconnect later.
4351 */
4352 if (adapter->defer_disconnect) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004353 hdd_debug("LFR3:Do not send roam auth event");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -08004354 return 0;
4355 }
4356
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004357 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05304358 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004359 ETH_ALEN + req_rsn_len + rsp_rsn_len +
4360 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
4361 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004362 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004363 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
4364 GFP_KERNEL);
4365
4366 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07004367 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004368 return -EINVAL;
4369 }
4370
4371 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
4372 ETH_ALEN, bssid) ||
4373 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
4374 req_rsn_len, req_rsn_ie) ||
4375 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
4376 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004377 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004378 goto nla_put_failure;
4379 }
Jeff Johnson020db452016-06-29 14:37:26 -07004380 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004381 if (roam_info_ptr->synchAuthStatus ==
4382 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07004383 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08004384 if (nla_put_u8(skb,
4385 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
4386 hdd_err("nla put fail");
4387 goto nla_put_failure;
4388 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08004389 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
4390 /* if FT or CCKM connection: dont send replay counter */
4391 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
4392 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
4393 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
4394 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
4395 nla_put(skb,
4396 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
4397 SIR_REPLAY_CTR_LEN,
4398 roam_info_ptr->replay_ctr)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004399 hdd_err("non FT/non CCKM connection");
4400 hdd_err("failed to send replay counter");
Naveen Rawat14298b92015-11-25 16:27:41 -08004401 goto nla_put_failure;
4402 }
4403 if (nla_put(skb,
4404 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
4405 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
4406 nla_put(skb,
4407 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
4408 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
4409 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004410 goto nla_put_failure;
4411 }
4412 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07004413 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004414 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
4415 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004416 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004417 goto nla_put_failure;
4418 }
4419 }
4420
Jeff Johnson020db452016-06-29 14:37:26 -07004421 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004422 roam_info_ptr->subnet_change_status);
4423
4424 /*
4425 * Add subnet change status if subnet has changed
4426 * 0 = unchanged
4427 * 1 = changed
4428 * 2 = unknown
4429 */
4430 if (roam_info_ptr->subnet_change_status) {
4431 if (nla_put_u8(skb,
4432 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
4433 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07004434 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08004435 goto nla_put_failure;
4436 }
4437 }
4438
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004439 cfg80211_vendor_event(skb, GFP_KERNEL);
4440 return 0;
4441
4442nla_put_failure:
4443 kfree_skb(skb);
4444 return -EINVAL;
4445}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08004446#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004447
4448static const struct nla_policy
4449wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
4450
4451 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
4452 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
4453 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304454 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304455 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
4456 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004457 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
4458 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
4459 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
4460 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
4461 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304462 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004463};
4464
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004465/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304466 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
4467 *
4468 * @adapter: Pointer to HDD adapter
4469 * @ie_data: Pointer to Scan IEs buffer
4470 * @ie_len: Length of Scan IEs
4471 *
4472 * Return: 0 on success; error number otherwise
4473 */
4474static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
4475 uint8_t *ie_data, uint8_t ie_len)
4476{
4477 hdd_scaninfo_t *scan_info = NULL;
4478 scan_info = &adapter->scan_info;
4479
4480 if (scan_info->default_scan_ies) {
4481 qdf_mem_free(scan_info->default_scan_ies);
4482 scan_info->default_scan_ies = NULL;
4483 }
4484
4485 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
4486 if (!scan_info->default_scan_ies)
4487 return -ENOMEM;
4488
4489 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
4490 scan_info->default_scan_ies_len = ie_len;
4491 return 0;
4492}
4493
4494/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004495 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4496 * vendor command
4497 *
4498 * @wiphy: wiphy device pointer
4499 * @wdev: wireless device pointer
4500 * @data: Vendor command data buffer
4501 * @data_len: Buffer length
4502 *
4503 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4504 *
4505 * Return: Error code.
4506 */
4507static int
4508__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4509 struct wireless_dev *wdev,
4510 const void *data,
4511 int data_len)
4512{
4513 struct net_device *dev = wdev->netdev;
4514 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4515 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4516 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
4517 int ret_val = 0;
4518 u32 modulated_dtim;
4519 u16 stats_avg_factor;
4520 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304521 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07004522 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07004523 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304524 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304525 int attr_len;
4526 int access_policy = 0;
4527 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
4528 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304529 uint16_t scan_ie_len = 0;
4530 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304531 struct sir_set_tx_rx_aggregation_size request;
4532 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004533 uint8_t retry, delay;
4534 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304535 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304536
Jeff Johnson1f61b612016-02-12 16:28:33 -08004537 ENTER_DEV(dev);
4538
Anurag Chouhan6d760662016-02-20 16:05:43 +05304539 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004540 hdd_err("Command not allowed in FTM mode");
4541 return -EPERM;
4542 }
4543
4544 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304545 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004546 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004547
4548 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4549 data, data_len,
4550 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004551 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004552 return -EINVAL;
4553 }
4554
Krunal Sonie3531942016-04-12 17:43:53 -07004555 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4556 ftm_capab = nla_get_u32(tb[
4557 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4558 hdd_ctx->config->fine_time_meas_cap =
4559 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4560 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304561 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004562 hdd_ctx->config->fine_time_meas_cap);
Naveen Rawat5f040ba2017-03-06 12:20:25 -08004563 os_if_wifi_pos_set_ftm_cap(hdd_ctx->hdd_psoc,
4564 hdd_ctx->config->fine_time_meas_cap);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004565 hdd_debug("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
Krunal Sonie3531942016-04-12 17:43:53 -07004566 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4567 hdd_ctx->config->fine_time_meas_cap);
4568 }
4569
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004570 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4571 modulated_dtim = nla_get_u32(
4572 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4573
4574 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4575 adapter->sessionId,
4576 modulated_dtim);
4577
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304578 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004579 ret_val = -EPERM;
4580 }
4581
Kapil Gupta6213c012016-09-02 19:39:09 +05304582 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4583 qpower = nla_get_u8(
4584 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4585 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4586 ret_val = -EINVAL;
4587 }
4588
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004589 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4590 stats_avg_factor = nla_get_u16(
4591 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4592 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4593 adapter->sessionId,
4594 stats_avg_factor);
4595
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304596 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004597 ret_val = -EPERM;
4598 }
4599
4600
4601 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4602 guard_time = nla_get_u32(
4603 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4604 status = sme_configure_guard_time(hdd_ctx->hHal,
4605 adapter->sessionId,
4606 guard_time);
4607
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304608 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004609 ret_val = -EPERM;
4610 }
4611
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304612 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4613 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4614 attr_len = nla_len(
4615 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4616 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004617 hdd_err("Invalid value. attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304618 attr_len);
4619 return -EINVAL;
4620 }
4621
4622 nla_memcpy(&vendor_ie,
4623 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4624 attr_len);
4625 vendor_ie_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004626 hdd_debug("Access policy vendor ie present.attr_len %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304627 attr_len);
4628 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4629 &vendor_ie[0], attr_len);
4630 }
4631
4632 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4633 access_policy = (int) nla_get_u32(
4634 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4635 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4636 (access_policy >
4637 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004638 hdd_err("Invalid value. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304639 access_policy);
4640 return -EINVAL;
4641 }
4642 access_policy_present = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004643 hdd_debug("Access policy present. access_policy %d",
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304644 access_policy);
4645 }
4646
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004647 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4648 retry = nla_get_u8(tb[
4649 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4650 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4651 CFG_NON_AGG_RETRY_MAX : retry;
4652 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4653 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4654 retry, PDEV_CMD);
4655 }
4656
4657 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4658 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4659 retry = retry > CFG_AGG_RETRY_MAX ?
4660 CFG_AGG_RETRY_MAX : retry;
4661
4662 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4663 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4664 CFG_AGG_RETRY_MIN : retry;
4665 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4666 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4667 retry, PDEV_CMD);
4668 }
4669
4670 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4671 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4672 retry = retry > CFG_MGMT_RETRY_MAX ?
4673 CFG_MGMT_RETRY_MAX : retry;
4674 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4675 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4676 retry, PDEV_CMD);
4677 }
4678
4679 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4680 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4681 retry = retry > CFG_CTRL_RETRY_MAX ?
4682 CFG_CTRL_RETRY_MAX : retry;
4683 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4684 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4685 retry, PDEV_CMD);
4686 }
4687
4688 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4689 delay = nla_get_u8(tb[
4690 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4691 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4692 CFG_PROPAGATION_DELAY_MAX : delay;
4693 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4694 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4695 delay, PDEV_CMD);
4696 }
4697
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304698 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4699 tx_fail_count = nla_get_u32(
4700 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4701 if (tx_fail_count) {
4702 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4703 adapter->sessionId, tx_fail_count);
4704 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004705 hdd_err("sme_update_tx_fail_cnt_threshold (err=%d)",
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304706 status);
4707 return -EINVAL;
4708 }
4709 }
4710 }
4711
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304712 if (vendor_ie_present && access_policy_present) {
4713 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4714 access_policy =
4715 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304716 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304717 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304718 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304719
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004720 hdd_debug("calling sme_update_access_policy_vendor_ie");
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304721 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4722 adapter->sessionId, &vendor_ie[0],
4723 access_policy);
4724 if (QDF_STATUS_SUCCESS != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004725 hdd_err("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304726 return -EINVAL;
4727 }
4728 }
4729
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304730 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4731 set_value = nla_get_u8(
4732 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004733 hdd_debug("set_value: %d", set_value);
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304734 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4735 }
4736
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304737 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4738 scan_ie_len = nla_len(
4739 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004740 hdd_debug("Received default scan IE of len %d session %d device mode %d",
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304741 scan_ie_len, adapter->sessionId,
4742 adapter->device_mode);
4743 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4744 scan_ie = (uint8_t *) nla_data(tb
4745 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304746
4747 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4748 scan_ie_len))
4749 hdd_err("Failed to save default scan IEs");
4750
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304751 if (adapter->device_mode == QDF_STA_MODE) {
4752 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4753 adapter->sessionId, scan_ie,
4754 scan_ie_len);
4755 if (QDF_STATUS_SUCCESS != status)
4756 ret_val = -EPERM;
4757 }
4758 } else
4759 ret_val = -EPERM;
4760 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304761
4762 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4763 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4764 /* if one is specified, both must be specified */
4765 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4766 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4767 hdd_err("Both TX and RX MPDU Aggregation required");
4768 return -EINVAL;
4769 }
4770
4771 request.tx_aggregation_size = nla_get_u8(
4772 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4773 request.rx_aggregation_size = nla_get_u8(
4774 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4775 request.vdev_id = adapter->sessionId;
4776
4777 if (request.tx_aggregation_size >=
4778 CFG_TX_AGGREGATION_SIZE_MIN &&
4779 request.tx_aggregation_size <=
4780 CFG_TX_AGGREGATION_SIZE_MAX &&
4781 request.rx_aggregation_size >=
4782 CFG_RX_AGGREGATION_SIZE_MIN &&
4783 request.rx_aggregation_size <=
4784 CFG_RX_AGGREGATION_SIZE_MAX) {
4785 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4786 if (qdf_status != QDF_STATUS_SUCCESS) {
4787 hdd_err("failed to set aggr sizes err %d",
4788 qdf_status);
4789 ret_val = -EPERM;
4790 }
4791 } else {
4792 hdd_err("TX %d RX %d MPDU aggr size not in range",
4793 request.tx_aggregation_size,
4794 request.rx_aggregation_size);
4795 ret_val = -EINVAL;
4796 }
4797 }
4798
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304799 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4800 uint8_t ignore_assoc_disallowed;
4801
4802 ignore_assoc_disallowed
4803 = nla_get_u8(tb[
4804 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004805 hdd_debug("Set ignore_assoc_disallowed value - %d",
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304806 ignore_assoc_disallowed);
4807 if ((ignore_assoc_disallowed <
4808 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4809 (ignore_assoc_disallowed >
4810 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4811 return -EPERM;
4812
4813 sme_update_session_param(hdd_ctx->hHal,
4814 adapter->sessionId,
4815 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4816 ignore_assoc_disallowed);
4817 }
4818
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004819 return ret_val;
4820}
4821
4822/**
4823 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4824 * vendor command
4825 *
4826 * @wiphy: wiphy device pointer
4827 * @wdev: wireless device pointer
4828 * @data: Vendor command data buffer
4829 * @data_len: Buffer length
4830 *
4831 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4832 *
4833 * Return: EOK or other error codes.
4834 */
4835static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4836 struct wireless_dev *wdev,
4837 const void *data,
4838 int data_len)
4839{
4840 int ret;
4841
4842 cds_ssr_protect(__func__);
4843 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4844 data, data_len);
4845 cds_ssr_unprotect(__func__);
4846
4847 return ret;
4848}
4849
4850static const struct
4851nla_policy
4852qca_wlan_vendor_wifi_logger_start_policy
4853[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4854 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4855 = {.type = NLA_U32 },
4856 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4857 = {.type = NLA_U32 },
4858 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4859 = {.type = NLA_U32 },
4860};
4861
4862/**
4863 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4864 * or disable the collection of packet statistics from the firmware
4865 * @wiphy: WIPHY structure pointer
4866 * @wdev: Wireless device structure pointer
4867 * @data: Pointer to the data received
4868 * @data_len: Length of the data received
4869 *
4870 * This function enables or disables the collection of packet statistics from
4871 * the firmware
4872 *
4873 * Return: 0 on success and errno on failure
4874 */
4875static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4876 struct wireless_dev *wdev,
4877 const void *data,
4878 int data_len)
4879{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304880 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004881 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4882 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4883 struct sir_wifi_start_log start_log;
4884
Jeff Johnson1f61b612016-02-12 16:28:33 -08004885 ENTER_DEV(wdev->netdev);
4886
Anurag Chouhan6d760662016-02-20 16:05:43 +05304887 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004888 hdd_err("Command not allowed in FTM mode");
4889 return -EPERM;
4890 }
4891
4892 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304893 if (status)
4894 return status;
4895
Ashish Kumar Dhanotiya3c308422017-03-02 16:48:56 +05304896 if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) {
4897 hdd_err("Driver Modules are closed, can not start logger");
4898 return -EINVAL;
4899 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004900
4901 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4902 data, data_len,
4903 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004904 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004905 return -EINVAL;
4906 }
4907
4908 /* Parse and fetch ring id */
4909 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004910 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004911 return -EINVAL;
4912 }
4913 start_log.ring_id = nla_get_u32(
4914 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004915 hdd_debug("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004916
4917 /* Parse and fetch verbose level */
4918 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004919 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004920 return -EINVAL;
4921 }
4922 start_log.verbose_level = nla_get_u32(
4923 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004924 hdd_debug("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004925
4926 /* Parse and fetch flag */
4927 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004928 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004929 return -EINVAL;
4930 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304931 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004932 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08004933 hdd_debug("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004934
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304935 /* size is buff size which can be set using iwpriv command*/
4936 start_log.size = 0;
4937
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004938 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4939
4940 if (start_log.ring_id == RING_ID_WAKELOCK) {
4941 /* Start/stop wakelock events */
4942 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4943 cds_set_wakelock_logging(true);
4944 else
4945 cds_set_wakelock_logging(false);
4946 return 0;
4947 }
4948
4949 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304950 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004951 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004952 status);
4953 return -EINVAL;
4954 }
4955 return 0;
4956}
4957
4958/**
4959 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4960 * or disable the collection of packet statistics from the firmware
4961 * @wiphy: WIPHY structure pointer
4962 * @wdev: Wireless device structure pointer
4963 * @data: Pointer to the data received
4964 * @data_len: Length of the data received
4965 *
4966 * This function is used to enable or disable the collection of packet
4967 * statistics from the firmware
4968 *
4969 * Return: 0 on success and errno on failure
4970 */
4971static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4972 struct wireless_dev *wdev,
4973 const void *data,
4974 int data_len)
4975{
4976 int ret = 0;
4977
4978 cds_ssr_protect(__func__);
4979 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4980 wdev, data, data_len);
4981 cds_ssr_unprotect(__func__);
4982
4983 return ret;
4984}
4985
4986static const struct
4987nla_policy
4988qca_wlan_vendor_wifi_logger_get_ring_data_policy
4989[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4990 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4991 = {.type = NLA_U32 },
4992};
4993
4994/**
4995 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4996 * @wiphy: WIPHY structure pointer
4997 * @wdev: Wireless device structure pointer
4998 * @data: Pointer to the data received
4999 * @data_len: Length of the data received
5000 *
5001 * This function is used to flush or retrieve the per packet statistics from
5002 * the driver
5003 *
5004 * Return: 0 on success and errno on failure
5005 */
5006static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5007 struct wireless_dev *wdev,
5008 const void *data,
5009 int data_len)
5010{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305011 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005012 uint32_t ring_id;
5013 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5014 struct nlattr *tb
5015 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
5016
Jeff Johnson1f61b612016-02-12 16:28:33 -08005017 ENTER_DEV(wdev->netdev);
5018
Anurag Chouhan6d760662016-02-20 16:05:43 +05305019 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005020 hdd_err("Command not allowed in FTM mode");
5021 return -EPERM;
5022 }
5023
5024 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305025 if (status)
5026 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005027
5028 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
5029 data, data_len,
5030 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005031 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005032 return -EINVAL;
5033 }
5034
5035 /* Parse and fetch ring id */
5036 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005037 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005038 return -EINVAL;
5039 }
5040
5041 ring_id = nla_get_u32(
5042 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
5043
5044 if (ring_id == RING_ID_PER_PACKET_STATS) {
5045 wlan_logging_set_per_pkt_stats();
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005046 hdd_debug("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05305047 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
5048 /*
5049 * As part of DRIVER ring ID, flush both driver and fw logs.
5050 * For other Ring ID's driver doesn't have any rings to flush
5051 */
5052 hdd_notice("Bug report triggered by framework");
5053
5054 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
5055 WLAN_LOG_INDICATOR_FRAMEWORK,
5056 WLAN_LOG_REASON_CODE_UNUSED,
5057 true, false);
5058 if (QDF_STATUS_SUCCESS != status) {
5059 hdd_err("Failed to trigger bug report");
5060 return -EINVAL;
5061 }
5062 } else {
5063 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
5064 WLAN_LOG_INDICATOR_FRAMEWORK,
5065 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005066 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005067 return 0;
5068}
5069
5070/**
5071 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
5072 * @wiphy: WIPHY structure pointer
5073 * @wdev: Wireless device structure pointer
5074 * @data: Pointer to the data received
5075 * @data_len: Length of the data received
5076 *
5077 * This function is used to flush or retrieve the per packet statistics from
5078 * the driver
5079 *
5080 * Return: 0 on success and errno on failure
5081 */
5082static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
5083 struct wireless_dev *wdev,
5084 const void *data,
5085 int data_len)
5086{
5087 int ret = 0;
5088
5089 cds_ssr_protect(__func__);
5090 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
5091 wdev, data, data_len);
5092 cds_ssr_unprotect(__func__);
5093
5094 return ret;
5095}
5096
5097#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
5098/**
5099 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
5100 * @hdd_ctx: HDD context
5101 * @request_id: [input] request id
5102 * @pattern_id: [output] pattern id
5103 *
5104 * This function loops through request id to pattern id array
5105 * if the slot is available, store the request id and return pattern id
5106 * if entry exists, return the pattern id
5107 *
5108 * Return: 0 on success and errno on failure
5109 */
5110static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5111 uint32_t request_id,
5112 uint8_t *pattern_id)
5113{
5114 uint32_t i;
5115
5116 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5117 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5118 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
5119 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
5120 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5121 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5122 return 0;
5123 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
5124 request_id) {
5125 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5126 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5127 return 0;
5128 }
5129 }
5130 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5131 return -EINVAL;
5132}
5133
5134/**
5135 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
5136 * @hdd_ctx: HDD context
5137 * @request_id: [input] request id
5138 * @pattern_id: [output] pattern id
5139 *
5140 * This function loops through request id to pattern id array
5141 * reset request id to 0 (slot available again) and
5142 * return pattern id
5143 *
5144 * Return: 0 on success and errno on failure
5145 */
5146static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
5147 uint32_t request_id,
5148 uint8_t *pattern_id)
5149{
5150 uint32_t i;
5151
5152 mutex_lock(&hdd_ctx->op_ctx.op_lock);
5153 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
5154 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
5155 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
5156 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
5157 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5158 return 0;
5159 }
5160 }
5161 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
5162 return -EINVAL;
5163}
5164
5165
5166/*
5167 * define short names for the global vendor params
5168 * used by __wlan_hdd_cfg80211_offloaded_packets()
5169 */
5170#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
5171#define PARAM_REQUEST_ID \
5172 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
5173#define PARAM_CONTROL \
5174 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
5175#define PARAM_IP_PACKET \
5176 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
5177#define PARAM_SRC_MAC_ADDR \
5178 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
5179#define PARAM_DST_MAC_ADDR \
5180 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
5181#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
5182
5183/**
5184 * wlan_hdd_add_tx_ptrn() - add tx pattern
5185 * @adapter: adapter pointer
5186 * @hdd_ctx: hdd context
5187 * @tb: nl attributes
5188 *
5189 * This function reads the NL attributes and forms a AddTxPtrn message
5190 * posts it to SME.
5191 *
5192 */
5193static int
5194wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5195 struct nlattr **tb)
5196{
5197 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305198 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005199 uint32_t request_id, ret, len;
5200 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05305201 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005202 uint16_t eth_type = htons(ETH_P_IP);
5203
5204 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005205 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005206 return -ENOTSUPP;
5207 }
5208
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305209 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005210 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005211 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005212 return -ENOMEM;
5213 }
5214
5215 /* Parse and fetch request Id */
5216 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005217 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005218 goto fail;
5219 }
5220
5221 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5222 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005223 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005224 return -EINVAL;
5225 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005226 hdd_debug("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005227
5228 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005229 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005230 goto fail;
5231 }
5232 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005233 hdd_debug("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005234 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07005235 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005236 goto fail;
5237 }
5238
5239 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005240 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005241 goto fail;
5242 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08005243 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05305244 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005245 hdd_debug("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005246 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005247
Anurag Chouhanc5548422016-02-24 18:33:27 +05305248 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08005249 &adapter->macAddressCurrent)) {
5250 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005251 goto fail;
5252 }
5253
5254 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005255 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005256 goto fail;
5257 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05305258 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005259 hdd_debug("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005260 MAC_ADDR_ARRAY(dst_addr.bytes));
5261
5262 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005263 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005264 goto fail;
5265 }
5266 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005267 hdd_debug("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005268
5269 if (add_req->ucPtrnSize < 0 ||
5270 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
5271 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005272 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005273 add_req->ucPtrnSize);
5274 goto fail;
5275 }
5276
5277 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305278 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05305279 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305280 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305281 QDF_MAC_ADDR_SIZE);
5282 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305283 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005284 len += 2;
5285
5286 /*
5287 * This is the IP packet, add 14 bytes Ethernet (802.3) header
5288 * ------------------------------------------------------------
5289 * | 14 bytes Ethernet (802.3) header | IP header and payload |
5290 * ------------------------------------------------------------
5291 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305292 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005293 nla_data(tb[PARAM_IP_PACKET]),
5294 add_req->ucPtrnSize);
5295 add_req->ucPtrnSize += len;
5296
5297 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5298 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005299 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005300 goto fail;
5301 }
5302 add_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005303 hdd_debug("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005304
5305 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305306 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005307 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005308 goto fail;
5309 }
5310
5311 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305312 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005313 return 0;
5314
5315fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305316 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005317 return -EINVAL;
5318}
5319
5320/**
5321 * wlan_hdd_del_tx_ptrn() - delete tx pattern
5322 * @adapter: adapter pointer
5323 * @hdd_ctx: hdd context
5324 * @tb: nl attributes
5325 *
5326 * This function reads the NL attributes and forms a DelTxPtrn message
5327 * posts it to SME.
5328 *
5329 */
5330static int
5331wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
5332 struct nlattr **tb)
5333{
5334 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305335 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005336 uint32_t request_id, ret;
5337 uint8_t pattern_id = 0;
5338
5339 /* Parse and fetch request Id */
5340 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005341 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005342 return -EINVAL;
5343 }
5344 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5345 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07005346 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005347 return -EINVAL;
5348 }
5349
5350 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
5351 if (ret) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005352 hdd_err("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005353 return -EINVAL;
5354 }
5355
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305356 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005357 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07005358 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005359 return -ENOMEM;
5360 }
5361
Anurag Chouhanc5548422016-02-24 18:33:27 +05305362 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005363 hdd_debug(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005364 del_req->ucPtrnId = pattern_id;
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005365 hdd_debug("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005366 request_id, del_req->ucPtrnId);
5367
5368 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305369 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005370 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005371 goto fail;
5372 }
5373
5374 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305375 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005376 return 0;
5377
5378fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305379 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005380 return -EINVAL;
5381}
5382
5383
5384/**
5385 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
5386 * @wiphy: Pointer to wireless phy
5387 * @wdev: Pointer to wireless device
5388 * @data: Pointer to data
5389 * @data_len: Data length
5390 *
5391 * Return: 0 on success, negative errno on failure
5392 */
5393static int
5394__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5395 struct wireless_dev *wdev,
5396 const void *data,
5397 int data_len)
5398{
5399 struct net_device *dev = wdev->netdev;
5400 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5401 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5402 struct nlattr *tb[PARAM_MAX + 1];
5403 uint8_t control;
5404 int ret;
5405 static const struct nla_policy policy[PARAM_MAX + 1] = {
5406 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5407 [PARAM_CONTROL] = { .type = NLA_U32 },
5408 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305409 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005410 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305411 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005412 [PARAM_PERIOD] = { .type = NLA_U32 },
5413 };
5414
Jeff Johnson1f61b612016-02-12 16:28:33 -08005415 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005416
Anurag Chouhan6d760662016-02-20 16:05:43 +05305417 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005418 hdd_err("Command not allowed in FTM mode");
5419 return -EPERM;
5420 }
5421
5422 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305423 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005424 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005425
5426 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005427 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005428 return -ENOTSUPP;
5429 }
5430
5431 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005432 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005433 return -EINVAL;
5434 }
5435
5436 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005437 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005438 return -EINVAL;
5439 }
5440 control = nla_get_u32(tb[PARAM_CONTROL]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005441 hdd_debug("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005442
5443 if (control == WLAN_START_OFFLOADED_PACKETS)
5444 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005445 if (control == WLAN_STOP_OFFLOADED_PACKETS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005446 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
Jeff Johnson68755312017-02-10 11:46:55 -08005447
5448 hdd_err("Invalid control: %d", control);
5449
5450 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005451}
5452
5453/*
5454 * done with short names for the global vendor params
5455 * used by __wlan_hdd_cfg80211_offloaded_packets()
5456 */
5457#undef PARAM_MAX
5458#undef PARAM_REQUEST_ID
5459#undef PARAM_CONTROL
5460#undef PARAM_IP_PACKET
5461#undef PARAM_SRC_MAC_ADDR
5462#undef PARAM_DST_MAC_ADDR
5463#undef PARAM_PERIOD
5464
5465/**
5466 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
5467 * @wiphy: wiphy structure pointer
5468 * @wdev: Wireless device structure pointer
5469 * @data: Pointer to the data received
5470 * @data_len: Length of @data
5471 *
5472 * Return: 0 on success; errno on failure
5473 */
5474static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
5475 struct wireless_dev *wdev,
5476 const void *data,
5477 int data_len)
5478{
5479 int ret = 0;
5480
5481 cds_ssr_protect(__func__);
5482 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
5483 wdev, data, data_len);
5484 cds_ssr_unprotect(__func__);
5485
5486 return ret;
5487}
5488#endif
5489
5490/*
5491 * define short names for the global vendor params
5492 * used by __wlan_hdd_cfg80211_monitor_rssi()
5493 */
5494#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
5495#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
5496#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
5497#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
5498#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
5499
5500/**
5501 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
5502 * @wiphy: Pointer to wireless phy
5503 * @wdev: Pointer to wireless device
5504 * @data: Pointer to data
5505 * @data_len: Data length
5506 *
5507 * Return: 0 on success, negative errno on failure
5508 */
5509static int
5510__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
5511 struct wireless_dev *wdev,
5512 const void *data,
5513 int data_len)
5514{
5515 struct net_device *dev = wdev->netdev;
5516 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5517 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5518 struct nlattr *tb[PARAM_MAX + 1];
5519 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305520 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005521 int ret;
5522 uint32_t control;
5523 static const struct nla_policy policy[PARAM_MAX + 1] = {
5524 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
5525 [PARAM_CONTROL] = { .type = NLA_U32 },
5526 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
5527 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
5528 };
5529
Jeff Johnson1f61b612016-02-12 16:28:33 -08005530 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005531
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05305532 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
5533 hdd_err("invalid session id: %d", adapter->sessionId);
5534 return -EINVAL;
5535 }
5536
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005537 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305538 if (ret)
5539 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005540
5541 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005542 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005543 return -ENOTSUPP;
5544 }
5545
5546 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005547 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005548 return -EINVAL;
5549 }
5550
5551 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005552 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005553 return -EINVAL;
5554 }
5555
5556 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005557 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005558 return -EINVAL;
5559 }
5560
5561 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5562 req.session_id = adapter->sessionId;
5563 control = nla_get_u32(tb[PARAM_CONTROL]);
5564
5565 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5566 req.control = true;
5567 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005568 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005569 return -EINVAL;
5570 }
5571
5572 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005573 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005574 return -EINVAL;
5575 }
5576
5577 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5578 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5579
5580 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005581 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005582 req.min_rssi, req.max_rssi);
5583 return -EINVAL;
5584 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005585 hdd_debug("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005586 req.min_rssi, req.max_rssi);
5587
5588 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5589 req.control = false;
5590 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005591 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005592 return -EINVAL;
5593 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005594 hdd_debug("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005595 req.request_id, req.session_id, req.control);
5596
5597 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305598 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005599 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005600 return -EINVAL;
5601 }
5602
5603 return 0;
5604}
5605
5606/*
5607 * done with short names for the global vendor params
5608 * used by __wlan_hdd_cfg80211_monitor_rssi()
5609 */
5610#undef PARAM_MAX
5611#undef PARAM_CONTROL
5612#undef PARAM_REQUEST_ID
5613#undef PARAM_MAX_RSSI
5614#undef PARAM_MIN_RSSI
5615
5616/**
5617 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5618 * @wiphy: wiphy structure pointer
5619 * @wdev: Wireless device structure pointer
5620 * @data: Pointer to the data received
5621 * @data_len: Length of @data
5622 *
5623 * Return: 0 on success; errno on failure
5624 */
5625static int
5626wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5627 const void *data, int data_len)
5628{
5629 int ret;
5630
5631 cds_ssr_protect(__func__);
5632 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5633 cds_ssr_unprotect(__func__);
5634
5635 return ret;
5636}
5637
5638/**
5639 * hdd_rssi_threshold_breached() - rssi breached NL event
5640 * @hddctx: HDD context
5641 * @data: rssi breached event data
5642 *
5643 * This function reads the rssi breached event %data and fill in the skb with
5644 * NL attributes and send up the NL event.
5645 *
5646 * Return: none
5647 */
5648void hdd_rssi_threshold_breached(void *hddctx,
5649 struct rssi_breach_event *data)
5650{
5651 hdd_context_t *hdd_ctx = hddctx;
5652 struct sk_buff *skb;
5653
5654 ENTER();
5655
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305656 if (wlan_hdd_validate_context(hdd_ctx))
5657 return;
5658 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005659 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005660 return;
5661 }
5662
5663 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5664 NULL,
5665 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5666 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5667 GFP_KERNEL);
5668
5669 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005670 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005671 return;
5672 }
5673
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005674 hdd_debug("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005675 data->request_id, data->curr_rssi);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08005676 hdd_debug("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005677 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5678
5679 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5680 data->request_id) ||
5681 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5682 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5683 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5684 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005685 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005686 goto fail;
5687 }
5688
5689 cfg80211_vendor_event(skb, GFP_KERNEL);
5690 return;
5691
5692fail:
5693 kfree_skb(skb);
5694 return;
5695}
5696
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305697static const struct nla_policy
5698ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5699 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5700};
5701
5702/**
5703 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5704 * @wiphy: Pointer to wireless phy
5705 * @wdev: Pointer to wireless device
5706 * @data: Pointer to data
5707 * @data_len: Length of @data
5708 *
5709 * Return: 0 on success, negative errno on failure
5710 */
5711static int
5712__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5713 struct wireless_dev *wdev,
5714 const void *data, int data_len)
5715{
5716 int status;
5717 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5718 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005719 struct net_device *dev = wdev->netdev;
5720 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305721
5722 ENTER_DEV(wdev->netdev);
5723
5724 status = wlan_hdd_validate_context(pHddCtx);
5725 if (0 != status)
5726 return status;
5727 if (!pHddCtx->config->fhostNSOffload) {
5728 hdd_err("ND Offload not supported");
5729 return -EINVAL;
5730 }
5731
5732 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5733 (struct nlattr *)data,
5734 data_len, ns_offload_set_policy)) {
5735 hdd_err("nla_parse failed");
5736 return -EINVAL;
5737 }
5738
5739 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5740 hdd_err("ND Offload flag attribute not present");
5741 return -EINVAL;
5742 }
5743
5744 pHddCtx->ns_offload_enable =
5745 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5746
Dustin Brownd8279d22016-09-07 14:52:57 -07005747 /* update ns offload in case it is already enabled/disabled */
Mukul Sharma3ba26b82017-01-12 21:59:41 +05305748 if (pHddCtx->ns_offload_enable)
5749 hdd_enable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
5750 else
5751 hdd_disable_ns_offload(adapter, pmo_ns_offload_dynamic_update);
Dustin Brownd8279d22016-09-07 14:52:57 -07005752
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305753 return 0;
5754}
5755
5756/**
5757 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5758 * @wiphy: pointer to wireless wiphy structure.
5759 * @wdev: pointer to wireless_dev structure.
5760 * @data: Pointer to the data to be passed via vendor interface
5761 * @data_len:Length of the data to be passed
5762 *
5763 * Return: Return the Success or Failure code.
5764 */
5765static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5766 struct wireless_dev *wdev,
5767 const void *data, int data_len)
5768{
5769 int ret;
5770
5771 cds_ssr_protect(__func__);
5772 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5773 cds_ssr_unprotect(__func__);
5774
5775 return ret;
5776}
5777
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005778/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5779 * @wiphy: Pointer to wireless phy
5780 * @wdev: Pointer to wireless device
5781 * @data: Pointer to data
5782 * @data_len: Data length
5783 *
5784 * This function return the preferred frequency list generated by the policy
5785 * manager.
5786 *
5787 * Return: success or failure code
5788 */
5789static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5790 struct wireless_dev
5791 *wdev, const void *data,
5792 int data_len)
5793{
5794 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5795 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305796 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305797 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005798 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305799 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005800 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005801 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5802 struct sk_buff *reply_skb;
5803
Jeff Johnson1f61b612016-02-12 16:28:33 -08005804 ENTER_DEV(wdev->netdev);
5805
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005806 ret = wlan_hdd_validate_context(hdd_ctx);
5807 if (ret)
5808 return -EINVAL;
5809
5810 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5811 data, data_len, NULL)) {
5812 hdd_err("Invalid ATTR");
5813 return -EINVAL;
5814 }
5815
5816 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5817 hdd_err("attr interface type failed");
5818 return -EINVAL;
5819 }
5820
5821 intf_mode = nla_get_u32(tb
5822 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5823
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005824 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005825 hdd_err("Invalid interface type");
5826 return -EINVAL;
5827 }
5828
5829 hdd_debug("Userspace requested pref freq list");
5830
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005831 status = policy_mgr_get_pcl(hdd_ctx->hdd_psoc,
5832 intf_mode, pcl, &pcl_len,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305833 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305834 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005835 hdd_err("Get pcl failed");
5836 return -EINVAL;
5837 }
5838
5839 /* convert channel number to frequency */
5840 for (i = 0; i < pcl_len; i++) {
5841 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5842 freq_list[i] =
5843 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005844 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005845 else
5846 freq_list[i] =
5847 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005848 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005849 }
5850
5851 /* send the freq_list back to supplicant */
5852 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5853 sizeof(u32) *
5854 pcl_len +
5855 NLMSG_HDRLEN);
5856
5857 if (!reply_skb) {
5858 hdd_err("Allocate reply_skb failed");
5859 return -EINVAL;
5860 }
5861
5862 if (nla_put_u32(reply_skb,
5863 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5864 intf_mode) ||
5865 nla_put(reply_skb,
5866 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5867 sizeof(uint32_t) * pcl_len,
5868 freq_list)) {
5869 hdd_err("nla put fail");
5870 kfree_skb(reply_skb);
5871 return -EINVAL;
5872 }
5873
5874 return cfg80211_vendor_cmd_reply(reply_skb);
5875}
5876
5877/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5878 * @wiphy: Pointer to wireless phy
5879 * @wdev: Pointer to wireless device
5880 * @data: Pointer to data
5881 * @data_len: Data length
5882 *
5883 * This function return the preferred frequency list generated by the policy
5884 * manager.
5885 *
5886 * Return: success or failure code
5887 */
5888static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5889 struct wireless_dev
5890 *wdev, const void *data,
5891 int data_len)
5892{
5893 int ret = 0;
5894
5895 cds_ssr_protect(__func__);
5896 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5897 data, data_len);
5898 cds_ssr_unprotect(__func__);
5899
5900 return ret;
5901}
5902
5903/**
5904 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5905 * @wiphy: Pointer to wireless phy
5906 * @wdev: Pointer to wireless device
5907 * @data: Pointer to data
5908 * @data_len: Data length
5909 *
5910 * Return: 0 on success, negative errno on failure
5911 */
5912static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5913 struct wireless_dev *wdev,
5914 const void *data,
5915 int data_len)
5916{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305917 struct net_device *ndev = wdev->netdev;
5918 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005919 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5920 int ret = 0;
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005921 enum policy_mgr_con_mode intf_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005922 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5923 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005924
Jeff Johnson1f61b612016-02-12 16:28:33 -08005925 ENTER_DEV(ndev);
5926
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005927 ret = wlan_hdd_validate_context(hdd_ctx);
5928 if (ret)
5929 return ret;
5930
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005931 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5932 data, data_len, NULL)) {
5933 hdd_err("Invalid ATTR");
5934 return -EINVAL;
5935 }
5936
5937 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5938 hdd_err("attr interface type failed");
5939 return -EINVAL;
5940 }
5941
5942 intf_mode = nla_get_u32(tb
5943 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5944
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005945 if (intf_mode < PM_STA_MODE || intf_mode >= PM_MAX_NUM_OF_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005946 hdd_err("Invalid interface type");
5947 return -EINVAL;
5948 }
5949
5950 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5951 hdd_err("attr probable freq failed");
5952 return -EINVAL;
5953 }
5954
5955 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5956 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5957
5958 /* check pcl table */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005959 if (!policy_mgr_allow_concurrency(hdd_ctx->hdd_psoc, intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005960 channel_hint, HW_MODE_20_MHZ)) {
5961 hdd_err("Set channel hint failed due to concurrency check");
5962 return -EINVAL;
5963 }
5964
Krunal Soni09e55032016-06-07 10:06:55 -07005965 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5966 hdd_warn("Remain On Channel Pending");
5967
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005968 ret = policy_mgr_reset_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07005969 if (!QDF_IS_STATUS_SUCCESS(ret))
5970 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005971
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005972 ret = policy_mgr_current_connections_update(hdd_ctx->hdd_psoc,
5973 adapter->sessionId, channel_hint,
Krunal Soni3091bcc2016-06-23 12:28:21 -07005974 SIR_UPDATE_REASON_SET_OPER_CHAN);
5975 if (QDF_STATUS_E_FAILURE == ret) {
5976 /* return in the failure case */
5977 hdd_err("ERROR: connections update failed!!");
5978 return -EINVAL;
5979 }
5980
5981 if (QDF_STATUS_SUCCESS == ret) {
5982 /*
5983 * Success is the only case for which we expect hw mode
5984 * change to take place, hence we need to wait.
5985 * For any other return value it should be a pass
5986 * through
5987 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08005988 ret = policy_mgr_wait_for_connection_update(hdd_ctx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -07005989 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5990 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005991 return -EINVAL;
5992 }
5993
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005994 }
5995
5996 return 0;
5997}
5998
5999/**
6000 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
6001 * @wiphy: Pointer to wireless phy
6002 * @wdev: Pointer to wireless device
6003 * @data: Pointer to data
6004 * @data_len: Data length
6005 *
6006 * Return: 0 on success, negative errno on failure
6007 */
6008static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
6009 struct wireless_dev *wdev,
6010 const void *data,
6011 int data_len)
6012{
6013 int ret = 0;
6014
6015 cds_ssr_protect(__func__);
6016 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
6017 data, data_len);
6018 cds_ssr_unprotect(__func__);
6019
6020 return ret;
6021}
6022
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306023static const struct
6024nla_policy
6025qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
6026 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
6027};
6028
6029/**
6030 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
6031 * @wiphy: WIPHY structure pointer
6032 * @wdev: Wireless device structure pointer
6033 * @data: Pointer to the data received
6034 * @data_len: Length of the data received
6035 *
6036 * This function is used to get link properties like nss, rate flags and
6037 * operating frequency for the active connection with the given peer.
6038 *
6039 * Return: 0 on success and errno on failure
6040 */
6041static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6042 struct wireless_dev *wdev,
6043 const void *data,
6044 int data_len)
6045{
6046 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6047 struct net_device *dev = wdev->netdev;
6048 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6049 hdd_station_ctx_t *hdd_sta_ctx;
6050 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05306051 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306052 uint32_t sta_id;
6053 struct sk_buff *reply_skb;
6054 uint32_t rate_flags = 0;
6055 uint8_t nss;
6056 uint8_t final_rate_flags = 0;
6057 uint32_t freq;
6058
Jeff Johnson1f61b612016-02-12 16:28:33 -08006059 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306060
Anurag Chouhan6d760662016-02-20 16:05:43 +05306061 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306062 hdd_err("Command not allowed in FTM mode");
6063 return -EPERM;
6064 }
6065
6066 if (0 != wlan_hdd_validate_context(hdd_ctx))
6067 return -EINVAL;
6068
6069 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
6070 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006071 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306072 return -EINVAL;
6073 }
6074
6075 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006076 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306077 adapter->device_mode);
6078 return -EINVAL;
6079 }
6080
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306081 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05306082 QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006083 hdd_debug("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306084 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
6085
Krunal Sonib4326f22016-03-10 13:05:51 -08006086 if (adapter->device_mode == QDF_STA_MODE ||
6087 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306088 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
6089 if ((hdd_sta_ctx->conn_info.connState !=
6090 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306091 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306092 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006093 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306094 MAC_ADDR_ARRAY(peer_mac));
6095 return -EINVAL;
6096 }
6097
6098 nss = hdd_sta_ctx->conn_info.nss;
6099 freq = cds_chan_to_freq(
6100 hdd_sta_ctx->conn_info.operationChannel);
6101 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08006102 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
6103 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306104
6105 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
6106 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05306107 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306108 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05306109 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306110 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05306111 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306112 break;
6113 }
6114
6115 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07006116 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306117 MAC_ADDR_ARRAY(peer_mac));
6118 return -EINVAL;
6119 }
6120
6121 nss = adapter->aStaInfo[sta_id].nss;
6122 freq = cds_chan_to_freq(
6123 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
6124 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
6125 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07006126 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306127 MAC_ADDR_ARRAY(peer_mac));
6128 return -EINVAL;
6129 }
6130
6131 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
6132 if (rate_flags & eHAL_TX_RATE_VHT80) {
6133 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006134#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306135 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006136#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306137 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
6138 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006139#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306140 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006141#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306142 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
6143 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
6144 } else if (rate_flags &
6145 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
6146 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006147#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306148 if (rate_flags & eHAL_TX_RATE_HT40)
6149 final_rate_flags |=
6150 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08006151#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306152 }
6153
6154 if (rate_flags & eHAL_TX_RATE_SGI) {
6155 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
6156 final_rate_flags |= RATE_INFO_FLAGS_MCS;
6157 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
6158 }
6159 }
6160
6161 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
6162 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
6163
6164 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006165 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306166 return -EINVAL;
6167 }
6168
6169 if (nla_put_u8(reply_skb,
6170 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
6171 nss) ||
6172 nla_put_u8(reply_skb,
6173 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
6174 final_rate_flags) ||
6175 nla_put_u32(reply_skb,
6176 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
6177 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006178 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05306179 kfree_skb(reply_skb);
6180 return -EINVAL;
6181 }
6182
6183 return cfg80211_vendor_cmd_reply(reply_skb);
6184}
6185
6186/**
6187 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
6188 * properties.
6189 * @wiphy: WIPHY structure pointer
6190 * @wdev: Wireless device structure pointer
6191 * @data: Pointer to the data received
6192 * @data_len: Length of the data received
6193 *
6194 * This function is used to get link properties like nss, rate flags and
6195 * operating frequency for the active connection with the given peer.
6196 *
6197 * Return: 0 on success and errno on failure
6198 */
6199static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
6200 struct wireless_dev *wdev,
6201 const void *data,
6202 int data_len)
6203{
6204 int ret = 0;
6205
6206 cds_ssr_protect(__func__);
6207 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
6208 wdev, data, data_len);
6209 cds_ssr_unprotect(__func__);
6210
6211 return ret;
6212}
6213
Peng Xu278d0122015-09-24 16:34:17 -07006214static const struct
6215nla_policy
6216qca_wlan_vendor_ota_test_policy
6217[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
6218 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
6219};
6220
6221/**
6222 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
6223 * @wiphy: Pointer to wireless phy
6224 * @wdev: Pointer to wireless device
6225 * @data: Pointer to data
6226 * @data_len: Data length
6227 *
6228 * Return: 0 on success, negative errno on failure
6229 */
6230static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6231 struct wireless_dev *wdev,
6232 const void *data,
6233 int data_len)
6234{
6235 struct net_device *dev = wdev->netdev;
6236 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6237 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
6238 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6239 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
6240 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306241 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07006242 uint32_t current_roam_state;
6243
Jeff Johnson1f61b612016-02-12 16:28:33 -08006244 ENTER_DEV(dev);
6245
Anurag Chouhan6d760662016-02-20 16:05:43 +05306246 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07006247 hdd_err("Command not allowed in FTM mode");
6248 return -EPERM;
6249 }
6250
6251 if (0 != wlan_hdd_validate_context(hdd_ctx))
6252 return -EINVAL;
6253
6254 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
6255 data, data_len,
6256 qca_wlan_vendor_ota_test_policy)) {
6257 hdd_err("invalid attr");
6258 return -EINVAL;
6259 }
6260
6261 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
6262 hdd_err("attr ota test failed");
6263 return -EINVAL;
6264 }
6265
6266 ota_enable = nla_get_u8(
6267 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
6268
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006269 hdd_debug(" OTA test enable = %d", ota_enable);
Peng Xu278d0122015-09-24 16:34:17 -07006270 if (ota_enable != 1) {
6271 hdd_err("Invalid value, only enable test mode is supported!");
6272 return -EINVAL;
6273 }
6274
6275 current_roam_state =
6276 sme_get_current_roam_state(hal, adapter->sessionId);
6277 status = sme_stop_roaming(hal, adapter->sessionId,
6278 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306279 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006280 hdd_err("Enable/Disable roaming failed");
6281 return -EINVAL;
6282 }
6283
6284 status = sme_ps_enable_disable(hal, adapter->sessionId,
6285 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306286 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07006287 hdd_err("Enable/Disable power save failed");
6288 /* restore previous roaming setting */
6289 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
6290 current_roam_state == eCSR_ROAMING_STATE_JOINED)
6291 status = sme_start_roaming(hal, adapter->sessionId,
6292 eCsrHddIssued);
6293 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
6294 current_roam_state == eCSR_ROAMING_STATE_IDLE)
6295 status = sme_stop_roaming(hal, adapter->sessionId,
6296 eCsrHddIssued);
6297
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05306298 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07006299 hdd_err("Restoring roaming state failed");
6300
6301 return -EINVAL;
6302 }
6303
6304
6305 return 0;
6306}
6307
6308/**
6309 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
6310 * @wiphy: Pointer to wireless phy
6311 * @wdev: Pointer to wireless device
6312 * @data: Pointer to data
6313 * @data_len: Data length
6314 *
6315 * Return: 0 on success, negative errno on failure
6316 */
6317static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
6318 struct wireless_dev *wdev,
6319 const void *data,
6320 int data_len)
6321{
6322 int ret = 0;
6323
6324 cds_ssr_protect(__func__);
6325 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
6326 cds_ssr_unprotect(__func__);
6327
6328 return ret;
6329}
6330
Peng Xu4d67c8f2015-10-16 16:02:26 -07006331/**
6332 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6333 * @wiphy: Pointer to wireless phy
6334 * @wdev: Pointer to wireless device
6335 * @data: Pointer to data
6336 * @data_len: Data length
6337 *
6338 * Return: 0 on success, negative errno on failure
6339 */
6340static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6341 struct wireless_dev *wdev,
6342 const void *data,
6343 int data_len)
6344{
6345 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6346 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006347 hdd_adapter_t *adapter;
6348 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006349 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
6350 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006351 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006352
Jeff Johnson1f61b612016-02-12 16:28:33 -08006353 ENTER_DEV(dev);
6354
Peng Xu4d67c8f2015-10-16 16:02:26 -07006355 ret = wlan_hdd_validate_context(hdd_ctx);
6356 if (ret)
6357 return ret;
6358
6359 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6360
6361 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
6362 data, data_len, NULL)) {
6363 hdd_err("Invalid ATTR");
6364 return -EINVAL;
6365 }
6366
6367 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
6368 hdd_err("attr tx power scale failed");
6369 return -EINVAL;
6370 }
6371
6372 scale_value = nla_get_u8(tb
6373 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
6374
6375 if (scale_value > MAX_TXPOWER_SCALE) {
6376 hdd_err("Invalid tx power scale level");
6377 return -EINVAL;
6378 }
6379
Peng Xu62c8c432016-05-09 15:23:02 -07006380 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006381
Peng Xu62c8c432016-05-09 15:23:02 -07006382 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006383 hdd_err("Set tx power scale failed");
6384 return -EINVAL;
6385 }
6386
6387 return 0;
6388}
6389
6390/**
6391 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
6392 * @wiphy: Pointer to wireless phy
6393 * @wdev: Pointer to wireless device
6394 * @data: Pointer to data
6395 * @data_len: Data length
6396 *
6397 * Return: 0 on success, negative errno on failure
6398 */
6399static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
6400 struct wireless_dev *wdev,
6401 const void *data,
6402 int data_len)
6403{
Peng Xu62c8c432016-05-09 15:23:02 -07006404 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006405
6406 cds_ssr_protect(__func__);
6407 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
6408 data, data_len);
6409 cds_ssr_unprotect(__func__);
6410
6411 return ret;
6412}
6413
6414/**
6415 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6416 * @wiphy: Pointer to wireless phy
6417 * @wdev: Pointer to wireless device
6418 * @data: Pointer to data
6419 * @data_len: Data length
6420 *
6421 * Return: 0 on success, negative errno on failure
6422 */
6423static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6424 struct wireless_dev *wdev,
6425 const void *data,
6426 int data_len)
6427{
6428 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6429 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07006430 hdd_adapter_t *adapter;
6431 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006432 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
6433 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07006434 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006435
Jeff Johnson1f61b612016-02-12 16:28:33 -08006436 ENTER_DEV(dev);
6437
Peng Xu4d67c8f2015-10-16 16:02:26 -07006438 ret = wlan_hdd_validate_context(hdd_ctx);
6439 if (ret)
6440 return ret;
6441
6442 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6443
6444 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
6445 data, data_len, NULL)) {
6446 hdd_err("Invalid ATTR");
6447 return -EINVAL;
6448 }
6449
6450 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
6451 hdd_err("attr tx power decrease db value failed");
6452 return -EINVAL;
6453 }
6454
6455 scale_value = nla_get_u8(tb
6456 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
6457
Peng Xu62c8c432016-05-09 15:23:02 -07006458 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
6459 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07006460
Peng Xu62c8c432016-05-09 15:23:02 -07006461 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07006462 hdd_err("Set tx power decrease db failed");
6463 return -EINVAL;
6464 }
6465
6466 return 0;
6467}
6468
6469/**
6470 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
6471 * @wiphy: Pointer to wireless phy
6472 * @wdev: Pointer to wireless device
6473 * @data: Pointer to data
6474 * @data_len: Data length
6475 *
6476 * Return: 0 on success, negative errno on failure
6477 */
6478static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
6479 struct wireless_dev *wdev,
6480 const void *data,
6481 int data_len)
6482{
Peng Xu62c8c432016-05-09 15:23:02 -07006483 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07006484
6485 cds_ssr_protect(__func__);
6486 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
6487 data, data_len);
6488 cds_ssr_unprotect(__func__);
6489
6490 return ret;
6491}
Peng Xu8fdaa492016-06-22 10:20:47 -07006492
6493/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306494 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
6495 * @wiphy: Pointer to wireless phy
6496 * @wdev: Pointer to wireless device
6497 * @data: Pointer to data
6498 * @data_len: Data length
6499 *
6500 * Processes the conditional channel switch request and invokes the helper
6501 * APIs to process the channel switch request.
6502 *
6503 * Return: 0 on success, negative errno on failure
6504 */
6505static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6506 struct wireless_dev *wdev,
6507 const void *data,
6508 int data_len)
6509{
6510 int ret;
6511 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6512 struct net_device *dev = wdev->netdev;
6513 hdd_adapter_t *adapter;
6514 struct nlattr
6515 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
6516 uint32_t freq_len, i;
6517 uint32_t *freq;
6518 uint8_t chans[QDF_MAX_NUM_CHAN];
6519
6520 ENTER_DEV(dev);
6521
6522 ret = wlan_hdd_validate_context(hdd_ctx);
6523 if (ret)
6524 return ret;
6525
6526 if (!hdd_ctx->config->enableDFSMasterCap) {
6527 hdd_err("DFS master capability is not present in the driver");
6528 return -EINVAL;
6529 }
6530
6531 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6532 hdd_err("Command not allowed in FTM mode");
6533 return -EPERM;
6534 }
6535
6536 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6537 if (adapter->device_mode != QDF_SAP_MODE) {
6538 hdd_err("Invalid device mode %d", adapter->device_mode);
6539 return -EINVAL;
6540 }
6541
6542 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6543 data, data_len, NULL)) {
6544 hdd_err("Invalid ATTR");
6545 return -EINVAL;
6546 }
6547
6548 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6549 hdd_err("Frequency list is missing");
6550 return -EINVAL;
6551 }
6552
6553 freq_len = nla_len(
6554 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6555 sizeof(uint32_t);
6556
6557 if (freq_len > QDF_MAX_NUM_CHAN) {
6558 hdd_err("insufficient space to hold channels");
6559 return -ENOMEM;
6560 }
6561
6562 hdd_debug("freq_len=%d", freq_len);
6563
6564 freq = nla_data(
6565 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6566
6567
6568 for (i = 0; i < freq_len; i++) {
6569 if (freq[i] == 0)
6570 chans[i] = 0;
6571 else
6572 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6573
6574 hdd_debug("freq[%d]=%d", i, freq[i]);
6575 }
6576
6577 /*
6578 * The input frequency list from user space is designed to be a
6579 * priority based frequency list. This is only to accommodate any
6580 * future request. But, current requirement is only to perform CAC
6581 * on a single channel. So, the first entry from the list is picked.
6582 *
6583 * If channel is zero, any channel in the available outdoor regulatory
6584 * domain will be selected.
6585 */
6586 ret = wlan_hdd_request_pre_cac(chans[0]);
6587 if (ret) {
6588 hdd_err("pre cac request failed with reason:%d", ret);
6589 return ret;
6590 }
6591
6592 return 0;
6593}
6594
6595/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006596 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6597 * @wiphy: Pointer to wireless phy
6598 * @wdev: Pointer to wireless device
6599 * @data: Pointer to data
6600 * @data_len: Data length
6601 *
6602 * This function is to process the p2p listen offload start vendor
6603 * command. It parses the input parameters and invoke WMA API to
6604 * send the command to firmware.
6605 *
6606 * Return: 0 on success, negative errno on failure
6607 */
6608static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6609 struct wireless_dev *wdev,
6610 const void *data,
6611 int data_len)
6612{
6613 int ret;
6614 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6615 struct net_device *dev = wdev->netdev;
6616 hdd_adapter_t *adapter;
6617 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6618 struct sir_p2p_lo_start params;
Peng Xu8fdaa492016-06-22 10:20:47 -07006619
6620 ENTER_DEV(dev);
6621
6622 ret = wlan_hdd_validate_context(hdd_ctx);
6623 if (ret)
6624 return ret;
6625
6626 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6627 hdd_err("Command not allowed in FTM mode");
6628 return -EPERM;
6629 }
6630
6631 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6632 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6633 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6634 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6635 hdd_err("Invalid device mode %d", adapter->device_mode);
6636 return -EINVAL;
6637 }
6638
6639 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6640 data, data_len, NULL)) {
6641 hdd_err("Invalid ATTR");
6642 return -EINVAL;
6643 }
6644
6645 memset(&params, 0, sizeof(params));
6646
6647 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6648 params.ctl_flags = 1; /* set to default value */
6649 else
6650 params.ctl_flags = nla_get_u32(tb
6651 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6652
6653 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6654 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6655 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6656 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6657 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6658 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6659 hdd_err("Attribute parsing failed");
6660 return -EINVAL;
6661 }
6662
6663 params.vdev_id = adapter->sessionId;
6664 params.freq = nla_get_u32(tb
6665 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6666 if ((params.freq != 2412) && (params.freq != 2437) &&
6667 (params.freq != 2462)) {
6668 hdd_err("Invalid listening channel: %d", params.freq);
6669 return -EINVAL;
6670 }
6671
6672 params.period = nla_get_u32(tb
6673 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6674 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6675 hdd_err("Invalid period: %d", params.period);
6676 return -EINVAL;
6677 }
6678
6679 params.interval = nla_get_u32(tb
6680 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6681 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6682 hdd_err("Invalid interval: %d", params.interval);
6683 return -EINVAL;
6684 }
6685
6686 params.count = nla_get_u32(tb
6687 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
Peng Xu6d578ef2017-01-10 06:22:21 -08006688 if (!((params.count >= 0) && (params.count < UINT_MAX))) {
Peng Xu8fdaa492016-06-22 10:20:47 -07006689 hdd_err("Invalid count: %d", params.count);
6690 return -EINVAL;
6691 }
6692
6693 params.device_types = nla_data(tb
6694 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6695 if (params.device_types == NULL) {
6696 hdd_err("Invalid device types");
6697 return -EINVAL;
6698 }
6699
6700 params.dev_types_len = nla_len(tb
6701 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6702 if (params.dev_types_len < 8) {
6703 hdd_err("Invalid device type length: %d", params.dev_types_len);
6704 return -EINVAL;
6705 }
6706
6707 params.probe_resp_tmplt = nla_data(tb
6708 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6709 if (params.probe_resp_tmplt == NULL) {
6710 hdd_err("Invalid probe response template");
6711 return -EINVAL;
6712 }
6713
6714 params.probe_resp_len = nla_len(tb
6715 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6716 if (params.probe_resp_len == 0) {
6717 hdd_err("Invalid probe resp template length: %d",
6718 params.probe_resp_len);
6719 return -EINVAL;
6720 }
6721
6722 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6723 params.freq, params.period, params.interval, params.count);
6724
Wu Gao9a704f42017-03-10 18:42:11 +08006725 return wlan_hdd_listen_offload_start(adapter, &params);
Peng Xu8fdaa492016-06-22 10:20:47 -07006726}
6727
6728
6729/**
6730 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6731 * @wiphy: Pointer to wireless phy
6732 * @wdev: Pointer to wireless device
6733 * @data: Pointer to data
6734 * @data_len: Data length
6735 *
6736 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6737 * to process p2p listen offload start vendor command.
6738 *
6739 * Return: 0 on success, negative errno on failure
6740 */
6741static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6742 struct wireless_dev *wdev,
6743 const void *data,
6744 int data_len)
6745{
6746 int ret = 0;
6747
6748 cds_ssr_protect(__func__);
6749 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6750 data, data_len);
6751 cds_ssr_unprotect(__func__);
6752
6753 return ret;
6754}
6755
6756/**
6757 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6758 * @wiphy: Pointer to wireless phy
6759 * @wdev: Pointer to wireless device
6760 * @data: Pointer to data
6761 * @data_len: Data length
6762 *
6763 * This function is to process the p2p listen offload stop vendor
6764 * command. It invokes WMA API to send command to firmware.
6765 *
6766 * Return: 0 on success, negative errno on failure
6767 */
6768static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6769 struct wireless_dev *wdev,
6770 const void *data,
6771 int data_len)
6772{
Peng Xu8fdaa492016-06-22 10:20:47 -07006773 hdd_adapter_t *adapter;
6774 struct net_device *dev = wdev->netdev;
6775
6776 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6777 hdd_err("Command not allowed in FTM mode");
6778 return -EPERM;
6779 }
6780
6781 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6782 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6783 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6784 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6785 hdd_err("Invalid device mode");
6786 return -EINVAL;
6787 }
6788
Wu Gao9a704f42017-03-10 18:42:11 +08006789 return wlan_hdd_listen_offload_stop(adapter);
Peng Xu8fdaa492016-06-22 10:20:47 -07006790}
6791
6792/**
6793 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6794 * @wiphy: Pointer to wireless phy
6795 * @wdev: Pointer to wireless device
6796 * @data: Pointer to data
6797 * @data_len: Data length
6798 *
6799 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6800 * to process p2p listen offload stop vendor command.
6801 *
6802 * Return: 0 on success, negative errno on failure
6803 */
6804static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6805 struct wireless_dev *wdev,
6806 const void *data,
6807 int data_len)
6808{
6809 int ret = 0;
6810
6811 cds_ssr_protect(__func__);
6812 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6813 data, data_len);
6814 cds_ssr_unprotect(__func__);
6815
6816 return ret;
6817}
6818
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306819/**
6820 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6821 * @wiphy: Pointer to wireless phy
6822 * @wdev: Pointer to wireless device
6823 * @data: Pointer to data
6824 * @data_len: Data length
6825 *
6826 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6827 * to process the conditional channel switch request.
6828 *
6829 * Return: 0 on success, negative errno on failure
6830 */
6831static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6832 struct wireless_dev *wdev,
6833 const void *data,
6834 int data_len)
6835{
6836 int ret;
6837
6838 cds_ssr_protect(__func__);
6839 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6840 data, data_len);
6841 cds_ssr_unprotect(__func__);
6842
6843 return ret;
6844}
6845
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306846/*
6847 * define short names for the global vendor params
6848 * used by __wlan_hdd_cfg80211_bpf_offload()
6849 */
6850#define BPF_INVALID \
6851 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6852#define BPF_SET_RESET \
6853 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6854#define BPF_VERSION \
6855 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6856#define BPF_FILTER_ID \
6857 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6858#define BPF_PACKET_SIZE \
6859 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6860#define BPF_CURRENT_OFFSET \
6861 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6862#define BPF_PROGRAM \
6863 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6864#define BPF_MAX \
6865 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006866
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306867static const struct nla_policy
6868wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6869 [BPF_SET_RESET] = {.type = NLA_U32},
6870 [BPF_VERSION] = {.type = NLA_U32},
6871 [BPF_FILTER_ID] = {.type = NLA_U32},
6872 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6873 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6874 [BPF_PROGRAM] = {.type = NLA_U8},
6875};
6876
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006877struct bpf_offload_priv {
6878 struct sir_bpf_get_offload bpf_get_offload;
6879};
6880
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306881/**
6882 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006883 * @context: opaque context originally passed to SME. HDD always passes
6884 * a cookie for the request context
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306885 * @bpf_get_offload: struct for get offload
6886 *
6887 * This function receives the response/data from the lower layer and
6888 * checks to see if the thread is still waiting then post the results to
6889 * upper layer, if the request has timed out then ignore.
6890 *
6891 * Return: None
6892 */
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006893static void hdd_get_bpf_offload_cb(void *context,
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006894 struct sir_bpf_get_offload *data)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306895{
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006896 struct hdd_request *request;
6897 struct bpf_offload_priv *priv;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306898
6899 ENTER();
6900
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006901 request = hdd_request_get(context);
6902 if (!request) {
6903 hdd_err("Obsolete request");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306904 return;
6905 }
6906
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006907 priv = hdd_request_priv(request);
6908 priv->bpf_get_offload = *data;
6909 hdd_request_complete(request);
6910 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306911}
6912
6913/**
6914 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6915 * @hdd_context: hdd_context
6916 * @bpf_get_offload: struct for get offload
6917 *
6918 * Return: 0 on success, error number otherwise.
6919 */
6920static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6921 struct sir_bpf_get_offload *bpf_get_offload)
6922{
6923 struct sk_buff *skb;
6924 uint32_t nl_buf_len;
6925
6926 ENTER();
6927
6928 nl_buf_len = NLMSG_HDRLEN;
6929 nl_buf_len +=
6930 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6931 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6932
6933 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6934 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006935 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306936 return -ENOMEM;
6937 }
6938
Srinivas Girigowda13d39252017-03-06 16:12:15 -08006939 hdd_debug("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306940 bpf_get_offload->bpf_version,
6941 bpf_get_offload->max_bytes_for_bpf_inst);
6942
6943 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6944 bpf_get_offload->max_bytes_for_bpf_inst) ||
6945 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006946 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306947 goto nla_put_failure;
6948 }
6949
6950 cfg80211_vendor_cmd_reply(skb);
6951 EXIT();
6952 return 0;
6953
6954nla_put_failure:
6955 kfree_skb(skb);
6956 return -EINVAL;
6957}
6958
6959/**
6960 * hdd_get_bpf_offload - Get BPF offload Capabilities
6961 * @hdd_ctx: Hdd context
6962 *
6963 * Return: 0 on success, errno on failure
6964 */
6965static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6966{
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306967 QDF_STATUS status;
6968 int ret;
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006969 void *cookie;
6970 struct hdd_request *request;
6971 struct bpf_offload_priv *priv;
6972 static const struct hdd_request_params params = {
6973 .priv_size = sizeof(*priv),
6974 .timeout_ms = WLAN_WAIT_TIME_BPF,
6975 };
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306976
6977 ENTER();
6978
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006979 request = hdd_request_alloc(&params);
6980 if (!request) {
6981 hdd_err("Unable to allocate request");
6982 return -EINVAL;
6983 }
6984 cookie = hdd_request_cookie(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306985
Jeff Johnsona867e0c2017-01-26 13:43:51 -08006986 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal,
6987 hdd_get_bpf_offload_cb,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006988 cookie);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306989 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006990 hdd_err("Unable to retrieve BPF caps");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006991 ret = qdf_status_to_os_return(status);
6992 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306993 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006994 ret = hdd_request_wait_for_response(request);
6995 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07006996 hdd_err("Target response timed out");
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006997 goto cleanup;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306998 }
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08006999 priv = hdd_request_priv(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307000 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007001 &priv->bpf_get_offload);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307002 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07007003 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307004
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007005cleanup:
7006 /*
7007 * either we never sent a request to SME, we sent a request to
7008 * SME and timed out, or we sent a request to SME, received a
7009 * response from SME, and posted the response to userspace.
7010 * regardless we are done with the request.
7011 */
7012 hdd_request_put(request);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307013 EXIT();
Jeff Johnsoncd113fc2017-01-26 14:42:44 -08007014
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307015 return ret;
7016}
7017
7018/**
7019 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
7020 * @hdd_ctx: Hdd context
7021 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307022 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307023 *
7024 * Return: 0 on success; errno on failure
7025 */
7026static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
7027 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307028 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307029{
7030 struct sir_bpf_set_offload *bpf_set_offload;
7031 QDF_STATUS status;
7032 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05307033 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307034
7035 ENTER();
7036
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307037 if (adapter->device_mode == QDF_STA_MODE ||
7038 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
7039 if (!hdd_conn_is_connected(
7040 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
7041 hdd_err("Not in Connected state!");
7042 return -ENOTSUPP;
7043 }
7044 }
7045
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307046 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
7047 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07007048 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307049 return -ENOMEM;
7050 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307051
7052 /* Parse and fetch bpf packet size */
7053 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007054 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307055 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307056 goto fail;
7057 }
7058 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
7059
7060 if (!bpf_set_offload->total_length) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007061 hdd_debug("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307062 goto post_sme;
7063 }
7064
7065 /* Parse and fetch bpf program */
7066 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007067 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307068 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307069 goto fail;
7070 }
7071
7072 prog_len = nla_len(tb[BPF_PROGRAM]);
7073 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05307074
7075 if (bpf_set_offload->program == NULL) {
7076 hdd_err("qdf_mem_malloc failed for bpf offload program");
7077 ret = -ENOMEM;
7078 goto fail;
7079 }
7080
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307081 bpf_set_offload->current_length = prog_len;
7082 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307083 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307084
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007085 hdd_debug("BPF set instructions");
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05307086 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
7087 bpf_set_offload->program, prog_len);
7088
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307089 /* Parse and fetch filter Id */
7090 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007091 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307092 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307093 goto fail;
7094 }
7095 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
7096
7097 /* Parse and fetch current offset */
7098 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007099 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05307100 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307101 goto fail;
7102 }
7103 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
7104
7105post_sme:
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007106 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 +05307107 bpf_set_offload->session_id,
7108 bpf_set_offload->version,
7109 bpf_set_offload->filter_id,
7110 bpf_set_offload->total_length,
7111 bpf_set_offload->current_length,
7112 bpf_set_offload->current_offset);
7113
7114 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
7115 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007116 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05307117 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307118 goto fail;
7119 }
7120 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307121
7122fail:
7123 if (bpf_set_offload->current_length)
7124 qdf_mem_free(bpf_set_offload->program);
7125 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05307126 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307127}
7128
7129/**
7130 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
7131 * @wiphy: wiphy structure pointer
7132 * @wdev: Wireless device structure pointer
7133 * @data: Pointer to the data received
7134 * @data_len: Length of @data
7135 *
7136 * Return: 0 on success; errno on failure
7137 */
7138static int
7139__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7140 struct wireless_dev *wdev,
7141 const void *data, int data_len)
7142{
7143 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7144 struct net_device *dev = wdev->netdev;
7145 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
7146 struct nlattr *tb[BPF_MAX + 1];
7147 int ret_val, packet_filter_subcmd;
7148
7149 ENTER();
7150
7151 ret_val = wlan_hdd_validate_context(hdd_ctx);
7152 if (ret_val)
7153 return ret_val;
7154
7155 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007156 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307157 return -EINVAL;
7158 }
7159
7160 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07007161 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307162 return -ENOTSUPP;
7163 }
7164
7165 if (nla_parse(tb, BPF_MAX, data, data_len,
7166 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007167 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307168 return -EINVAL;
7169 }
7170
7171 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07007172 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307173 return -EINVAL;
7174 }
7175
7176 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
7177
7178 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
7179 return hdd_get_bpf_offload(hdd_ctx);
7180 else
7181 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05307182 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307183}
7184
7185/**
7186 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
7187 * @wiphy: wiphy structure pointer
7188 * @wdev: Wireless device structure pointer
7189 * @data: Pointer to the data received
7190 * @data_len: Length of @data
7191 *
7192 * Return: 0 on success; errno on failure
7193 */
7194
7195static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
7196 struct wireless_dev *wdev,
7197 const void *data, int data_len)
7198{
7199 int ret;
7200
7201 cds_ssr_protect(__func__);
7202 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
7203 cds_ssr_unprotect(__func__);
7204
7205 return ret;
7206}
7207
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307208/**
7209 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
7210 * @pre_cac_adapter: AP adapter used for pre cac
7211 * @status: Status (true or false)
7212 * @handle: Global handle
7213 *
7214 * Sets the status of pre cac i.e., whether the pre cac is active or not
7215 *
7216 * Return: Zero on success, non-zero on failure
7217 */
7218static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
7219 bool status, tHalHandle handle)
7220{
7221 QDF_STATUS ret;
7222
7223 ret = wlan_sap_set_pre_cac_status(
7224 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
7225 if (QDF_IS_STATUS_ERROR(ret))
7226 return -EINVAL;
7227
7228 return 0;
7229}
7230
7231/**
7232 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
7233 * @ap_adapter: AP adapter
7234 * @chan_before_pre_cac: Channel
7235 *
7236 * Saves the channel which the AP was beaconing on before moving to the pre
7237 * cac channel. If radar is detected on the pre cac channel, this saved
7238 * channel will be used for AP operations.
7239 *
7240 * Return: Zero on success, non-zero on failure
7241 */
7242static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
7243 uint8_t chan_before_pre_cac)
7244{
7245 QDF_STATUS ret;
7246
7247 ret = wlan_sap_set_chan_before_pre_cac(
7248 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
7249 if (QDF_IS_STATUS_ERROR(ret))
7250 return -EINVAL;
7251
7252 return 0;
7253}
7254
7255/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307256 * wlan_hdd_get_chanlist_without_nol() - This API removes the channels which
7257 * are in nol list from provided channel list
7258 * @adapter: AP adapter
7259 * @channel_count: channel count
7260 * @channel_list: channel list
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307261 *
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307262 * Return: None
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307263 */
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307264static void wlan_hdd_get_chanlist_without_nol(hdd_adapter_t *adapter,
7265 uint32_t *channel_count,
7266 uint8_t *channel_list)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307267{
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307268 uint8_t i, j;
7269 uint32_t nol_len = 0;
7270 uint8_t nol[QDF_MAX_NUM_CHAN] = {0};
7271 uint8_t tmp_chan_list[QDF_MAX_NUM_CHAN] = {0};
7272 uint32_t chan_count;
7273 bool found;
7274 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307275
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307276 if (!hdd_ctx) {
7277 hdd_err("hdd ctx not found");
7278 *channel_count = 0;
7279 return;
7280 }
7281
7282 if ((*channel_count == 0) || (*channel_count > QDF_MAX_NUM_CHAN)) {
7283 hdd_err("invalid channel count %d", *channel_count);
7284 return;
7285 }
7286
7287 wlan_hdd_sap_get_nol(adapter, nol, &nol_len);
7288 if (nol_len == 0)
7289 return;
7290
7291 qdf_mem_copy(tmp_chan_list, channel_list, *channel_count);
7292 chan_count = *channel_count;
7293 qdf_mem_zero(channel_list, chan_count);
7294 *channel_count = 0;
7295
7296 for (i = 0 ; i < chan_count; i++) {
7297 if ((hdd_ctx->config->force_sap_acs_st_ch > tmp_chan_list[i]) ||
7298 (hdd_ctx->config->force_sap_acs_end_ch < tmp_chan_list[i]))
7299 continue;
7300 found = false;
7301 for (j = 0; j < nol_len; j++) {
7302 if (tmp_chan_list[i] == nol[j]) {
7303 found = true;
7304 hdd_notice("skipped channel %d due to nol",
7305 nol[j]);
7306 break;
7307 }
7308 }
7309 if (!found) {
7310 channel_list[*channel_count] = tmp_chan_list[i];
7311 *channel_count = *channel_count + 1;
7312 }
7313 }
7314}
7315
7316int wlan_hdd_sap_get_valid_channellist(hdd_adapter_t *adapter,
7317 uint32_t *channel_count,
7318 uint8_t *channel_list)
7319{
7320 tsap_Config_t *sap_config;
7321
7322 sap_config = &adapter->sessionCtx.ap.sapConfig;
7323
7324 qdf_mem_copy(channel_list, sap_config->acs_cfg.ch_list,
7325 sap_config->acs_cfg.ch_list_count);
7326 *channel_count = sap_config->acs_cfg.ch_list_count;
7327 wlan_hdd_get_chanlist_without_nol(adapter, channel_count, channel_list);
7328
7329 if (*channel_count == 0) {
7330 hdd_err("no valid channel found");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307331 return -EINVAL;
Kapil Gupta94ca6f62016-12-11 18:43:12 +05307332 }
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307333
7334 return 0;
7335}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307336
7337/**
7338 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
7339 * @hdd_ctx: HDD context
7340 * @ap_adapter: AP adapter
7341 * @channel: Channel requested by userspace
7342 * @pre_cac_chan: Pointer to the pre CAC channel
7343 *
7344 * Validates the channel provided by userspace. If user provided channel 0,
7345 * a valid outdoor channel must be selected from the regulatory channel.
7346 *
7347 * Return: Zero on success and non zero value on error
7348 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07007349static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
7350 hdd_adapter_t *ap_adapter,
7351 uint8_t channel,
7352 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307353{
7354 uint32_t i, j;
7355 QDF_STATUS status;
7356 int ret;
7357 uint8_t nol[QDF_MAX_NUM_CHAN];
7358 uint32_t nol_len = 0, weight_len = 0;
7359 bool found;
7360 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
7361 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
7362 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
7363
7364 if (0 == channel) {
7365 /* Channel is not obtained from PCL because PCL may not have
7366 * the entire channel list. For example: if SAP is up on
7367 * channel 6 and PCL is queried for the next SAP interface,
7368 * if SCC is preferred, the PCL will contain only the channel
7369 * 6. But, we are in need of a DFS channel. So, going with the
7370 * first channel from the valid channel list.
7371 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007372 status = policy_mgr_get_valid_chans(hdd_ctx->hdd_psoc,
7373 channel_list, &len);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307374 if (QDF_IS_STATUS_ERROR(status)) {
7375 hdd_err("Failed to get channel list");
7376 return -EINVAL;
7377 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007378 policy_mgr_update_with_safe_channel_list(channel_list, &len,
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307379 pcl_weights, weight_len);
7380 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
7381 for (i = 0; i < len; i++) {
7382 found = false;
7383 for (j = 0; j < nol_len; j++) {
7384 if (channel_list[i] == nol[j]) {
7385 found = true;
7386 break;
7387 }
7388 }
7389 if (found)
7390 continue;
7391 if (CDS_IS_DFS_CH(channel_list[i])) {
7392 *pre_cac_chan = channel_list[i];
7393 break;
7394 }
7395 }
7396 if (*pre_cac_chan == 0) {
7397 hdd_err("unable to find outdoor channel");
7398 return -EINVAL;
7399 }
7400 } else {
7401 /* Only when driver selects a channel, check is done for
7402 * unnsafe and NOL channels. When user provides a fixed channel
7403 * the user is expected to take care of this.
7404 */
7405 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
7406 !CDS_IS_DFS_CH(channel)) {
7407 hdd_err("Invalid channel for pre cac:%d", channel);
7408 return -EINVAL;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307409 }
Jeff Johnson68755312017-02-10 11:46:55 -08007410
7411 *pre_cac_chan = channel;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307412 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007413 hdd_debug("selected pre cac channel:%d", *pre_cac_chan);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307414 return 0;
7415}
7416
7417/**
7418 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
7419 * @channel: Channel option provided by userspace
7420 *
7421 * Sets the driver to the required hardware mode and start an adapater for
7422 * pre CAC which will mimic an AP.
7423 *
7424 * Return: Zero on success, non-zero value on error
7425 */
7426int wlan_hdd_request_pre_cac(uint8_t channel)
7427{
Krunal Sonib37bb352016-12-20 14:12:21 -08007428 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307429 hdd_context_t *hdd_ctx;
7430 int ret;
7431 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
7432 hdd_ap_ctx_t *hdd_ap_ctx;
7433 QDF_STATUS status;
7434 struct wiphy *wiphy;
7435 struct net_device *dev;
7436 struct cfg80211_chan_def chandef;
7437 enum nl80211_channel_type channel_type;
7438 uint32_t freq;
7439 struct ieee80211_channel *chan;
7440 tHalHandle handle;
7441 bool val;
7442
7443 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
7444 if (0 != wlan_hdd_validate_context(hdd_ctx))
7445 return -EINVAL;
7446
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007447 if (policy_mgr_get_connection_count(hdd_ctx->hdd_psoc) > 1) {
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307448 hdd_err("pre cac not allowed in concurrency");
7449 return -EINVAL;
7450 }
7451
7452 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
7453 if (!ap_adapter) {
7454 hdd_err("unable to get SAP adapter");
7455 return -EINVAL;
7456 }
7457
7458 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
7459 if (!handle) {
7460 hdd_err("Invalid handle");
7461 return -EINVAL;
7462 }
7463
7464 val = wlan_sap_is_pre_cac_active(handle);
7465 if (val) {
7466 hdd_err("pre cac is already in progress");
7467 return -EINVAL;
7468 }
7469
7470 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
7471 if (!hdd_ap_ctx) {
7472 hdd_err("SAP context is NULL");
7473 return -EINVAL;
7474 }
7475
7476 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
7477 hdd_err("SAP is already on DFS channel:%d",
7478 hdd_ap_ctx->operatingChannel);
7479 return -EINVAL;
7480 }
7481
7482 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
7483 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
7484 hdd_ap_ctx->operatingChannel);
7485 return -EINVAL;
7486 }
7487
Krunal Sonib37bb352016-12-20 14:12:21 -08007488 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
7489 if (!mac_addr) {
7490 hdd_err("can't add virtual intf: Not getting valid mac addr");
7491 return -EINVAL;
7492 }
7493
Srinivas Girigowda13d39252017-03-06 16:12:15 -08007494 hdd_debug("channel:%d", channel);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307495
7496 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
7497 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08007498 if (ret != 0) {
7499 hdd_err("can't validate pre-cac channel");
7500 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307501 }
7502
7503 hdd_debug("starting pre cac SAP adapter");
7504
7505 /* Starting a SAP adapter:
7506 * Instead of opening an adapter, we could just do a SME open session
7507 * for AP type. But, start BSS would still need an adapter.
7508 * So, this option is not taken.
7509 *
7510 * hdd open adapter is going to register this precac interface with
7511 * user space. This interface though exposed to user space will be in
7512 * DOWN state. Consideration was done to avoid this registration to the
7513 * user space. But, as part of SAP operations multiple events are sent
7514 * to user space. Some of these events received from unregistered
7515 * interface was causing crashes. So, retaining the registration.
7516 *
7517 * So, this interface would remain registered and will remain in DOWN
7518 * state for the CAC duration. We will add notes in the feature
7519 * announcement to not use this temporary interface for any activity
7520 * from user space.
7521 */
7522 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08007523 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307524 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307525 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08007526 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307527 }
7528
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307529 /*
7530 * This interface is internally created by the driver. So, no interface
7531 * up comes for this interface from user space and hence starting
7532 * the adapter internally.
7533 */
7534 if (hdd_start_adapter(pre_cac_adapter)) {
7535 hdd_err("error starting the pre cac adapter");
7536 goto close_pre_cac_adapter;
7537 }
7538
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307539 hdd_debug("preparing for start ap/bss on the pre cac adapter");
7540
7541 wiphy = hdd_ctx->wiphy;
7542 dev = pre_cac_adapter->dev;
7543
7544 /* Since this is only a dummy interface lets us use the IEs from the
7545 * other active SAP interface. In regular scenarios, these IEs would
7546 * come from the user space entity
7547 */
7548 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
7549 sizeof(*ap_adapter->sessionCtx.ap.beacon));
7550 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
7551 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307552 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307553 }
7554 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
7555 ap_adapter->sessionCtx.ap.beacon,
7556 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
7557 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
7558 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
7559 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
7560 ap_adapter->sessionCtx.ap.sapConfig.authType;
7561
7562 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
7563 * to operate on the same bandwidth as that of the 2.4GHz operations.
7564 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
7565 */
7566 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
7567 case CH_WIDTH_20MHZ:
7568 channel_type = NL80211_CHAN_HT20;
7569 break;
7570 case CH_WIDTH_40MHZ:
7571 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
7572 ap_adapter->sessionCtx.ap.sapConfig.channel)
7573 channel_type = NL80211_CHAN_HT40PLUS;
7574 else
7575 channel_type = NL80211_CHAN_HT40MINUS;
7576 break;
7577 default:
7578 channel_type = NL80211_CHAN_NO_HT;
7579 break;
7580 }
7581
7582 freq = cds_chan_to_freq(pre_cac_chan);
7583 chan = __ieee80211_get_channel(wiphy, freq);
7584 if (!chan) {
7585 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307586 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307587 }
7588
7589 cfg80211_chandef_create(&chandef, chan, channel_type);
7590
7591 hdd_debug("orig width:%d channel_type:%d freq:%d",
7592 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7593 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007594 /*
7595 * Doing update after opening and starting pre-cac adapter will make
7596 * sure that driver won't do hardware mode change if there are any
7597 * initial hick-ups or issues in pre-cac adapter's configuration.
7598 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7599 * connection update should result in DBS mode
7600 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08007601 status = policy_mgr_update_and_wait_for_connection_update(
7602 hdd_ctx->hdd_psoc,
Krunal Sonib37bb352016-12-20 14:12:21 -08007603 ap_adapter->sessionId,
7604 pre_cac_chan,
7605 SIR_UPDATE_REASON_PRE_CAC);
7606 if (QDF_IS_STATUS_ERROR(status)) {
7607 hdd_err("error in moving to DBS mode");
7608 goto stop_close_pre_cac_adapter;
7609 }
7610
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307611
7612 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7613 if (0 != ret) {
7614 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307615 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307616 }
7617
7618 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7619 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007620 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307621 if (QDF_IS_STATUS_ERROR(status)) {
7622 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307623 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307624 }
7625
7626 /*
7627 * The pre cac status is set here. But, it would not be reset explicitly
7628 * anywhere, since after the pre cac success/failure, the pre cac
7629 * adapter itself would be removed.
7630 */
7631 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7632 if (0 != ret) {
7633 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307634 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307635 }
7636
7637 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7638 hdd_ap_ctx->operatingChannel);
7639 if (0 != ret) {
7640 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307641 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307642 }
7643
7644 ap_adapter->pre_cac_chan = pre_cac_chan;
7645
7646 return 0;
7647
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307648stop_close_pre_cac_adapter:
7649 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307650 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7651 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307652close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307653 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007654release_intf_addr_and_return_failure:
7655 /*
7656 * Release the interface address as the adapter
7657 * failed to start, if you don't release then next
7658 * adapter which is trying to come wouldn't get valid
7659 * mac address. Remember we have limited pool of mac addresses
7660 */
7661 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307662 return -EINVAL;
7663}
7664
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307665static const struct nla_policy
7666wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7667 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7668};
7669
Agrawal Ashish65634612016-08-18 13:24:32 +05307670static const struct nla_policy
7671wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7672 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7673 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7674};
7675
7676/**
7677 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7678 * @wiphy: Pointer to wireless phy
7679 * @wdev: Pointer to wireless device
7680 * @data: Pointer to data
7681 * @data_len: Length of @data
7682 *
7683 * This function parses the incoming NL vendor command data attributes and
7684 * updates the SAP context about channel_hint and DFS mode.
7685 * If channel_hint is set, SAP will choose that channel
7686 * as operating channel.
7687 *
7688 * If DFS mode is enabled, driver will include DFS channels
7689 * in ACS else driver will skip DFS channels.
7690 *
7691 * Return: 0 on success, negative errno on failure
7692 */
7693static int
7694__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7695 struct wireless_dev *wdev,
7696 const void *data, int data_len)
7697{
7698 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7699 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7700 int ret;
7701 struct acs_dfs_policy *acs_policy;
7702 int mode = DFS_MODE_NONE;
7703 int channel_hint = 0;
7704
7705 ENTER_DEV(wdev->netdev);
7706
7707 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7708 hdd_err("Command not allowed in FTM mode");
7709 return -EINVAL;
7710 }
7711
7712 ret = wlan_hdd_validate_context(hdd_ctx);
7713 if (0 != ret)
7714 return ret;
7715
7716 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7717 data, data_len,
7718 wlan_hdd_set_acs_dfs_config_policy)) {
7719 hdd_err("invalid attr");
7720 return -EINVAL;
7721 }
7722
7723 acs_policy = &hdd_ctx->acs_policy;
7724 /*
7725 * SCM sends this attribute to restrict SAP from choosing
7726 * DFS channels from ACS.
7727 */
7728 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7729 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7730
7731 if (!IS_DFS_MODE_VALID(mode)) {
7732 hdd_err("attr acs dfs mode is not valid");
7733 return -EINVAL;
7734 }
7735 acs_policy->acs_dfs_mode = mode;
7736
7737 /*
7738 * SCM sends this attribute to provide an active channel,
7739 * to skip redundant ACS between drivers, and save driver start up time
7740 */
7741 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7742 channel_hint = nla_get_u8(
7743 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7744
7745 if (!IS_CHANNEL_VALID(channel_hint)) {
7746 hdd_err("acs channel is not valid");
7747 return -EINVAL;
7748 }
7749 acs_policy->acs_channel = channel_hint;
7750
7751 return 0;
7752}
7753
7754/**
7755 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7756 * @wiphy: wiphy structure pointer
7757 * @wdev: Wireless device structure pointer
7758 * @data: Pointer to the data received
7759 * @data_len: Length of @data
7760 *
7761 * This function parses the incoming NL vendor command data attributes and
7762 * updates the SAP context about channel_hint and DFS mode.
7763 *
7764 * Return: 0 on success; errno on failure
7765 */
7766static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7767 struct wireless_dev *wdev,
7768 const void *data, int data_len)
7769{
7770 int ret;
7771
7772 cds_ssr_protect(__func__);
7773 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7774 cds_ssr_unprotect(__func__);
7775
7776 return ret;
7777}
7778
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307779/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307780 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7781 * @mode : cfg80211 dfs mode
7782 *
7783 * Return: return csr sta roam dfs mode else return NONE
7784 */
7785static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7786 enum dfs_mode mode)
7787{
7788 switch (mode) {
7789 case DFS_MODE_ENABLE:
7790 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7791 break;
7792 case DFS_MODE_DISABLE:
7793 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7794 break;
7795 case DFS_MODE_DEPRIORITIZE:
7796 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7797 break;
7798 default:
7799 hdd_err("STA Roam policy dfs mode is NONE");
7800 return CSR_STA_ROAM_POLICY_NONE;
7801 }
7802}
7803
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307804/*
7805 * hdd_get_sap_operating_band: Get current operating channel
7806 * for sap.
7807 * @hdd_ctx: hdd context
7808 *
7809 * Return : Corresponding band for SAP operating channel
7810 */
7811uint8_t hdd_get_sap_operating_band(hdd_context_t *hdd_ctx)
7812{
7813 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
7814 QDF_STATUS status;
7815 hdd_adapter_t *adapter;
7816 uint8_t operating_channel = 0;
7817 uint8_t sap_operating_band = 0;
7818 status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
7819 while (NULL != adapter_node && QDF_STATUS_SUCCESS == status) {
7820 adapter = adapter_node->pAdapter;
7821
7822 if (!(adapter && (QDF_SAP_MODE == adapter->device_mode))) {
7823 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7824 &next);
7825 adapter_node = next;
7826 continue;
7827 }
7828 operating_channel = adapter->sessionCtx.ap.operatingChannel;
7829 if (IS_24G_CH(operating_channel))
7830 sap_operating_band = eCSR_BAND_24;
7831 else if (IS_5G_CH(operating_channel))
7832 sap_operating_band = eCSR_BAND_5G;
7833 else
7834 sap_operating_band = eCSR_BAND_ALL;
7835 status = hdd_get_next_adapter(hdd_ctx, adapter_node,
7836 &next);
bings373b99b2017-01-23 10:35:08 +08007837 adapter_node = next;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307838 }
7839 return sap_operating_band;
7840}
7841
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307842static const struct nla_policy
7843wlan_hdd_set_sta_roam_config_policy[
7844QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7845 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7846 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7847};
7848
7849/**
7850 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7851 * for station connection or roaming.
7852 * @wiphy: Pointer to wireless phy
7853 * @wdev: Pointer to wireless device
7854 * @data: Pointer to data
7855 * @data_len: Length of @data
7856 *
7857 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7858 * channels needs to be skipped in scanning or not.
7859 * If dfs_mode is disabled, driver will not scan DFS channels.
7860 * If skip_unsafe_channels is set, driver will skip unsafe channels
7861 * in Scanning.
7862 *
7863 * Return: 0 on success, negative errno on failure
7864 */
7865static int
7866__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7867 struct wireless_dev *wdev,
7868 const void *data, int data_len)
7869{
7870 struct net_device *dev = wdev->netdev;
7871 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7872 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7873 struct nlattr *tb[
7874 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7875 int ret;
7876 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7877 enum dfs_mode mode = DFS_MODE_NONE;
7878 bool skip_unsafe_channels = false;
7879 QDF_STATUS status;
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307880 uint8_t sap_operating_band;
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307881
7882 ENTER_DEV(dev);
7883
7884 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7885 hdd_err("Command not allowed in FTM mode");
7886 return -EINVAL;
7887 }
7888
7889 ret = wlan_hdd_validate_context(hdd_ctx);
7890 if (0 != ret)
7891 return ret;
7892 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7893 data, data_len,
7894 wlan_hdd_set_sta_roam_config_policy)) {
7895 hdd_err("invalid attr");
7896 return -EINVAL;
7897 }
7898 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7899 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7900 if (!IS_DFS_MODE_VALID(mode)) {
7901 hdd_err("attr sta roam dfs mode policy is not valid");
7902 return -EINVAL;
7903 }
7904
7905 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7906
7907 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7908 skip_unsafe_channels = nla_get_u8(
7909 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307910 sap_operating_band = hdd_get_sap_operating_band(hdd_ctx);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307911 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
Agrawal, Ashish9f84c402016-11-30 16:19:44 +05307912 skip_unsafe_channels, adapter->sessionId,
7913 sap_operating_band);
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307914
7915 if (!QDF_IS_STATUS_SUCCESS(status)) {
7916 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7917 return -EINVAL;
7918 }
7919 return 0;
7920}
7921
7922/**
7923 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7924 * connection and roaming for station.
7925 * @wiphy: wiphy structure pointer
7926 * @wdev: Wireless device structure pointer
7927 * @data: Pointer to the data received
7928 * @data_len: Length of @data
7929 *
7930 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7931 * channels needs to be skipped in scanning or not.
7932 * If dfs_mode is disabled, driver will not scan DFS channels.
7933 * If skip_unsafe_channels is set, driver will skip unsafe channels
7934 * in Scanning.
7935 * Return: 0 on success; errno on failure
7936 */
7937static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7938 struct wireless_dev *wdev,
7939 const void *data, int data_len)
7940{
7941 int ret;
7942
7943 cds_ssr_protect(__func__);
7944 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7945 cds_ssr_unprotect(__func__);
7946
7947 return ret;
7948}
7949
Agrawal Ashish467dde42016-09-08 18:44:22 +05307950#ifdef FEATURE_WLAN_CH_AVOID
7951/**
7952 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7953 * is on unsafe channel.
7954 * @wiphy: wiphy structure pointer
7955 * @wdev: Wireless device structure pointer
7956 * @data: Pointer to the data received
7957 * @data_len: Length of @data
7958 *
7959 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7960 * on any of unsafe channels.
7961 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7962 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7963 *
7964 * Return: 0 on success; errno on failure
7965 */
7966static int
7967__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7968 struct wireless_dev *wdev,
7969 const void *data, int data_len)
7970{
7971 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7972 int ret;
7973 uint16_t unsafe_channel_count;
7974 int unsafe_channel_index;
7975 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7976
7977 ENTER_DEV(wdev->netdev);
7978
7979 if (!qdf_ctx) {
7980 cds_err("qdf_ctx is NULL");
7981 return -EINVAL;
7982 }
7983
7984 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7985 hdd_err("Command not allowed in FTM mode");
7986 return -EINVAL;
7987 }
7988
7989 ret = wlan_hdd_validate_context(hdd_ctx);
7990 if (0 != ret)
7991 return ret;
7992 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7993 &(hdd_ctx->unsafe_channel_count),
7994 sizeof(hdd_ctx->unsafe_channel_list));
7995
7996 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7997 (uint16_t)NUM_CHANNELS);
7998 for (unsafe_channel_index = 0;
7999 unsafe_channel_index < unsafe_channel_count;
8000 unsafe_channel_index++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008001 hdd_debug("Channel %d is not safe",
Agrawal Ashish467dde42016-09-08 18:44:22 +05308002 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
8003 }
8004 hdd_unsafe_channel_restart_sap(hdd_ctx);
8005 return 0;
8006}
8007
8008/**
8009 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
8010 * is on unsafe channel.
8011 * @wiphy: wiphy structure pointer
8012 * @wdev: Wireless device structure pointer
8013 * @data: Pointer to the data received
8014 * @data_len: Length of @data
8015 *
8016 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
8017 * on any of unsafe channels.
8018 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
8019 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
8020 *
8021 * Return: 0 on success; errno on failure
8022 */
8023static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
8024 struct wireless_dev *wdev,
8025 const void *data, int data_len)
8026{
8027 int ret;
8028
8029 cds_ssr_protect(__func__);
8030 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
8031 cds_ssr_unprotect(__func__);
8032
8033 return ret;
8034}
8035
8036#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308037/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308038 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
8039 * SAP is on unsafe channel.
8040 * @wiphy: wiphy structure pointer
8041 * @wdev: Wireless device structure pointer
8042 * @data: Pointer to the data received
8043 * @data_len: Length of @data
8044 *
8045 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8046 * driver.
8047 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8048 * will initiate restart of sap.
8049 *
8050 * Return: 0 on success; errno on failure
8051 */
8052static int
8053__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8054 struct wireless_dev *wdev,
8055 const void *data, int data_len)
8056{
8057 struct net_device *ndev = wdev->netdev;
8058 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8059 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8060 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
8061 uint8_t config_channel = 0;
8062 hdd_ap_ctx_t *ap_ctx;
8063 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308064 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308065
8066 ENTER();
8067
8068 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008069 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308070 return -EINVAL;
8071 }
8072
8073 ret = wlan_hdd_validate_context(hdd_ctx);
8074 if (0 != ret)
8075 return -EINVAL;
8076
8077 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
8078 data, data_len,
8079 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008080 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308081 return -EINVAL;
8082 }
8083
8084 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
8085 if (!test_bit(SOFTAP_BSS_STARTED,
8086 &hostapd_adapter->event_flags)) {
8087 hdd_err("SAP is not started yet. Restart sap will be invalid");
8088 return -EINVAL;
8089 }
8090
8091 config_channel =
8092 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
8093
8094 if (!((IS_24G_CH(config_channel)) ||
8095 (IS_5G_CH(config_channel)))) {
8096 hdd_err("Channel %d is not valid to restart SAP",
8097 config_channel);
8098 return -ENOTSUPP;
8099 }
8100
8101 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
8102 ap_ctx->sapConfig.channel = config_channel;
8103 ap_ctx->sapConfig.ch_params.ch_width =
8104 ap_ctx->sapConfig.ch_width_orig;
8105
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07008106 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308107 ap_ctx->sapConfig.sec_ch,
8108 &ap_ctx->sapConfig.ch_params);
8109
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008110 hdd_restart_sap(hostapd_adapter);
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308111 }
8112
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308113 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
8114 uint32_t freq_len, i;
8115 uint32_t *freq;
8116 uint8_t chans[QDF_MAX_NUM_CHAN];
8117
8118 hdd_debug("setting mandatory freq/chan list");
8119
8120 freq_len = nla_len(
8121 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
8122 sizeof(uint32_t);
8123
8124 if (freq_len > QDF_MAX_NUM_CHAN) {
8125 hdd_err("insufficient space to hold channels");
8126 return -ENOMEM;
8127 }
8128
8129 freq = nla_data(
8130 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
8131
8132 hdd_debug("freq_len=%d", freq_len);
8133
8134 for (i = 0; i < freq_len; i++) {
8135 chans[i] = ieee80211_frequency_to_channel(freq[i]);
8136 hdd_debug("freq[%d]=%d", i, freq[i]);
8137 }
8138
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -08008139 status = policy_mgr_set_sap_mandatory_channels(
8140 hdd_ctx->hdd_psoc, chans, freq_len);
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05308141 if (QDF_IS_STATUS_ERROR(status))
8142 return -EINVAL;
8143 }
8144
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308145 return 0;
8146}
8147
8148/**
8149 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
8150 * @wiphy: wiphy structure pointer
8151 * @wdev: Wireless device structure pointer
8152 * @data: Pointer to the data received
8153 * @data_len: Length of @data
8154 *
8155 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
8156 * driver.
8157 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
8158 * will initiate restart of sap.
8159 *
8160 * Return: 0 on success; errno on failure
8161 */
8162static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
8163 struct wireless_dev *wdev,
8164 const void *data, int data_len)
8165{
8166 int ret;
8167
8168 cds_ssr_protect(__func__);
8169 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
8170 wdev, data, data_len);
8171 cds_ssr_unprotect(__func__);
8172
8173 return ret;
8174}
8175
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308176#undef BPF_INVALID
8177#undef BPF_SET_RESET
8178#undef BPF_VERSION
8179#undef BPF_ID
8180#undef BPF_PACKET_SIZE
8181#undef BPF_CURRENT_OFFSET
8182#undef BPF_PROGRAM
8183#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308184
8185/**
8186 * define short names for the global vendor params
8187 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
8188 */
8189#define PARAM_TOTAL_CMD_EVENT_WAKE \
8190 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
8191#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
8192 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
8193#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
8194 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
8195#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
8196 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
8197#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
8198 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
8199#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
8200 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
8201#define PARAM_TOTAL_RX_DATA_WAKE \
8202 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
8203#define PARAM_RX_UNICAST_CNT \
8204 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
8205#define PARAM_RX_MULTICAST_CNT \
8206 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
8207#define PARAM_RX_BROADCAST_CNT \
8208 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
8209#define PARAM_ICMP_PKT \
8210 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
8211#define PARAM_ICMP6_PKT \
8212 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
8213#define PARAM_ICMP6_RA \
8214 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
8215#define PARAM_ICMP6_NA \
8216 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
8217#define PARAM_ICMP6_NS \
8218 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
8219#define PARAM_ICMP4_RX_MULTICAST_CNT \
8220 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
8221#define PARAM_ICMP6_RX_MULTICAST_CNT \
8222 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
8223#define PARAM_OTHER_RX_MULTICAST_CNT \
8224 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308225#define PARAM_RSSI_BREACH_CNT \
8226 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
8227#define PARAM_LOW_RSSI_CNT \
8228 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
8229#define PARAM_GSCAN_CNT \
8230 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
8231#define PARAM_PNO_COMPLETE_CNT \
8232 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
8233#define PARAM_PNO_MATCH_CNT \
8234 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
8235
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308236
8237
8238/**
8239 * hdd_send_wakelock_stats() - API to send wakelock stats
8240 * @ctx: context to be passed to callback
8241 * @data: data passed to callback
8242 *
8243 * This function is used to send wake lock stats to HAL layer
8244 *
8245 * Return: 0 on success, error number otherwise.
8246 */
8247static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
8248 const struct sir_wake_lock_stats *data)
8249{
8250 struct sk_buff *skb;
8251 uint32_t nl_buf_len;
8252 uint32_t total_rx_data_wake, rx_multicast_cnt;
8253 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308254 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308255
8256 ENTER();
8257
8258 nl_buf_len = NLMSG_HDRLEN;
8259 nl_buf_len +=
8260 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
8261 (NLMSG_HDRLEN + sizeof(uint32_t));
8262
8263 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8264
8265 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008266 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308267 return -ENOMEM;
8268 }
8269
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008270 hdd_debug("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308271 data->wow_ucast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008272 hdd_debug("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308273 data->wow_bcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008274 hdd_debug("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308275 data->wow_ipv4_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008276 hdd_debug("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308277 data->wow_ipv6_mcast_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008278 hdd_debug("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308279 data->wow_ipv6_mcast_ra_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008280 hdd_debug("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308281 data->wow_ipv6_mcast_ns_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008282 hdd_debug("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308283 data->wow_ipv6_mcast_na_stats);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008284 hdd_debug("wow_icmpv4_count %d", data->wow_icmpv4_count);
8285 hdd_debug("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308286 data->wow_icmpv6_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008287 hdd_debug("wow_rssi_breach_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308288 data->wow_rssi_breach_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008289 hdd_debug("wow_low_rssi_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308290 data->wow_low_rssi_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008291 hdd_debug("wow_gscan_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308292 data->wow_gscan_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008293 hdd_debug("wow_pno_complete_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308294 data->wow_pno_complete_wake_up_count);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008295 hdd_debug("wow_pno_match_wake_up_count %d",
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308296 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308297
8298 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308299 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308300
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308301 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05308302 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308303
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308304 rx_multicast_cnt =
8305 data->wow_ipv4_mcast_wake_up_count +
8306 ipv6_rx_multicast_addr_cnt;
8307
8308 total_rx_data_wake =
8309 data->wow_ucast_wake_up_count +
8310 data->wow_bcast_wake_up_count +
8311 rx_multicast_cnt;
8312
8313 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
8314 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
8315 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
8316 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
8317 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
8318 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
8319 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
8320 total_rx_data_wake) ||
8321 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
8322 data->wow_ucast_wake_up_count) ||
8323 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
8324 rx_multicast_cnt) ||
8325 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
8326 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05308327 nla_put_u32(skb, PARAM_ICMP_PKT,
8328 data->wow_icmpv4_count) ||
8329 nla_put_u32(skb, PARAM_ICMP6_PKT,
8330 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308331 nla_put_u32(skb, PARAM_ICMP6_RA,
8332 data->wow_ipv6_mcast_ra_stats) ||
8333 nla_put_u32(skb, PARAM_ICMP6_NA,
8334 data->wow_ipv6_mcast_na_stats) ||
8335 nla_put_u32(skb, PARAM_ICMP6_NS,
8336 data->wow_ipv6_mcast_ns_stats) ||
8337 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
8338 data->wow_ipv4_mcast_wake_up_count) ||
8339 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
8340 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05308341 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
8342 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
8343 data->wow_rssi_breach_wake_up_count) ||
8344 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
8345 data->wow_low_rssi_wake_up_count) ||
8346 nla_put_u32(skb, PARAM_GSCAN_CNT,
8347 data->wow_gscan_wake_up_count) ||
8348 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
8349 data->wow_pno_complete_wake_up_count) ||
8350 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
8351 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008352 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308353 goto nla_put_failure;
8354 }
8355
8356 cfg80211_vendor_cmd_reply(skb);
8357
8358 EXIT();
8359 return 0;
8360
8361nla_put_failure:
8362 kfree_skb(skb);
8363 return -EINVAL;
8364}
8365
8366/**
8367 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8368 * @wiphy: wiphy pointer
8369 * @wdev: pointer to struct wireless_dev
8370 * @data: pointer to incoming NL vendor data
8371 * @data_len: length of @data
8372 *
8373 * This function parses the incoming NL vendor command data attributes and
8374 * invokes the SME Api and blocks on a completion variable.
8375 * WMA copies required data and invokes callback
8376 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8377 *
8378 * Return: 0 on success; error number otherwise.
8379 */
8380static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8381 struct wireless_dev *wdev,
8382 const void *data,
8383 int data_len)
8384{
8385 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8386 int status, ret;
8387 struct sir_wake_lock_stats wake_lock_stats;
8388 QDF_STATUS qdf_status;
8389
8390 ENTER();
8391
8392 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008393 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308394 return -EINVAL;
8395 }
8396
8397 status = wlan_hdd_validate_context(hdd_ctx);
8398 if (0 != status)
8399 return -EINVAL;
8400
8401 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
8402 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07008403 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308404 return -EINVAL;
8405 }
8406
8407 ret = hdd_send_wakelock_stats(hdd_ctx,
8408 &wake_lock_stats);
8409 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07008410 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308411
8412 EXIT();
8413 return ret;
8414}
8415
8416/**
8417 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
8418 * @wiphy: wiphy pointer
8419 * @wdev: pointer to struct wireless_dev
8420 * @data: pointer to incoming NL vendor data
8421 * @data_len: length of @data
8422 *
8423 * This function parses the incoming NL vendor command data attributes and
8424 * invokes the SME Api and blocks on a completion variable.
8425 * WMA copies required data and invokes callback
8426 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
8427 *
8428 * Return: 0 on success; error number otherwise.
8429 */
8430static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
8431 struct wireless_dev *wdev,
8432 const void *data, int data_len)
8433{
8434 int ret;
8435
8436 cds_ssr_protect(__func__);
8437 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
8438 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07008439 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308440
8441 return ret;
8442}
8443
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308444/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308445 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
8446 * @wiphy: wiphy structure pointer
8447 * @wdev: Wireless device structure pointer
8448 * @data: Pointer to the data received
8449 * @data_len: Length of @data
8450 *
8451 * This function reads wmi max bus size and fill in the skb with
8452 * NL attributes and send up the NL event.
8453 * Return: 0 on success; errno on failure
8454 */
8455static int
8456__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8457 struct wireless_dev *wdev,
8458 const void *data, int data_len)
8459{
8460 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8461 int ret_val;
8462 struct sk_buff *skb;
8463 uint32_t nl_buf_len;
8464
8465 ENTER();
8466
8467 ret_val = wlan_hdd_validate_context(hdd_ctx);
8468 if (ret_val)
8469 return ret_val;
8470
8471 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8472 hdd_err("Command not allowed in FTM mode");
8473 return -EINVAL;
8474 }
8475
Srinivas Girigowda13d39252017-03-06 16:12:15 -08008476 hdd_debug("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308477
8478 nl_buf_len = NLMSG_HDRLEN;
8479 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
8480
8481 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
8482 if (!skb) {
8483 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
8484 return -ENOMEM;
8485 }
8486
8487 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
8488 hdd_ctx->wmi_max_len)) {
8489 hdd_err("nla put failure");
8490 goto nla_put_failure;
8491 }
8492
8493 cfg80211_vendor_cmd_reply(skb);
8494
8495 EXIT();
8496
8497 return 0;
8498
8499nla_put_failure:
8500 kfree_skb(skb);
8501 return -EINVAL;
8502}
8503
8504/**
8505 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
8506 * @wiphy: wiphy structure pointer
8507 * @wdev: Wireless device structure pointer
8508 * @data: Pointer to the data received
8509 * @data_len: Length of @data
8510 *
8511 * Return: 0 on success; errno on failure
8512 */
8513static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
8514 struct wireless_dev *wdev,
8515 const void *data, int data_len)
8516{
8517 int ret;
8518
8519 cds_ssr_protect(__func__);
8520 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
8521 cds_ssr_unprotect(__func__);
8522
8523 return ret;
8524}
8525
8526/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308527 *__wlan_hdd_cfg80211_setband() - set band
8528 * @wiphy: Pointer to wireless phy
8529 * @wdev: Pointer to wireless device
8530 * @data: Pointer to data
8531 * @data_len: Length of @data
8532 *
8533 * Return: 0 on success, negative errno on failure
8534 */
8535static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8536 struct wireless_dev *wdev,
8537 const void *data, int data_len)
8538{
8539 struct net_device *dev = wdev->netdev;
8540 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8541 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
8542 int ret;
8543 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
8544 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
8545
8546 ENTER();
8547
8548 ret = wlan_hdd_validate_context(hdd_ctx);
8549 if (ret)
8550 return ret;
8551
8552 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
8553 hdd_err(FL("Invalid ATTR"));
8554 return -EINVAL;
8555 }
8556
8557 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
8558 hdd_err(FL("attr SETBAND_VALUE failed"));
8559 return -EINVAL;
8560 }
8561
8562 ret = hdd_set_band(dev,
8563 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
8564
8565 EXIT();
8566 return ret;
8567}
8568
8569/**
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308570 *wlan_hdd_validate_acs_channel() - validate channel provided by ACS
8571 * @adapter: hdd adapter
8572 * @channel: channel number
8573 *
8574 * return: QDF status based on success or failure
8575 */
8576static QDF_STATUS wlan_hdd_validate_acs_channel(hdd_adapter_t *adapter,
8577 int channel, int chan_bw)
8578{
8579 if (QDF_STATUS_SUCCESS !=
8580 wlan_hdd_validate_operation_channel(adapter, channel))
8581 return QDF_STATUS_E_FAILURE;
8582 if ((wlansap_is_channel_in_nol_list(WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8583 channel,
8584 PHY_SINGLE_CHANNEL_CENTERED))) {
8585 hdd_notice("channel %d is in nol", channel);
8586 return -EINVAL;
8587 }
8588
8589 if ((wlansap_is_channel_leaking_in_nol(
8590 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8591 channel, chan_bw))) {
8592 hdd_notice("channel %d is leaking in nol", channel);
8593 return -EINVAL;
8594 }
8595
8596 return 0;
8597
8598}
8599
Kapil Gupta8878ad92017-02-13 11:56:04 +05308600static void hdd_update_acs_sap_config(hdd_context_t *hdd_ctx,
8601 tsap_Config_t *sap_config,
8602 struct hdd_vendor_chan_info *channel_list)
8603{
8604 sap_config->channel = channel_list->pri_ch;
8605
8606 sap_config->ch_params.center_freq_seg0 =
8607 channel_list->vht_seg0_center_ch;
8608 sap_config->ch_params.center_freq_seg1 =
8609 channel_list->vht_seg1_center_ch;
8610
8611 sap_config->ch_params.sec_ch_offset = channel_list->ht_sec_ch;
8612 sap_config->ch_params.ch_width = channel_list->chan_width;
8613 if (sap_config->channel >= 36)
8614 sap_config->ch_width_orig =
8615 hdd_ctx->config->vhtChannelWidth;
8616 else
8617 sap_config->ch_width_orig =
8618 hdd_ctx->config->nChannelBondingMode24GHz ?
8619 eHT_CHANNEL_WIDTH_40MHZ :
8620 eHT_CHANNEL_WIDTH_20MHZ;
8621
8622 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8623 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8624 sap_config->acs_cfg.vht_seg0_center_ch =
8625 channel_list->vht_seg0_center_ch;
8626 sap_config->acs_cfg.vht_seg1_center_ch =
8627 channel_list->vht_seg1_center_ch;
8628 sap_config->acs_cfg.ht_sec_ch = channel_list->ht_sec_ch;
8629}
8630
8631static int hdd_update_acs_channel(hdd_adapter_t *adapter, uint8_t reason,
8632 uint8_t channel_cnt,
8633 struct hdd_vendor_chan_info *channel_list)
8634{
8635 tsap_Config_t *sap_config;
8636 hdd_ap_ctx_t *hdd_ap_ctx;
8637 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8638 QDF_STATUS status = QDF_STATUS_SUCCESS;
8639
8640 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
8641 sap_config = &adapter->sessionCtx.ap.sapConfig;
8642
8643 if (QDF_TIMER_STATE_RUNNING ==
8644 qdf_mc_timer_get_current_state(&adapter->sessionCtx.
8645 ap.vendor_acs_timer)) {
8646 qdf_mc_timer_stop(&adapter->sessionCtx.ap.vendor_acs_timer);
8647 }
8648
8649 if (channel_list && channel_list->pri_ch == 0) {
8650 /* Check mode, set default channel */
8651 channel_list->pri_ch = 6;
8652 /*
8653 * sap_select_default_oper_chan(hdd_ctx->hHal,
8654 * sap_config->acs_cfg.hw_mode);
8655 */
8656 }
8657
8658 switch (reason) {
8659 /* SAP init case */
8660 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT:
8661 hdd_update_acs_sap_config(hdd_ctx, sap_config, channel_list);
8662 /* Update Hostapd */
8663 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
8664 break;
8665
8666 /* DFS detected on current channel */
8667 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS:
8668 wlan_sap_update_next_channel(
8669 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
8670 channel_list->pri_ch,
8671 channel_list->chan_width);
8672 status = sme_update_new_channel_event(
8673 WLAN_HDD_GET_HAL_CTX(adapter),
8674 adapter->sessionId);
8675 break;
8676
8677 /* LTE coex event on current channel */
8678 case QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX:
8679 sap_config->acs_cfg.pri_ch = channel_list->pri_ch;
8680 sap_config->acs_cfg.ch_width = channel_list->chan_width;
8681 hdd_ap_ctx->sapConfig.ch_width_orig =
8682 channel_list->chan_width;
Tushnim Bhattacharyya9e81b4c2017-02-15 17:11:14 -08008683 hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch);
Kapil Gupta8878ad92017-02-13 11:56:04 +05308684 break;
8685
8686 default:
8687 hdd_info("invalid reason for timer invoke");
8688 }
8689 qdf_mem_free(channel_list);
8690 EXIT();
8691 return status;
8692}
8693
8694/**
8695 * Define short name for vendor channel set config
8696 */
8697#define SET_CHAN_REASON QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON
8698#define SET_CHAN_CHANNEL_COUNT QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_COUNT
8699#define SET_CHAN_CHAN_LIST QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST
8700#define SET_CHAN_PRIMARY_CHANNEL \
8701 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY
8702#define SET_CHAN_SECONDARY_CHANNEL \
8703 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY
8704#define SET_CHAN_SEG0_CENTER_CHANNEL \
8705 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0
8706#define SET_CHAN_SEG1_CENTER_CHANNEL \
8707 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1
8708#define SET_CHAN_CHANNEL_WIDTH \
8709 QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH
8710#define SET_CHAN_MAX QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX
8711
8712/**
8713 * hdd_parse_vendor_acs_chan_config() - API to parse vendor acs channel config
8714 * @channel_list: pointer to hdd_vendor_chan_info
8715 * @reason: channel change reason
8716 * @channel_cnt: channel count
8717 * @data: data
8718 * @data_len: data len
8719 *
8720 * Return: 0 on success, negative errno on failure
8721 */
8722static int hdd_parse_vendor_acs_chan_config(struct hdd_vendor_chan_info
8723 **chan_list_ptr, uint8_t *reason, uint8_t *channel_cnt,
8724 const void *data, int data_len)
8725{
8726 int rem, i = 0;
8727 struct nlattr *tb[SET_CHAN_MAX + 1];
8728 struct nlattr *tb2[SET_CHAN_MAX + 1];
8729 struct nlattr *curr_attr;
8730 struct hdd_vendor_chan_info *channel_list;
8731
8732 if (nla_parse(tb, SET_CHAN_MAX, data, data_len, NULL)) {
8733 hdd_err("Invalid ATTR");
8734 return -EINVAL;
8735 }
8736
8737 if (tb[SET_CHAN_REASON])
8738 *reason = nla_get_u8(tb[SET_CHAN_REASON]);
8739
8740 if (tb[SET_CHAN_CHANNEL_COUNT]) {
8741 *channel_cnt = nla_get_u8(tb[
8742 SET_CHAN_CHANNEL_COUNT]);
8743 hdd_info("channel count %d", *channel_cnt);
8744 }
8745
8746 if (!(*channel_cnt)) {
8747 hdd_err("channel count is %d", *channel_cnt);
8748 return -EINVAL;
8749 }
8750
8751 channel_list = qdf_mem_malloc(sizeof(struct hdd_vendor_chan_info) *
8752 (*channel_cnt));
8753
8754 nla_for_each_nested(curr_attr, tb[SET_CHAN_CHAN_LIST], rem) {
8755 if (nla_parse(tb2,
8756 SET_CHAN_MAX,
8757 nla_data(curr_attr), nla_len(curr_attr),
8758 NULL)) {
8759 hdd_err("nla_parse failed");
8760 return -EINVAL;
8761 }
8762 /* Parse and Fetch allowed SSID list*/
8763 if (tb2[SET_CHAN_PRIMARY_CHANNEL]) {
8764 channel_list[i].pri_ch =
8765 nla_get_u8(
8766 tb2[SET_CHAN_PRIMARY_CHANNEL]);
8767 }
8768 if (tb2[SET_CHAN_SECONDARY_CHANNEL]) {
8769 channel_list[i].ht_sec_ch =
8770 nla_get_u8(tb2[SET_CHAN_SECONDARY_CHANNEL]);
8771 }
8772 if (tb2[SET_CHAN_SEG0_CENTER_CHANNEL]) {
8773 channel_list[i].vht_seg0_center_ch =
8774 nla_get_u8(tb2[SET_CHAN_SEG0_CENTER_CHANNEL]);
8775 }
8776 if (tb2[SET_CHAN_SEG1_CENTER_CHANNEL]) {
8777 channel_list[i].vht_seg1_center_ch =
8778 nla_get_u8(tb2[SET_CHAN_SEG1_CENTER_CHANNEL]);
8779 }
8780 if (tb2[SET_CHAN_CHANNEL_WIDTH]) {
8781 channel_list[i].chan_width =
8782 nla_get_u8(tb2[SET_CHAN_CHANNEL_WIDTH]);
8783 }
8784 hdd_info("index %d pri %d sec %d seg0 %d seg1 %d width %d",
8785 i, channel_list[i].pri_ch,
8786 channel_list[i].ht_sec_ch,
8787 channel_list[i].vht_seg0_center_ch,
8788 channel_list[i].vht_seg1_center_ch,
8789 channel_list[i].chan_width);
8790 i++;
8791 if (i > *channel_cnt)
8792 break;
8793 }
8794 *chan_list_ptr = channel_list;
8795
8796 return 0;
8797}
8798
8799/**
8800 * Undef short names for vendor set channel configuration
8801 */
8802#undef SET_CHAN_REASON
8803#undef SET_CHAN_CHANNEL_COUNT
8804#undef SET_CHAN_CHAN_LIST
8805#undef SET_CHAN_PRIMARY_CHANNEL
8806#undef SET_CHAN_SECONDARY_CHANNEL
8807#undef SET_CHAN_SEG0_CENTER_CHANNEL
8808#undef SET_CHAN_SEG1_CENTER_CHANNEL
8809#undef SET_CHAN_CHANNEL_WIDTH
8810#undef SET_CHAN_MAX
8811
8812/**
8813 * __wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8814 * @wiphy: Pointer to wireless phy
8815 * @wdev: Pointer to wireless device
8816 * @data: Pointer to data
8817 * @data_len: Length of @data
8818 *
8819 * Return: 0 on success, negative errno on failure
8820 */
8821static int __wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8822 struct wireless_dev *wdev,
8823 const void *data, int data_len)
8824{
8825 int ret_val;
8826 QDF_STATUS qdf_status;
8827 uint8_t channel_cnt = 0, reason = -1;
8828 struct hdd_vendor_chan_info *channel_list = NULL;
8829 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev);
8830 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
8831
8832 ENTER();
8833
8834 ret_val = wlan_hdd_validate_context(hdd_ctx);
8835 if (ret_val)
8836 return ret_val;
8837
8838 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
8839 hdd_err("Command not allowed in FTM mode");
8840 return -EINVAL;
8841 }
8842
8843 if (test_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags))
8844 clear_bit(VENDOR_ACS_RESPONSE_PENDING, &adapter->event_flags);
8845 else {
8846 hdd_err("already timeout happened for acs");
8847 return -EINVAL;
8848 }
8849
8850 ret_val = hdd_parse_vendor_acs_chan_config(&channel_list, &reason,
8851 &channel_cnt, data, data_len);
8852 if (ret_val)
8853 return ret_val;
8854
8855 /* Validate channel to be set */
8856 while (channel_cnt && channel_list) {
8857 qdf_status = wlan_hdd_validate_acs_channel(adapter,
8858 channel_list->pri_ch,
8859 channel_list->chan_width);
8860 if (qdf_status == QDF_STATUS_SUCCESS)
8861 break;
8862 channel_cnt--;
8863 channel_list++;
8864 }
8865 if ((channel_cnt <= 0) || !channel_list) {
8866 hdd_err("no available channel/chanlist %p", channel_list);
8867 return -EINVAL;
8868 }
8869
8870 qdf_status = hdd_update_acs_channel(adapter, reason,
8871 channel_cnt, channel_list);
8872 return qdf_status_to_os_return(qdf_status);
8873}
8874
8875/**
8876 * wlan_hdd_cfg80211_update_vendor_channel() - update vendor channel
8877 * @wiphy: Pointer to wireless phy
8878 * @wdev: Pointer to wireless device
8879 * @data: Pointer to data
8880 * @data_len: Length of @data
8881 *
8882 * Return: 0 on success, negative errno on failure
8883 */
8884static int wlan_hdd_cfg80211_update_vendor_channel(struct wiphy *wiphy,
8885 struct wireless_dev *wdev,
8886 const void *data, int data_len)
8887{
8888 int ret;
8889
8890 cds_ssr_protect(__func__);
8891 ret = __wlan_hdd_cfg80211_update_vendor_channel(wiphy, wdev, data,
8892 data_len);
8893 cds_ssr_protect(__func__);
8894
8895 return ret;
8896}
Kapil Gupta94ca6f62016-12-11 18:43:12 +05308897
8898/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308899 * wlan_hdd_cfg80211_setband() - Wrapper to setband
8900 * @wiphy: wiphy structure pointer
8901 * @wdev: Wireless device structure pointer
8902 * @data: Pointer to the data received
8903 * @data_len: Length of @data
8904 *
8905 * Return: 0 on success; errno on failure
8906 */
8907static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
8908 struct wireless_dev *wdev,
8909 const void *data, int data_len)
8910{
8911 int ret;
8912
8913 cds_ssr_protect(__func__);
8914 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
8915 cds_ssr_unprotect(__func__);
8916
8917 return ret;
8918}
8919
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08008920/**
8921 * wlan_hdd_cfg80211_sar_convert_limit_set() - Convert limit set value
8922 * @nl80211_value: Vendor command attribute value
8923 * @wmi_value: Pointer to return converted WMI return value
8924 *
8925 * Convert NL80211 vendor command value for SAR limit set to WMI value
8926 * Return: 0 on success, -1 on invalid value
8927 */
8928static int wlan_hdd_cfg80211_sar_convert_limit_set(u32 nl80211_value,
8929 u32 *wmi_value)
8930{
8931 int ret = 0;
8932
8933 switch (nl80211_value) {
8934 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE:
8935 *wmi_value = WMI_SAR_FEATURE_OFF;
8936 break;
8937 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0:
8938 *wmi_value = WMI_SAR_FEATURE_ON_SET_0;
8939 break;
8940 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1:
8941 *wmi_value = WMI_SAR_FEATURE_ON_SET_1;
8942 break;
8943 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2:
8944 *wmi_value = WMI_SAR_FEATURE_ON_SET_2;
8945 break;
8946 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3:
8947 *wmi_value = WMI_SAR_FEATURE_ON_SET_3;
8948 break;
8949 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4:
8950 *wmi_value = WMI_SAR_FEATURE_ON_SET_4;
8951 break;
8952 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER:
8953 *wmi_value = WMI_SAR_FEATURE_ON_USER_DEFINED;
8954 break;
8955 default:
8956 ret = -1;
8957 }
8958 return ret;
8959}
8960
8961/**
8962 * wlan_hdd_cfg80211_sar_convert_band() - Convert WLAN band value
8963 * @nl80211_value: Vendor command attribute value
8964 * @wmi_value: Pointer to return converted WMI return value
8965 *
8966 * Convert NL80211 vendor command value for SAR BAND to WMI value
8967 * Return: 0 on success, -1 on invalid value
8968 */
8969static int wlan_hdd_cfg80211_sar_convert_band(u32 nl80211_value, u32 *wmi_value)
8970{
8971 int ret = 0;
8972
8973 switch (nl80211_value) {
8974 case NL80211_BAND_2GHZ:
8975 *wmi_value = WMI_SAR_2G_ID;
8976 break;
8977 case NL80211_BAND_5GHZ:
8978 *wmi_value = WMI_SAR_5G_ID;
8979 break;
8980 default:
8981 ret = -1;
8982 }
8983 return ret;
8984}
8985
8986/**
8987 * wlan_hdd_cfg80211_sar_convert_modulation() - Convert WLAN modulation value
8988 * @nl80211_value: Vendor command attribute value
8989 * @wmi_value: Pointer to return converted WMI return value
8990 *
8991 * Convert NL80211 vendor command value for SAR Modulation to WMI value
8992 * Return: 0 on success, -1 on invalid value
8993 */
8994static int wlan_hdd_cfg80211_sar_convert_modulation(u32 nl80211_value,
8995 u32 *wmi_value)
8996{
8997 int ret = 0;
8998
8999 switch (nl80211_value) {
9000 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK:
9001 *wmi_value = WMI_SAR_MOD_CCK;
9002 break;
9003 case QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM:
9004 *wmi_value = WMI_SAR_MOD_OFDM;
9005 break;
9006 default:
9007 ret = -1;
9008 }
9009 return ret;
9010}
9011
9012
9013/**
9014 * __wlan_hdd_set_sar_power_limits() - Set SAR power limits
9015 * @wiphy: Pointer to wireless phy
9016 * @wdev: Pointer to wireless device
9017 * @data: Pointer to data
9018 * @data_len: Length of @data
9019 *
9020 * This function is used to setup Specific Absorption Rate limit specs.
9021 *
9022 * Return: 0 on success, negative errno on failure
9023 */
9024static int __wlan_hdd_set_sar_power_limits(struct wiphy *wiphy,
9025 struct wireless_dev *wdev,
9026 const void *data, int data_len)
9027{
9028 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9029 struct nlattr *sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9030 *tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX + 1],
9031 *sar_spec_list;
9032 struct sar_limit_cmd_params sar_limit_cmd = {0};
9033 int ret = -EINVAL, i = 0, rem = 0;
9034
9035 ENTER();
9036
9037 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9038 hdd_err("Command not allowed in FTM mode");
9039 return -EPERM;
9040 }
9041
9042 if (wlan_hdd_validate_context(hdd_ctx))
9043 return -EINVAL;
9044
9045 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9046 data, data_len, NULL)) {
9047 hdd_err("Invalid SAR attributes");
9048 return -EINVAL;
9049 }
9050
9051 /* Vendor command manadates all SAR Specs in single call */
9052 sar_limit_cmd.commit_limits = 1;
9053 sar_limit_cmd.sar_enable = WMI_SAR_FEATURE_NO_CHANGE;
9054 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]) {
9055 if (wlan_hdd_cfg80211_sar_convert_limit_set(nla_get_u32(
9056 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE]),
9057 &sar_limit_cmd.sar_enable) < 0) {
9058 hdd_err("Invalid SAR Enable attr");
9059 goto fail;
9060 }
9061 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009062 hdd_debug("attr sar sar_enable %d", sar_limit_cmd.sar_enable);
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009063
9064 if (tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]) {
9065 sar_limit_cmd.num_limit_rows = nla_get_u32(
9066 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009067 hdd_debug("attr sar num_limit_rows %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009068 sar_limit_cmd.num_limit_rows);
9069 }
9070 if (sar_limit_cmd.num_limit_rows > MAX_SAR_LIMIT_ROWS_SUPPORTED) {
9071 hdd_err("SAR Spec list exceed supported size");
9072 goto fail;
9073 }
9074 if (sar_limit_cmd.num_limit_rows == 0)
9075 goto send_sar_limits;
9076 sar_limit_cmd.sar_limit_row_list = qdf_mem_malloc(sizeof(
9077 struct sar_limit_cmd_row) *
9078 sar_limit_cmd.num_limit_rows);
9079 if (!sar_limit_cmd.sar_limit_row_list) {
9080 ret = -ENOMEM;
9081 goto fail;
9082 }
9083 if (!tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC]) {
9084 hdd_err("Invalid SAR SPECs list");
9085 goto fail;
9086 }
9087
9088 nla_for_each_nested(sar_spec_list,
9089 tb[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC], rem) {
9090 if (i == sar_limit_cmd.num_limit_rows) {
9091 hdd_warn("SAR Cmd has excess SPECs in list");
9092 break;
9093 }
9094
9095 if (nla_parse(sar_spec, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX,
9096 nla_data(sar_spec_list), nla_len(sar_spec_list),
9097 NULL)) {
9098 hdd_err("nla_parse failed for SAR Spec list");
9099 goto fail;
9100 }
9101 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap = 0;
9102 if (sar_spec[
9103 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]) {
9104 sar_limit_cmd.sar_limit_row_list[i].limit_value =
9105 nla_get_u32(sar_spec[
9106 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT]);
9107 } else {
9108 hdd_err("SAR Spec does not have power limit value");
9109 goto fail;
9110 }
9111
9112 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]) {
9113 if (wlan_hdd_cfg80211_sar_convert_band(nla_get_u32(
9114 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND]),
9115 &sar_limit_cmd.sar_limit_row_list[i].band_id)
9116 < 0) {
9117 hdd_err("Invalid SAR Band attr");
9118 goto fail;
9119 }
9120 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9121 WMI_SAR_BAND_ID_VALID_MASK;
9122 }
9123 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]) {
9124 sar_limit_cmd.sar_limit_row_list[i].chain_id =
9125 nla_get_u32(sar_spec[
9126 QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN]);
9127 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9128 WMI_SAR_CHAIN_ID_VALID_MASK;
9129 }
9130 if (sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]) {
9131 if (wlan_hdd_cfg80211_sar_convert_modulation(nla_get_u32(
9132 sar_spec[QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION]),
9133 &sar_limit_cmd.sar_limit_row_list[i].mod_id)
9134 < 0) {
9135 hdd_err("Invalid SAR Modulation attr");
9136 goto fail;
9137 }
9138 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap |=
9139 WMI_SAR_MOD_ID_VALID_MASK;
9140 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009141 hdd_debug("Spec_ID: %d, Band: %d Chain: %d Mod: %d POW_Limit: %d Validity_Bitmap: %d",
Kabilan Kannan3c0a7352016-12-02 18:49:38 -08009142 i, sar_limit_cmd.sar_limit_row_list[i].band_id,
9143 sar_limit_cmd.sar_limit_row_list[i].chain_id,
9144 sar_limit_cmd.sar_limit_row_list[i].mod_id,
9145 sar_limit_cmd.sar_limit_row_list[i].limit_value,
9146 sar_limit_cmd.sar_limit_row_list[i].validity_bitmap);
9147 i++;
9148 }
9149
9150 if (i < sar_limit_cmd.num_limit_rows) {
9151 hdd_warn("SAR Cmd has less SPECs in list");
9152 sar_limit_cmd.num_limit_rows = i;
9153 }
9154
9155send_sar_limits:
9156 if (sme_set_sar_power_limits(hdd_ctx->hHal, &sar_limit_cmd) ==
9157 QDF_STATUS_SUCCESS)
9158 ret = 0;
9159fail:
9160 qdf_mem_free(sar_limit_cmd.sar_limit_row_list);
9161 return ret;
9162}
9163
9164/**
9165 * wlan_hdd_cfg80211_set_sar_power_limits() - Set SAR power limits
9166 * @wiphy: Pointer to wireless phy
9167 * @wdev: Pointer to wireless device
9168 * @data: Pointer to data
9169 * @data_len: Length of @data
9170 *
9171 * Wrapper function of __wlan_hdd_cfg80211_set_sar_power_limits()
9172 *
9173 * Return: 0 on success, negative errno on failure
9174 */
9175static int wlan_hdd_cfg80211_set_sar_power_limits(struct wiphy *wiphy,
9176 struct wireless_dev *wdev,
9177 const void *data,
9178 int data_len)
9179{
9180 int ret;
9181
9182 cds_ssr_protect(__func__);
9183 ret = __wlan_hdd_set_sar_power_limits(wiphy, wdev, data,
9184 data_len);
9185 cds_ssr_unprotect(__func__);
9186
9187 return ret;
9188}
9189
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309190static const struct
9191nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
9192 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
9193 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
9194 .len = QDF_MAC_ADDR_SIZE},
9195};
9196
9197/**
9198 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9199 * @wiphy: Pointer to wireless phy
9200 * @wdev: Pointer to wireless device
9201 * @data: Pointer to data
9202 * @data_len: Length of @data
9203 *
9204 * This function is used to enable/disable roaming using vendor commands
9205 *
9206 * Return: 0 on success, negative errno on failure
9207 */
9208static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9209 struct wireless_dev *wdev,
9210 const void *data, int data_len)
9211{
9212 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9213 struct net_device *dev = wdev->netdev;
9214 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
9215 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
9216 uint32_t is_fast_roam_enabled;
9217 int ret;
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309218 QDF_STATUS qdf_status;
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309219
9220 ENTER_DEV(dev);
9221
9222 ret = wlan_hdd_validate_context(hdd_ctx);
9223 if (0 != ret)
9224 return ret;
9225
9226 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
9227 hdd_err("Command not allowed in FTM mode");
9228 return -EINVAL;
9229 }
9230
9231 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
9232 qca_wlan_vendor_attr);
9233 if (ret) {
9234 hdd_err("Invalid ATTR");
9235 return -EINVAL;
9236 }
9237
9238 /* Parse and fetch Enable flag */
9239 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
9240 hdd_err("attr enable failed");
9241 return -EINVAL;
9242 }
9243
9244 is_fast_roam_enabled = nla_get_u32(
9245 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
Srinivas Girigowda13d39252017-03-06 16:12:15 -08009246 hdd_debug("isFastRoamEnabled %d fast_roaming_allowed %d",
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009247 is_fast_roam_enabled, adapter->fast_roaming_allowed);
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309248
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009249 if (!adapter->fast_roaming_allowed) {
9250 hdd_err("fast roaming not allowed on %s interface",
9251 adapter->dev->name);
9252 return -EINVAL;
9253 }
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309254 /* Update roaming */
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309255 qdf_status = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
Deepak Dhamdherea2785822016-11-17 01:17:45 -08009256 (is_fast_roam_enabled &&
9257 adapter->fast_roaming_allowed));
Selvaraj, Sridhard753e7c2017-01-12 20:19:27 +05309258 if (qdf_status != QDF_STATUS_SUCCESS)
9259 hdd_err("sme_config_fast_roaming failed with status=%d",
9260 qdf_status);
9261 ret = qdf_status_to_os_return(qdf_status);
9262
Mukul Sharma69c44cd2016-09-12 18:33:57 +05309263 EXIT();
9264 return ret;
9265}
9266
9267/**
9268 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
9269 * @wiphy: Pointer to wireless phy
9270 * @wdev: Pointer to wireless device
9271 * @data: Pointer to data
9272 * @data_len: Length of @data
9273 *
9274 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
9275 *
9276 * Return: 0 on success, negative errno on failure
9277 */
9278static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
9279 struct wireless_dev *wdev,
9280 const void *data, int data_len)
9281{
9282 int ret;
9283
9284 cds_ssr_protect(__func__);
9285 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
9286 cds_ssr_unprotect(__func__);
9287
9288 return ret;
9289}
9290
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309291static const struct nla_policy qca_wlan_vendor_set_trace_level_policy[
9292 QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1] = {
9293 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM] = {.type = NLA_NESTED },
9294 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID] = {.type = NLA_U32 },
9295 [QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK] = {.type = NLA_U32 },
9296};
9297
9298/**
9299 * __wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9300 * @wiphy: Pointer to wireless phy
9301 * @wdev: Pointer to wireless device
9302 * @data: Pointer to data
9303 * @data_len: Length of @data
9304 *
9305 * Return: 0 on success, negative errno on failure
9306 */
9307static int
9308__wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9309 struct wireless_dev *wdev,
9310 const void *data,
9311 int data_len)
9312{
9313 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
9314 struct nlattr *tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9315 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX + 1];
9316 struct nlattr *apth;
9317 int rem;
9318 int ret = 1;
9319 int print_idx = -1;
9320 int module_id = -1;
9321 int bit_mask = -1;
9322 int status;
9323
9324 ENTER();
9325
9326 if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
9327 hdd_err("Command not allowed in FTM mode");
9328 return -EINVAL;
9329 }
9330
9331 ret = wlan_hdd_validate_context(hdd_ctx);
9332 if (ret != 0)
9333 return -EINVAL;
9334
9335 print_idx = qdf_get_pidx();
9336 if (print_idx < 0 || print_idx >= MAX_PRINT_CONFIG_SUPPORTED) {
9337 hdd_err("Invalid print controle object index");
9338 return -EINVAL;
9339 }
9340
9341 if (nla_parse(tb1, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX, data,
9342 data_len, qca_wlan_vendor_set_trace_level_policy)) {
9343 hdd_err("Invalid attr");
9344 return -EINVAL;
9345 }
9346
9347 if (!tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM]) {
9348 hdd_err("attr trace level param failed");
9349 return -EINVAL;
9350 }
9351
9352 nla_for_each_nested(apth,
9353 tb1[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_PARAM], rem) {
9354 if (nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MAX,
9355 nla_data(apth), nla_len(apth), NULL)) {
9356 hdd_err("Invalid attr");
9357 return -EINVAL;
9358 }
9359
9360 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]) {
9361 hdd_err("attr Module ID failed");
9362 return -EINVAL;
9363 }
9364 module_id = nla_get_u32
9365 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_MODULE_ID]);
9366
9367 if (!tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]) {
9368 hdd_err("attr Verbose mask failed");
9369 return -EINVAL;
9370 }
9371 bit_mask = nla_get_u32
9372 (tb2[QCA_WLAN_VENDOR_ATTR_SET_TRACE_LEVEL_TRACE_MASK]);
9373
9374 status = hdd_qdf_trace_enable(module_id, bit_mask);
9375
9376 if (status != 0)
9377 hdd_err("can not set verbose mask %d for the category %d",
9378 bit_mask, module_id);
9379 }
9380
9381 EXIT();
9382 return ret;
9383}
9384
9385/**
Ashish Kumar Dhanotiyaeb4fe4b2017-02-20 16:04:00 +05309386 * wlan_hdd_cfg80211_set_trace_level() - Set the trace level
9387 * @wiphy: Pointer to wireless phy
9388 * @wdev: Pointer to wireless device
9389 * @data: Pointer to data
9390 * @data_len: Length of @data
9391 *
9392 * Wrapper function of __wlan_hdd_cfg80211_set_trace_level()
9393 *
9394 * Return: 0 on success, negative errno on failure
9395 */
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +05309396
9397static int wlan_hdd_cfg80211_set_trace_level(struct wiphy *wiphy,
9398 struct wireless_dev *wdev,
9399 const void *data,
9400 int data_len)
9401{
9402 int ret;
9403
9404 cds_ssr_protect(__func__);
9405 ret = __wlan_hdd_cfg80211_set_trace_level(wiphy, wdev, data, data_len);
9406 cds_ssr_unprotect(__func__);
9407
9408 return ret;
9409}
9410
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009411const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
9412 {
9413 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9414 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
9415 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05309416 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009417 .doit = is_driver_dfs_capable
9418 },
9419
9420#ifdef WLAN_FEATURE_NAN
9421 {
9422 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9423 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
9424 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9425 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9426 .doit = wlan_hdd_cfg80211_nan_request
9427 },
9428#endif
9429
9430#ifdef WLAN_FEATURE_STATS_EXT
9431 {
9432 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9433 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
9434 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9435 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9436 .doit = wlan_hdd_cfg80211_stats_ext_request
9437 },
9438#endif
9439#ifdef FEATURE_WLAN_EXTSCAN
9440 {
9441 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9442 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
9443 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9444 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9445 .doit = wlan_hdd_cfg80211_extscan_start
9446 },
9447 {
9448 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9449 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
9450 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9451 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9452 .doit = wlan_hdd_cfg80211_extscan_stop
9453 },
9454 {
9455 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9456 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
9457 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9458 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
9459 },
9460 {
9461 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9462 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
9463 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9464 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9465 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
9466 },
9467 {
9468 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9469 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
9470 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9471 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9472 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
9473 },
9474 {
9475 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9476 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
9477 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9478 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9479 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
9480 },
9481 {
9482 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9483 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
9484 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9485 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9486 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
9487 },
9488 {
9489 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9490 .info.subcmd =
9491 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
9492 .flags =
9493 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9494 WIPHY_VENDOR_CMD_NEED_RUNNING,
9495 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
9496 },
9497 {
9498 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9499 .info.subcmd =
9500 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
9501 .flags =
9502 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
9503 WIPHY_VENDOR_CMD_NEED_RUNNING,
9504 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
9505 },
9506 {
9507 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9508 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
9509 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9510 WIPHY_VENDOR_CMD_NEED_NETDEV |
9511 WIPHY_VENDOR_CMD_NEED_RUNNING,
9512 .doit = wlan_hdd_cfg80211_set_epno_list
9513 },
9514#endif /* FEATURE_WLAN_EXTSCAN */
9515
9516#ifdef WLAN_FEATURE_LINK_LAYER_STATS
9517 {
9518 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9519 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
9520 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9521 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9522 .doit = wlan_hdd_cfg80211_ll_stats_clear
9523 },
9524
9525 {
9526 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9527 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
9528 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9529 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9530 .doit = wlan_hdd_cfg80211_ll_stats_set
9531 },
9532
9533 {
9534 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9535 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
9536 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9537 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9538 .doit = wlan_hdd_cfg80211_ll_stats_get
9539 },
9540#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
9541#ifdef FEATURE_WLAN_TDLS
9542 {
9543 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9544 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
9545 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9546 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9547 .doit = wlan_hdd_cfg80211_exttdls_enable
9548 },
9549 {
9550 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9551 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
9552 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9553 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
9554 .doit = wlan_hdd_cfg80211_exttdls_disable
9555 },
9556 {
9557 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9558 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
9559 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9560 .doit = wlan_hdd_cfg80211_exttdls_get_status
9561 },
9562#endif
9563 {
9564 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9565 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
9566 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9567 .doit = wlan_hdd_cfg80211_get_supported_features
9568 },
9569 {
9570 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9571 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
9572 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
9573 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
9574 },
9575 {
9576 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9577 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
9578 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05309579 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009580 },
9581 {
9582 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9583 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
9584 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9585 WIPHY_VENDOR_CMD_NEED_NETDEV,
9586 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
9587 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07009588 {
9589 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9590 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
9591 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9592 WIPHY_VENDOR_CMD_NEED_NETDEV,
9593 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
9594 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009595 {
9596 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05309597 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
9598 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9599 WIPHY_VENDOR_CMD_NEED_NETDEV |
9600 WIPHY_VENDOR_CMD_NEED_RUNNING,
9601 .doit = hdd_cfg80211_get_station_cmd
9602 },
9603 {
9604 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009605 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
9606 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9607 WIPHY_VENDOR_CMD_NEED_NETDEV |
9608 WIPHY_VENDOR_CMD_NEED_RUNNING,
9609 .doit = wlan_hdd_cfg80211_do_acs
9610 },
9611
9612 {
9613 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9614 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
9615 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9616 WIPHY_VENDOR_CMD_NEED_NETDEV,
9617 .doit = wlan_hdd_cfg80211_get_features
9618 },
9619#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9620 {
9621 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9622 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
9623 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9624 WIPHY_VENDOR_CMD_NEED_NETDEV |
9625 WIPHY_VENDOR_CMD_NEED_RUNNING,
9626 .doit = wlan_hdd_cfg80211_keymgmt_set_key
9627 },
9628#endif
9629#ifdef FEATURE_WLAN_EXTSCAN
9630 {
9631 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9632 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
9633 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9634 WIPHY_VENDOR_CMD_NEED_NETDEV |
9635 WIPHY_VENDOR_CMD_NEED_RUNNING,
9636 .doit = wlan_hdd_cfg80211_set_passpoint_list
9637 },
9638 {
9639 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9640 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
9641 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9642 WIPHY_VENDOR_CMD_NEED_NETDEV |
9643 WIPHY_VENDOR_CMD_NEED_RUNNING,
9644 .doit = wlan_hdd_cfg80211_reset_passpoint_list
9645 },
9646 {
9647 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9648 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
9649 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9650 WIPHY_VENDOR_CMD_NEED_NETDEV |
9651 WIPHY_VENDOR_CMD_NEED_RUNNING,
9652 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
9653 },
9654 {
9655 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9656 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
9657 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9658 WIPHY_VENDOR_CMD_NEED_NETDEV |
9659 WIPHY_VENDOR_CMD_NEED_RUNNING,
9660 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
9661 },
9662#endif /* FEATURE_WLAN_EXTSCAN */
9663 {
9664 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9665 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
9666 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9667 WIPHY_VENDOR_CMD_NEED_NETDEV,
9668 .doit = wlan_hdd_cfg80211_get_wifi_info
9669 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009670#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009671 {
9672 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9673 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
9674 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9675 WIPHY_VENDOR_CMD_NEED_NETDEV |
9676 WIPHY_VENDOR_CMD_NEED_RUNNING,
9677 .doit = wlan_hdd_cfg80211_wifi_configuration_set
9678 },
Paul Zhang3a210c52016-12-08 10:18:12 +08009679#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009680 {
9681 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9682 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
9683 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9684 WIPHY_VENDOR_CMD_NEED_NETDEV,
9685 .doit = wlan_hdd_cfg80211_set_ext_roam_params
9686 },
9687 {
9688 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9689 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
9690 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9691 WIPHY_VENDOR_CMD_NEED_NETDEV,
9692 .doit = wlan_hdd_cfg80211_wifi_logger_start
9693 },
9694 {
9695 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9696 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
9697 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9698 WIPHY_VENDOR_CMD_NEED_NETDEV,
9699 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
9700 },
9701 {
9702 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9703 .info.subcmd =
9704 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
9705 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9706 WIPHY_VENDOR_CMD_NEED_NETDEV |
9707 WIPHY_VENDOR_CMD_NEED_RUNNING,
9708 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
9709 },
9710 {
9711 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9712 .info.subcmd =
9713 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
9714 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9715 WIPHY_VENDOR_CMD_NEED_NETDEV |
9716 WIPHY_VENDOR_CMD_NEED_RUNNING,
9717 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
9718 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07009719#ifdef WLAN_FEATURE_TSF
9720 {
9721 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9722 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
9723 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9724 WIPHY_VENDOR_CMD_NEED_NETDEV |
9725 WIPHY_VENDOR_CMD_NEED_RUNNING,
9726 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
9727 },
9728#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009729#ifdef FEATURE_WLAN_TDLS
9730 {
9731 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9732 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
9733 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9734 WIPHY_VENDOR_CMD_NEED_NETDEV |
9735 WIPHY_VENDOR_CMD_NEED_RUNNING,
9736 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
9737 },
9738#endif
9739#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
9740 {
9741 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9742 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
9743 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9744 WIPHY_VENDOR_CMD_NEED_NETDEV |
9745 WIPHY_VENDOR_CMD_NEED_RUNNING,
9746 .doit = wlan_hdd_cfg80211_offloaded_packets
9747 },
9748#endif
9749 {
9750 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9751 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
9752 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9753 WIPHY_VENDOR_CMD_NEED_NETDEV |
9754 WIPHY_VENDOR_CMD_NEED_RUNNING,
9755 .doit = wlan_hdd_cfg80211_monitor_rssi
9756 },
9757 {
9758 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05309759 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
9760 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9761 WIPHY_VENDOR_CMD_NEED_NETDEV |
9762 WIPHY_VENDOR_CMD_NEED_RUNNING,
9763 .doit = wlan_hdd_cfg80211_set_ns_offload
9764 },
9765 {
9766 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009767 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
9768 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9769 WIPHY_VENDOR_CMD_NEED_NETDEV |
9770 WIPHY_VENDOR_CMD_NEED_RUNNING,
9771 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
9772 },
9773#ifdef WLAN_FEATURE_MEMDUMP
9774 {
9775 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9776 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
9777 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9778 WIPHY_VENDOR_CMD_NEED_NETDEV |
9779 WIPHY_VENDOR_CMD_NEED_RUNNING,
9780 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
9781 },
9782#endif /* WLAN_FEATURE_MEMDUMP */
9783 {
9784 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9785 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
9786 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9787 WIPHY_VENDOR_CMD_NEED_NETDEV |
9788 WIPHY_VENDOR_CMD_NEED_RUNNING,
9789 .doit = wlan_hdd_cfg80211_vendor_scan
9790 },
9791
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +05309792 /* Vendor abort scan */
9793 {
9794 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9795 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN,
9796 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9797 WIPHY_VENDOR_CMD_NEED_NETDEV |
9798 WIPHY_VENDOR_CMD_NEED_RUNNING,
9799 .doit = wlan_hdd_vendor_abort_scan
9800 },
9801
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009802 /* OCB commands */
9803 {
9804 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9805 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
9806 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9807 WIPHY_VENDOR_CMD_NEED_NETDEV |
9808 WIPHY_VENDOR_CMD_NEED_RUNNING,
9809 .doit = wlan_hdd_cfg80211_ocb_set_config
9810 },
9811 {
9812 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9813 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
9814 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9815 WIPHY_VENDOR_CMD_NEED_NETDEV |
9816 WIPHY_VENDOR_CMD_NEED_RUNNING,
9817 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
9818 },
9819 {
9820 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9821 .info.subcmd =
9822 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
9823 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9824 WIPHY_VENDOR_CMD_NEED_NETDEV |
9825 WIPHY_VENDOR_CMD_NEED_RUNNING,
9826 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
9827 },
9828 {
9829 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9830 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
9831 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9832 WIPHY_VENDOR_CMD_NEED_NETDEV |
9833 WIPHY_VENDOR_CMD_NEED_RUNNING,
9834 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
9835 },
9836 {
9837 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9838 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
9839 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9840 WIPHY_VENDOR_CMD_NEED_NETDEV |
9841 WIPHY_VENDOR_CMD_NEED_RUNNING,
9842 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
9843 },
9844 {
9845 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9846 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
9847 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9848 WIPHY_VENDOR_CMD_NEED_NETDEV |
9849 WIPHY_VENDOR_CMD_NEED_RUNNING,
9850 .doit = wlan_hdd_cfg80211_dcc_get_stats
9851 },
9852 {
9853 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9854 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
9855 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9856 WIPHY_VENDOR_CMD_NEED_NETDEV |
9857 WIPHY_VENDOR_CMD_NEED_RUNNING,
9858 .doit = wlan_hdd_cfg80211_dcc_clear_stats
9859 },
9860 {
9861 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9862 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
9863 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9864 WIPHY_VENDOR_CMD_NEED_NETDEV |
9865 WIPHY_VENDOR_CMD_NEED_RUNNING,
9866 .doit = wlan_hdd_cfg80211_dcc_update_ndl
9867 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05309868 {
9869 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9870 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
9871 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9872 WIPHY_VENDOR_CMD_NEED_NETDEV |
9873 WIPHY_VENDOR_CMD_NEED_RUNNING,
9874 .doit = wlan_hdd_cfg80211_get_link_properties
9875 },
Peng Xu278d0122015-09-24 16:34:17 -07009876 {
Peng Xud2220962016-07-11 17:59:17 -07009877 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07009878 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
9879 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9880 WIPHY_VENDOR_CMD_NEED_NETDEV |
9881 WIPHY_VENDOR_CMD_NEED_RUNNING,
9882 .doit = wlan_hdd_cfg80211_set_ota_test
9883 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08009884#ifdef FEATURE_LFR_SUBNET_DETECTION
9885 {
9886 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9887 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
9888 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9889 WIPHY_VENDOR_CMD_NEED_NETDEV |
9890 WIPHY_VENDOR_CMD_NEED_RUNNING,
9891 .doit = wlan_hdd_cfg80211_set_gateway_params
9892 },
9893#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07009894 {
Peng Xud2220962016-07-11 17:59:17 -07009895 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07009896 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
9897 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9898 WIPHY_VENDOR_CMD_NEED_NETDEV |
9899 WIPHY_VENDOR_CMD_NEED_RUNNING,
9900 .doit = wlan_hdd_cfg80211_txpower_scale
9901 },
9902 {
9903 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9904 .info.subcmd =
9905 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
9906 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9907 WIPHY_VENDOR_CMD_NEED_NETDEV |
9908 WIPHY_VENDOR_CMD_NEED_RUNNING,
9909 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
9910 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05309911 {
9912 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9913 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
9914 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9915 WIPHY_VENDOR_CMD_NEED_NETDEV |
9916 WIPHY_VENDOR_CMD_NEED_RUNNING,
9917 .doit = wlan_hdd_cfg80211_bpf_offload
9918 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309919 {
9920 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05309921 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
9922 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9923 WIPHY_VENDOR_CMD_NEED_NETDEV |
9924 WIPHY_VENDOR_CMD_NEED_RUNNING,
9925 .doit = wlan_hdd_cfg80211_acs_dfs_mode
9926 },
9927 {
9928 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309929 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
9930 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9931 WIPHY_VENDOR_CMD_NEED_NETDEV |
9932 WIPHY_VENDOR_CMD_NEED_RUNNING,
9933 .doit = wlan_hdd_cfg80211_sta_roam_policy
9934 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05309935#ifdef FEATURE_WLAN_CH_AVOID
9936 {
9937 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9938 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
9939 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9940 WIPHY_VENDOR_CMD_NEED_NETDEV |
9941 WIPHY_VENDOR_CMD_NEED_RUNNING,
9942 .doit = wlan_hdd_cfg80211_avoid_freq
9943 },
9944#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05309945 {
9946 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05309947 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
9948 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9949 WIPHY_VENDOR_CMD_NEED_NETDEV |
9950 WIPHY_VENDOR_CMD_NEED_RUNNING,
9951 .doit = wlan_hdd_cfg80211_sap_configuration_set
9952 },
Peng Xu8fdaa492016-06-22 10:20:47 -07009953 {
Peng Xu4225c152016-07-14 21:18:14 -07009954 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07009955 .info.subcmd =
9956 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
9957 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9958 WIPHY_VENDOR_CMD_NEED_NETDEV |
9959 WIPHY_VENDOR_CMD_NEED_RUNNING,
9960 .doit = wlan_hdd_cfg80211_p2p_lo_start
9961 },
9962 {
9963 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9964 .info.subcmd =
9965 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
9966 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9967 WIPHY_VENDOR_CMD_NEED_NETDEV |
9968 WIPHY_VENDOR_CMD_NEED_RUNNING,
9969 .doit = wlan_hdd_cfg80211_p2p_lo_stop
9970 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05309971 {
9972 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9973 .info.subcmd =
9974 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
9975 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9976 WIPHY_VENDOR_CMD_NEED_NETDEV |
9977 WIPHY_VENDOR_CMD_NEED_RUNNING,
9978 .doit = wlan_hdd_cfg80211_conditional_chan_switch
9979 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07009980#ifdef WLAN_FEATURE_NAN_DATAPATH
9981 {
9982 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9983 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
9984 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9985 WIPHY_VENDOR_CMD_NEED_NETDEV |
9986 WIPHY_VENDOR_CMD_NEED_RUNNING,
9987 .doit = wlan_hdd_cfg80211_process_ndp_cmd
9988 },
9989#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05309990 {
9991 .info.vendor_id = QCA_NL80211_VENDOR_ID,
9992 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
9993 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
9994 WIPHY_VENDOR_CMD_NEED_NETDEV |
9995 WIPHY_VENDOR_CMD_NEED_RUNNING,
9996 .doit = wlan_hdd_cfg80211_get_wakelock_stats
9997 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05309998 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05309999 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10000 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
10001 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10002 WIPHY_VENDOR_CMD_NEED_NETDEV |
10003 WIPHY_VENDOR_CMD_NEED_RUNNING,
10004 .doit = wlan_hdd_cfg80211_get_bus_size
10005 },
10006 {
Kapil Gupta8878ad92017-02-13 11:56:04 +053010007 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10008 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS,
10009 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10010 WIPHY_VENDOR_CMD_NEED_NETDEV |
10011 WIPHY_VENDOR_CMD_NEED_RUNNING,
10012 .doit = wlan_hdd_cfg80211_update_vendor_channel
10013 },
10014 {
bingsd09dea32017-03-17 10:08:26 +080010015 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Srinivas Dasari510e7fe2016-04-28 11:51:30 +053010016 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
10017 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10018 WIPHY_VENDOR_CMD_NEED_NETDEV |
10019 WIPHY_VENDOR_CMD_NEED_RUNNING,
10020 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +053010021 },
10022 {
10023 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10024 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
10025 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10026 WIPHY_VENDOR_CMD_NEED_NETDEV |
10027 WIPHY_VENDOR_CMD_NEED_RUNNING,
10028 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +053010029 },
10030#ifdef WLAN_FEATURE_DISA
10031 {
10032 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10033 .info.subcmd =
10034 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
10035 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10036 WIPHY_VENDOR_CMD_NEED_NETDEV |
10037 WIPHY_VENDOR_CMD_NEED_RUNNING,
10038 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
10039 },
10040#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010041#ifdef FEATURE_WLAN_TDLS
10042 {
10043 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10044 .info.subcmd =
10045 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
10046 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10047 WIPHY_VENDOR_CMD_NEED_NETDEV |
10048 WIPHY_VENDOR_CMD_NEED_RUNNING,
10049 .doit = wlan_hdd_cfg80211_configure_tdls_mode
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010050 },
Kabilan Kannand053aaf2016-10-26 02:06:14 -070010051#endif
Kabilan Kannan3c0a7352016-12-02 18:49:38 -080010052 {
10053 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10054 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS,
10055 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10056 WIPHY_VENDOR_CMD_NEED_RUNNING,
10057 .doit = wlan_hdd_cfg80211_set_sar_power_limits
10058 },
Ashish Kumar Dhanotiya53c2f692017-02-08 00:25:11 +053010059 {
10060 .info.vendor_id = QCA_NL80211_VENDOR_ID,
10061 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL,
10062 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
10063 WIPHY_VENDOR_CMD_NEED_NETDEV |
10064 WIPHY_VENDOR_CMD_NEED_RUNNING,
10065 .doit = wlan_hdd_cfg80211_set_trace_level
10066 },
10067
Paul Zhang3a210c52016-12-08 10:18:12 +080010068#ifdef WLAN_UMAC_CONVERGENCE
10069 COMMON_VENDOR_COMMANDS
10070#endif
Krishna Kumaar Natarajanf5676502017-03-06 10:28:44 -080010071 FEATURE_11AX_VENDOR_COMMANDS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010072};
10073
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010074#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
10075 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
10076 defined(FEATURE_WLAN_SCAN_PNO)
10077/**
10078 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
10079 * @wiphy: pointer to wiphy
10080 * @config: pointer to config
10081 *
10082 * Return: None
10083 */
10084static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10085 struct hdd_config *config)
10086{
10087 if (config->configPNOScanSupport) {
10088 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10089 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
10090 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
10091 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
10092 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
10093 if (config->max_sched_scan_plan_interval)
10094 wiphy->max_sched_scan_plan_interval =
10095 config->max_sched_scan_plan_interval;
10096 if (config->max_sched_scan_plan_iterations)
10097 wiphy->max_sched_scan_plan_iterations =
10098 config->max_sched_scan_plan_iterations;
10099 }
10100}
10101#else
10102static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
10103 struct hdd_config *config)
10104{
10105}
10106#endif
10107
10108
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010109/**
10110 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
10111 * @priv_size: Size of the hdd context.
10112 *
10113 * Allocate wiphy context and hdd context.
10114 *
10115 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010116 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010117hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010118{
10119 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010120 hdd_context_t *hdd_ctx;
10121
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010122 ENTER();
10123
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010124 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
10125
10126 if (!wiphy) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010127 hdd_err("wiphy init failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010128 return NULL;
10129 }
10130
Prashanth Bhattac2a16f62015-12-03 15:06:15 -080010131 hdd_ctx = wiphy_priv(wiphy);
10132
10133 hdd_ctx->wiphy = wiphy;
10134
10135 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010136}
10137
10138/*
10139 * FUNCTION: wlan_hdd_cfg80211_update_band
10140 * This function is called from the supplicant through a
10141 * private ioctl to change the band value
10142 */
10143int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
10144{
10145 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -070010146 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010147
10148 ENTER();
10149
Dustin Browna30892e2016-10-12 17:28:36 -070010150 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010151
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010152 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010153 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010154
10155 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10156 struct ieee80211_supported_band *band = wiphy->bands[i];
10157
10158 channelEnabledState =
10159 cds_get_channel_state(band->channels[j].
10160 hw_value);
10161
Dustin Browna30892e2016-10-12 17:28:36 -070010162 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010163 /* 5G only */
10164#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10165 /* Enable Social channels for P2P */
10166 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10167 (band->channels[j].center_freq)
10168 && CHANNEL_STATE_ENABLE ==
10169 channelEnabledState)
10170 band->channels[j].flags &=
10171 ~IEEE80211_CHAN_DISABLED;
10172 else
10173#endif
10174 band->channels[j].flags |=
10175 IEEE80211_CHAN_DISABLED;
10176 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010177 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010178 eCSR_BAND_24 == eBand) {
10179 /* 2G only */
10180 band->channels[j].flags |=
10181 IEEE80211_CHAN_DISABLED;
10182 continue;
10183 }
10184
Amar Singhal6842e8f2016-02-23 16:30:32 -080010185 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010186 band->channels[j].flags &=
10187 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010188 }
10189 }
10190 return 0;
10191}
10192
Peng Xuacfdda12017-02-06 16:15:38 -080010193#define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010194/*
10195 * FUNCTION: wlan_hdd_cfg80211_init
10196 * This function is called by hdd_wlan_startup()
10197 * during initialization.
10198 * This function is used to initialize and register wiphy structure.
10199 */
10200int wlan_hdd_cfg80211_init(struct device *dev,
10201 struct wiphy *wiphy, struct hdd_config *pCfg)
10202{
10203 int i, j;
10204 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10205
10206 ENTER();
10207
10208 /* Now bind the underlying wlan device with wiphy */
10209 set_wiphy_dev(wiphy, dev);
10210
10211 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
10212
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010213#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
10214 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010215 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010216#else
10217 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -070010218 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010219#endif
10220
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010221 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
10222 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
10223 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
10224#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
10225 | WIPHY_FLAG_4ADDR_STATION
10226#endif
10227 | WIPHY_FLAG_OFFCHAN_TX;
10228
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010229#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10230 wiphy->wowlan = &wowlan_support_cfg80211_init;
10231#else
10232 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
10233 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
10234 wiphy->wowlan.pattern_min_len = 1;
10235 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
10236#endif
10237
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -070010238 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010239#ifdef FEATURE_WLAN_ESE
10240 || pCfg->isEseIniFeatureEnabled
10241#endif
10242 ) {
10243 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10244 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010245#ifdef FEATURE_WLAN_TDLS
10246 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
10247 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
10248#endif
10249
10250 wiphy->features |= NL80211_FEATURE_HT_IBSS;
10251
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010252#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
10253 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
10254#endif
10255
Anurag Chouhan7c01cc42016-12-16 21:33:43 +053010256 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010257
10258#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +053010259 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010260#endif
10261
10262 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010263 * driver can still register regulatory callback and
10264 * it will get regulatory settings in wiphy->band[], but
10265 * driver need to determine what to do with both
10266 * regulatory settings
10267 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010268
10269 wiphy->reg_notifier = hdd_reg_notifier;
10270
10271#if defined QCA_WIFI_FTM
10272}
10273#endif
10274
10275 wiphy->max_scan_ssids = MAX_SCAN_SSID;
10276
10277 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
10278
10279 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
10280
Arun Khandavallifae92942016-08-01 13:31:08 +053010281 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
10282 | BIT(NL80211_IFTYPE_ADHOC)
10283 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10284 | BIT(NL80211_IFTYPE_P2P_GO)
10285 | BIT(NL80211_IFTYPE_AP)
10286 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010287
Arun Khandavallifae92942016-08-01 13:31:08 +053010288 if (pCfg->advertiseConcurrentOperation) {
10289 if (pCfg->enableMCC) {
10290 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010291
Arun Khandavallifae92942016-08-01 13:31:08 +053010292 for (i = 0;
10293 i < ARRAY_SIZE(wlan_hdd_iface_combination);
10294 i++) {
10295 if (!pCfg->allowMCCGODiffBI)
10296 wlan_hdd_iface_combination[i].
10297 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010298 }
10299 }
10300 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +053010301 ARRAY_SIZE(wlan_hdd_iface_combination);
10302 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010303 }
10304
10305 /* Before registering we need to update the ht capabilitied based
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010306 * on ini values
10307 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010308 if (!pCfg->ShortGI20MhzEnable) {
10309 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
10310 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010311 }
10312
10313 if (!pCfg->ShortGI40MhzEnable) {
10314 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
10315 }
10316
10317 if (!pCfg->nChannelBondingMode5GHz) {
10318 wlan_hdd_band_5_ghz.ht_cap.cap &=
10319 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10320 }
10321
Abhishek Singhf512bf32016-05-04 16:47:46 +053010322 /*
10323 * In case of static linked driver at the time of driver unload,
10324 * module exit doesn't happens. Module cleanup helps in cleaning
10325 * of static memory.
10326 * If driver load happens statically, at the time of driver unload,
10327 * wiphy flags don't get reset because of static memory.
10328 * It's better not to store channel in static memory.
10329 */
Dustin Browna30892e2016-10-12 17:28:36 -070010330 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
10331 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010332 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010333 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010334 hdd_err("Not enough memory to allocate channels");
10335 return -ENOMEM;
10336 }
Dustin Browna30892e2016-10-12 17:28:36 -070010337 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010338 &hdd_channels_2_4_ghz[0],
10339 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +053010340 if ((hdd_is_5g_supported(pHddCtx)) &&
10341 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
10342 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
10343 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
10344 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -070010345 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
10346 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +053010347 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -070010348 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010349 hdd_err("Not enough memory to allocate channels");
10350 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -070010351 bands[NL80211_BAND_2GHZ]->channels);
10352 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +053010353 return -ENOMEM;
10354 }
Dustin Browna30892e2016-10-12 17:28:36 -070010355 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +053010356 &hdd_channels_5_ghz[0],
10357 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010358 }
10359
Dustin Browna30892e2016-10-12 17:28:36 -070010360 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010361
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010362 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010363 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010364
10365 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
10366 struct ieee80211_supported_band *band = wiphy->bands[i];
10367
Dustin Browna30892e2016-10-12 17:28:36 -070010368 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010369 eCSR_BAND_5G == pCfg->nBandCapability) {
10370 /* 5G only */
10371#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
10372 /* Enable social channels for P2P */
10373 if (WLAN_HDD_IS_SOCIAL_CHANNEL
10374 (band->channels[j].center_freq))
10375 band->channels[j].flags &=
10376 ~IEEE80211_CHAN_DISABLED;
10377 else
10378#endif
10379 band->channels[j].flags |=
10380 IEEE80211_CHAN_DISABLED;
10381 continue;
Dustin Browna30892e2016-10-12 17:28:36 -070010382 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010383 eCSR_BAND_24 == pCfg->nBandCapability) {
10384 /* 2G only */
10385 band->channels[j].flags |=
10386 IEEE80211_CHAN_DISABLED;
10387 continue;
10388 }
10389 }
10390 }
10391 /*Initialise the supported cipher suite details */
10392 wiphy->cipher_suites = hdd_cipher_suites;
10393 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
10394
10395 /*signal strength in mBm (100*dBm) */
10396 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10397 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
10398
Anurag Chouhan6d760662016-02-20 16:05:43 +053010399 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010400 wiphy->n_vendor_commands =
10401 ARRAY_SIZE(hdd_wiphy_vendor_commands);
10402 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
10403
10404 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
10405 wiphy->n_vendor_events =
10406 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
10407 }
10408
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010409 if (pCfg->enableDFSMasterCap) {
10410 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
10411 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010412
10413 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
10414
10415#ifdef QCA_HT_2040_COEX
10416 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
10417#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +053010418 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wadesonga75734c2017-02-07 16:03:25 +080010419
10420#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) || \
10421 defined(CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT)
10422 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);
10423 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);
10424 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);
10425#endif
10426
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010427 hdd_add_channel_switch_support(&wiphy->flags);
Peng Xuacfdda12017-02-06 16:15:38 -080010428 wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053010429
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010430 EXIT();
10431 return 0;
10432}
10433
Abhishek Singhf512bf32016-05-04 16:47:46 +053010434/**
Yingying Tang80e15f32016-09-27 18:23:01 +080010435 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
10436 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +053010437 *
10438 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010439 * memory allocated in wlan_hdd_cfg80211_init also
10440 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +053010441 *
10442 * Return: void
10443 */
10444void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
10445{
10446 int i;
10447
Dustin Browna30892e2016-10-12 17:28:36 -070010448 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +053010449 if (NULL != wiphy->bands[i] &&
10450 (NULL != wiphy->bands[i]->channels)) {
10451 qdf_mem_free(wiphy->bands[i]->channels);
10452 wiphy->bands[i]->channels = NULL;
10453 }
10454 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +053010455 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +053010456}
10457
Yingying Tang80e15f32016-09-27 18:23:01 +080010458/**
10459 * wlan_hdd_update_band_cap() - update capabilities for supported bands
10460 * @hdd_ctx: HDD context
10461 *
10462 * this function will update capabilities for supported bands
10463 *
10464 * Return: void
10465 */
10466static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
10467{
10468 uint32_t val32;
10469 uint16_t val16;
10470 tSirMacHTCapabilityInfo *ht_cap_info;
10471 QDF_STATUS status;
10472
10473 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
10474 if (QDF_STATUS_SUCCESS != status) {
10475 hdd_err("could not get HT capability info");
10476 val32 = 0;
10477 }
10478 val16 = (uint16_t)val32;
10479 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
10480
10481 if (ht_cap_info->txSTBC == true) {
10482 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
10483 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
10484 IEEE80211_HT_CAP_TX_STBC;
10485 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
10486 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
10487 IEEE80211_HT_CAP_TX_STBC;
10488 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010489
10490 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
10491 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
10492 vht_cap.vht_supported = 0;
10493 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
10494 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
10495 vht_cap.vht_supported = 0;
10496 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
10497 }
Yingying Tang80e15f32016-09-27 18:23:01 +080010498}
10499
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010500/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010501 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010502 * initialization. In wlan_hdd_cfg80211_init, only the
10503 * default values will be initialized. The final initialization
10504 * of all required members can be done here.
10505 */
Yingying Tang80e15f32016-09-27 18:23:01 +080010506void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010507{
Yingying Tang80e15f32016-09-27 18:23:01 +080010508 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
10509
10510 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010511}
10512
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010513/**
10514 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
10515 * @cfg: hdd cfg
10516 *
10517 * this function update 11n mode in hdd cfg
10518 *
10519 * Return: void
10520 */
10521void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
10522{
10523 if (sme_is_feature_supported_by_fw(DOT11AC)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010524 hdd_debug("support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010525 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010526 hdd_debug("not support 11ac");
Yingying Tang3ba3dbc2016-09-27 16:36:58 +080010527 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
10528 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
10529 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
10530 cfg->sap_p2p_11ac_override = 0;
10531 }
10532 }
10533}
10534
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010535/* In this function we are registering wiphy. */
10536int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
10537{
10538 ENTER();
10539 /* Register our wiphy dev with cfg80211 */
10540 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010541 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010542 return -EIO;
10543 }
10544
10545 EXIT();
10546 return 0;
10547}
10548
10549/*
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010550 * HDD function to update wiphy capability based on target offload status.
10551 *
10552 * wlan_hdd_cfg80211_init() does initialization of all wiphy related
10553 * capability even before downloading firmware to the target. In discrete
10554 * case, host will get know certain offload capability (say sched_scan
10555 * caps) only after downloading firmware to the target and target boots up.
10556 * This function is used to override setting done in wlan_hdd_cfg80211_init()
10557 * based on target capability.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010558 */
10559void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
10560{
10561#ifdef FEATURE_WLAN_SCAN_PNO
10562 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
10563 struct hdd_config *pCfg = pHddCtx->config;
10564
10565 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
10566 * control comes here. Here just we need to clear it if firmware doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010567 * have PNO support.
10568 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010569 if (!pCfg->PnoOffload) {
10570 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10571 wiphy->max_sched_scan_ssids = 0;
10572 wiphy->max_match_sets = 0;
10573 wiphy->max_sched_scan_ie_len = 0;
10574 }
10575#endif
10576}
10577
10578/* This function registers for all frame which supplicant is interested in */
Wu Gao84d120c2017-03-24 18:46:00 +080010579#ifdef CONVERGED_P2P_ENABLE
10580void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10581{
10582 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10583 /* Register for all P2P action, public action etc frames */
10584 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10585
10586 ENTER();
10587
10588 /* Register frame indication call back */
10589 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10590
10591 /* Register for p2p ack indication */
10592 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10593
10594 /* Right now we are registering these frame when driver is getting
10595 * initialized. Once we will move to 2.6.37 kernel, in which we have
10596 * frame register ops, we will move this code as a part of that
10597 */
10598
10599 /* GAS Initial Request */
10600 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10601 (uint8_t *) GAS_INITIAL_REQ,
10602 GAS_INITIAL_REQ_SIZE);
10603
10604 /* GAS Initial Response */
10605 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10606 (uint8_t *) GAS_INITIAL_RSP,
10607 GAS_INITIAL_RSP_SIZE);
10608
10609 /* GAS Comeback Request */
10610 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10611 (uint8_t *) GAS_COMEBACK_REQ,
10612 GAS_COMEBACK_REQ_SIZE);
10613
10614 /* GAS Comeback Response */
10615 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10616 (uint8_t *) GAS_COMEBACK_RSP,
10617 GAS_COMEBACK_RSP_SIZE);
10618
10619 /* WNM BSS Transition Request frame */
10620 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10621 (uint8_t *) WNM_BSS_ACTION_FRAME,
10622 WNM_BSS_ACTION_FRAME_SIZE);
10623
10624 /* WNM-Notification */
10625 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10626 (uint8_t *) WNM_NOTIFICATION_FRAME,
10627 WNM_NOTIFICATION_FRAME_SIZE);
10628}
10629#else
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010630void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
10631{
10632 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10633 /* Register for all P2P action, public action etc frames */
10634 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10635
10636 ENTER();
10637
Abhishek Singh7996eb72015-12-30 17:24:02 +053010638 /* Register frame indication call back */
10639 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
10640
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +053010641 /* Register for p2p ack indication */
10642 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
10643
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010644 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010645 * initialized. Once we will move to 2.6.37 kernel, in which we have
10646 * frame register ops, we will move this code as a part of that
10647 */
10648
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010649 /* GAS Initial Request */
10650 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10651 (uint8_t *) GAS_INITIAL_REQ,
10652 GAS_INITIAL_REQ_SIZE);
10653
10654 /* GAS Initial Response */
10655 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10656 (uint8_t *) GAS_INITIAL_RSP,
10657 GAS_INITIAL_RSP_SIZE);
10658
10659 /* GAS Comeback Request */
10660 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10661 (uint8_t *) GAS_COMEBACK_REQ,
10662 GAS_COMEBACK_REQ_SIZE);
10663
10664 /* GAS Comeback Response */
10665 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10666 (uint8_t *) GAS_COMEBACK_RSP,
10667 GAS_COMEBACK_RSP_SIZE);
10668
10669 /* P2P Public Action */
10670 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10671 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10672 P2P_PUBLIC_ACTION_FRAME_SIZE);
10673
10674 /* P2P Action */
10675 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10676 (uint8_t *) P2P_ACTION_FRAME,
10677 P2P_ACTION_FRAME_SIZE);
10678
10679 /* WNM BSS Transition Request frame */
10680 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10681 (uint8_t *) WNM_BSS_ACTION_FRAME,
10682 WNM_BSS_ACTION_FRAME_SIZE);
10683
10684 /* WNM-Notification */
10685 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
10686 (uint8_t *) WNM_NOTIFICATION_FRAME,
10687 WNM_NOTIFICATION_FRAME_SIZE);
10688}
Wu Gao84d120c2017-03-24 18:46:00 +080010689#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010690
10691void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
10692{
10693 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10694 /* Register for all P2P action, public action etc frames */
10695 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
10696
10697 ENTER();
10698
10699 /* Right now we are registering these frame when driver is getting
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010700 * initialized. Once we will move to 2.6.37 kernel, in which we have
10701 * frame register ops, we will move this code as a part of that
10702 */
10703
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010704 /* GAS Initial Request */
10705
10706 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10707 (uint8_t *) GAS_INITIAL_REQ,
10708 GAS_INITIAL_REQ_SIZE);
10709
10710 /* GAS Initial Response */
10711 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10712 (uint8_t *) GAS_INITIAL_RSP,
10713 GAS_INITIAL_RSP_SIZE);
10714
10715 /* GAS Comeback Request */
10716 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10717 (uint8_t *) GAS_COMEBACK_REQ,
10718 GAS_COMEBACK_REQ_SIZE);
10719
10720 /* GAS Comeback Response */
10721 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10722 (uint8_t *) GAS_COMEBACK_RSP,
10723 GAS_COMEBACK_RSP_SIZE);
10724
10725 /* P2P Public Action */
10726 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10727 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
10728 P2P_PUBLIC_ACTION_FRAME_SIZE);
10729
10730 /* P2P Action */
10731 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
10732 (uint8_t *) P2P_ACTION_FRAME,
10733 P2P_ACTION_FRAME_SIZE);
10734
10735 /* WNM-Notification */
10736 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
10737 (uint8_t *) WNM_NOTIFICATION_FRAME,
10738 WNM_NOTIFICATION_FRAME_SIZE);
10739}
10740
10741#ifdef FEATURE_WLAN_WAPI
10742void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
10743 const uint8_t *mac_addr, const uint8_t *key,
10744 int key_Len)
10745{
10746 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10747 tCsrRoamSetKey setKey;
10748 bool isConnected = true;
10749 int status = 0;
10750 uint32_t roamId = 0xFF;
10751 uint8_t *pKeyPtr = NULL;
10752 int n = 0;
10753
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010754 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010755 hdd_device_mode_to_string(pAdapter->device_mode),
10756 pAdapter->device_mode);
10757
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010758 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010759 setKey.keyId = key_index; /* Store Key ID */
10760 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
10761 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
10762 setKey.paeRole = 0; /* the PAE role */
10763 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +053010764 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010765 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010766 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010767 }
10768 setKey.keyLength = key_Len;
10769 pKeyPtr = setKey.Key;
10770 memcpy(pKeyPtr, key, key_Len);
10771
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010772 hdd_debug("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010773 for (n = 0; n < key_Len; n++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010774 hdd_debug("WAPI KEY Data[%d]:%02x ",
Jeff Johnson46b40792016-06-29 14:03:14 -070010775 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010776
10777 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10778 if (isConnected) {
10779 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10780 pAdapter->sessionId, &setKey, &roamId);
10781 }
10782 if (status != 0) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010783 hdd_err("sme_roam_set_key failed status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010784 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
10785 }
10786}
10787#endif /* FEATURE_WLAN_WAPI */
10788
10789uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
10790 uint8_t eid)
10791{
10792 int left = length;
10793 uint8_t *ptr = (uint8_t *)ies_ptr;
10794 uint8_t elem_id, elem_len;
10795
10796 while (left >= 2) {
10797 elem_id = ptr[0];
10798 elem_len = ptr[1];
10799 left -= 2;
10800 if (elem_len > left) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010801 hdd_err("Invalid IEs eid: %d elem_len: %d left: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010802 eid, elem_len, left);
10803 return NULL;
10804 }
10805 if (elem_id == eid) {
10806 return ptr;
10807 }
10808
10809 left -= elem_len;
10810 ptr += (elem_len + 2);
10811 }
10812 return NULL;
10813}
10814
10815/*
10816 * FUNCTION: wlan_hdd_validate_operation_channel
10817 * called by wlan_hdd_cfg80211_start_bss() and
10818 * wlan_hdd_set_channel()
10819 * This function validates whether given channel is part of valid
10820 * channel list.
10821 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010822QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010823 int channel)
10824{
10825
10826 uint32_t num_ch = 0;
10827 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
10828 u32 indx = 0;
10829 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10830 uint8_t fValidChannel = false, count = 0;
10831 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
10832
10833 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
10834
10835 if (hdd_pConfig_ini->sapAllowAllChannel) {
10836 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -080010837 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -070010838 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010839 fValidChannel = true;
10840 break;
10841 }
10842 }
10843 if (fValidChannel != true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010844 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010845 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010846 }
10847 } else {
10848 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
10849 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010850 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010851 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010852 }
10853 for (indx = 0; indx < num_ch; indx++) {
10854 if (channel == valid_ch[indx]) {
10855 break;
10856 }
10857 }
10858
10859 if (indx >= num_ch) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010860 hdd_err("Invalid Channel: %d", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010861 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010862 }
10863 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010864 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010865
10866}
10867
10868#ifdef DHCP_SERVER_OFFLOAD
10869static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
10870{
10871 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
10872 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
10873 uint8_t numEntries = 0;
10874 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
10875 uint8_t num;
10876 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010877 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010878 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -070010879 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010880 return;
10881 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010882 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
10883 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
10884 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
10885 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
10886 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
10887 if (numEntries != IPADDR_NUM_ENTRIES) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010888 hdd_err("Incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010889 goto end;
10890 }
10891 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010892 hdd_err("Invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010893 goto end;
10894 }
10895 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010896 hdd_err("Invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010897 goto end;
10898 }
10899 for (num = 0; num < numEntries; num++) {
10900 temp = srv_ip[num];
10901 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
10902 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010903 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010904 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -070010905 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010906 goto end;
10907 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010908 hdd_debug("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010909end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010910 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010911 return;
10912}
10913#endif /* DHCP_SERVER_OFFLOAD */
10914
10915static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
10916 struct net_device *dev,
10917 struct bss_parameters *params)
10918{
10919 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
10920 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10921 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010922 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010923
10924 ENTER();
10925
Anurag Chouhan6d760662016-02-20 16:05:43 +053010926 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070010927 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010928 return -EINVAL;
10929 }
10930
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010931 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10932 hdd_err("invalid session id: %d", pAdapter->sessionId);
10933 return -EINVAL;
10934 }
10935
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010936 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010937 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
10938 pAdapter->sessionId, params->ap_isolate));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010939 hdd_debug("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010940 hdd_device_mode_to_string(pAdapter->device_mode),
10941 pAdapter->device_mode, params->ap_isolate);
10942
10943 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10944 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010945 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010946 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010947
Krunal Sonib4326f22016-03-10 13:05:51 -080010948 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
10949 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010950 return -EOPNOTSUPP;
10951 }
10952
10953 /* ap_isolate == -1 means that in change bss, upper layer doesn't
Jeff Johnsonf3826e12017-01-12 09:49:40 -080010954 * want to update this parameter
10955 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010956 if (-1 != params->ap_isolate) {
10957 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
10958 !!params->ap_isolate;
10959
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010960 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010961 pAdapter->sessionId,
10962 pAdapter->sessionCtx.
10963 ap.
10964 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010965 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010966 ret = -EINVAL;
10967 }
10968 }
10969
10970 EXIT();
10971 return ret;
10972}
10973
Krunal Soni8c37e322016-02-03 16:08:37 -080010974/**
10975 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
10976 * @ndev: pointer to net device provided by supplicant
10977 * @type: type of the interface, upper layer wanted to change
10978 *
10979 * Upper layer provides the new interface mode that needs to be changed
10980 * for given net device
10981 *
10982 * Return: success or failure in terms of integer value
10983 */
10984static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010985 enum nl80211_iftype type)
10986{
Krunal Soni8c37e322016-02-03 16:08:37 -080010987 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10988 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
10989 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010990 hdd_wext_state_t *wext;
10991 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053010992 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010993
10994 ENTER();
10995
Krunal Soni8c37e322016-02-03 16:08:37 -080010996 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080010997 hdd_warn("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010998 return 0;
10999 }
11000
11001 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -080011002 hdd_stop_adapter(hdd_ctx, adapter, true);
11003 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011004 wdev->iftype = type;
11005 /*Check for sub-string p2p to confirm its a p2p interface */
11006 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -080011007 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011008 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011009 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -080011010 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -080011011 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011012 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -080011013 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011014 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011015 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011016 }
Krunal Soni8c37e322016-02-03 16:08:37 -080011017 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
11018 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -080011019 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
11020 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011021 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -080011022 adapter->scan_info.scanAddIE.length;
11023 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011024 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -080011025 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
11026 wext->roamProfile.phyMode =
11027 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
11028 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011029 EXIT();
11030 return status;
11031}
11032
11033static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
11034 struct net_device *dev,
11035 struct bss_parameters *params)
11036{
11037 int ret;
11038
11039 cds_ssr_protect(__func__);
11040 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
11041 cds_ssr_unprotect(__func__);
11042
11043 return ret;
11044}
11045
11046/* FUNCTION: wlan_hdd_change_country_code_cd
11047 * to wait for contry code completion
11048 */
11049void *wlan_hdd_change_country_code_cb(void *pAdapter)
11050{
11051 hdd_adapter_t *call_back_pAdapter = pAdapter;
11052 complete(&call_back_pAdapter->change_country_code);
11053 return NULL;
11054}
11055
Rajeev Kumar98edb772016-01-19 12:42:19 -080011056/**
11057 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11058 * @wiphy: Pointer to the wiphy structure
11059 * @ndev: Pointer to the net device
11060 * @type: Interface type
11061 * @flags: Flags for change interface
11062 * @params: Pointer to change interface parameters
11063 *
11064 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011065 */
11066static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11067 struct net_device *ndev,
11068 enum nl80211_iftype type,
11069 u32 *flags,
11070 struct vif_params *params)
11071{
11072 struct wireless_dev *wdev;
11073 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11074 hdd_context_t *pHddCtx;
11075 tCsrRoamProfile *pRoamProfile = NULL;
11076 eCsrRoamBssType LastBSSType;
11077 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011078 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011079 int status;
11080
11081 ENTER();
11082
Anurag Chouhan6d760662016-02-20 16:05:43 +053011083 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -070011084 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011085 return -EINVAL;
11086 }
11087
11088 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11089 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011090 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011091 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011092
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011093 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011094 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
11095 pAdapter->sessionId, type));
11096
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011097 hdd_debug("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011098 pAdapter->device_mode, type);
11099
Arun Khandavallifae92942016-08-01 13:31:08 +053011100 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
11101 if (status) {
11102 hdd_err("Failed to start modules");
11103 return -EINVAL;
11104 }
11105
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011106 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011107 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
11108 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -070011109 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011110 return -EINVAL;
11111 }
11112
11113 pConfig = pHddCtx->config;
11114 wdev = ndev->ieee80211_ptr;
11115
11116 /* Reset the current device mode bit mask */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011117 policy_mgr_clear_concurrency_mode(pHddCtx->hdd_psoc,
11118 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011119
Nitesh Shahe6359752017-02-23 19:57:50 +053011120 hdd_update_tdls_ct_and_teardown_links(pHddCtx);
Krunal Sonib4326f22016-03-10 13:05:51 -080011121 if ((pAdapter->device_mode == QDF_STA_MODE) ||
11122 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
11123 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
11124 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011125 hdd_wext_state_t *pWextState =
11126 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11127
11128 pRoamProfile = &pWextState->roamProfile;
11129 LastBSSType = pRoamProfile->BSSType;
11130
11131 switch (type) {
11132 case NL80211_IFTYPE_STATION:
11133 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -080011134 case NL80211_IFTYPE_ADHOC:
11135 if (type == NL80211_IFTYPE_ADHOC) {
11136 wlan_hdd_tdls_exit(pAdapter);
11137 hdd_deregister_tx_flow_control(pAdapter);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011138 hdd_debug("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -080011139 }
11140 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
11141 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011142 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011143 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011144 if (hdd_start_adapter(pAdapter)) {
11145 hdd_err("Failed to start adapter :%d",
11146 pAdapter->device_mode);
11147 return -EINVAL;
11148 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011149 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011150 case NL80211_IFTYPE_AP:
11151 case NL80211_IFTYPE_P2P_GO:
11152 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011153 hdd_debug("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011154 (type ==
11155 NL80211_IFTYPE_AP) ? "SoftAP" :
11156 "P2pGo");
11157
11158 /* Cancel any remain on channel for GO mode */
11159 if (NL80211_IFTYPE_P2P_GO == type) {
11160 wlan_hdd_cancel_existing_remain_on_channel
11161 (pAdapter);
11162 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011163
Arun Khandavallifae92942016-08-01 13:31:08 +053011164 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011165 /* De-init the adapter */
11166 hdd_deinit_adapter(pHddCtx, pAdapter, true);
11167 memset(&pAdapter->sessionCtx, 0,
11168 sizeof(pAdapter->sessionCtx));
11169 pAdapter->device_mode =
11170 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -080011171 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
11172 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011173
11174 /*
11175 * Fw will take care incase of concurrency
11176 */
11177
Krunal Sonib4326f22016-03-10 13:05:51 -080011178 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011179 && (pConfig->apRandomBssidEnabled)) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011180 /* To meet Android requirements create
11181 * a randomized MAC address of the
11182 * form 02:1A:11:Fx:xx:xx
11183 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011184 get_random_bytes(&ndev->dev_addr[3], 3);
11185 ndev->dev_addr[0] = 0x02;
11186 ndev->dev_addr[1] = 0x1A;
11187 ndev->dev_addr[2] = 0x11;
11188 ndev->dev_addr[3] |= 0xF0;
11189 memcpy(pAdapter->macAddressCurrent.
11190 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +053011191 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011192 pr_info("wlan: Generated HotSpot BSSID "
11193 MAC_ADDRESS_STR "\n",
11194 MAC_ADDR_ARRAY(ndev->dev_addr));
11195 }
11196
11197 hdd_set_ap_ops(pAdapter->dev);
11198
Arun Khandavallifae92942016-08-01 13:31:08 +053011199 if (hdd_start_adapter(pAdapter)) {
11200 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011201 return -EINVAL;
11202 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011203 /* Interface type changed update in wiphy structure */
11204 if (wdev) {
11205 wdev->iftype = type;
11206 } else {
Jeff Johnson77848112016-06-29 14:52:06 -070011207 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011208 return -EINVAL;
11209 }
11210 goto done;
11211 }
11212
11213 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011214 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011215 return -EOPNOTSUPP;
11216 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011217 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11218 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011219 switch (type) {
11220 case NL80211_IFTYPE_STATION:
11221 case NL80211_IFTYPE_P2P_CLIENT:
11222 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -080011223 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
11224 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011225 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011226 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011227 if (hdd_start_adapter(pAdapter)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011228 hdd_err("Failed to start adapter: %d",
Arun Khandavallib2f6c262016-08-18 19:07:19 +053011229 pAdapter->device_mode);
11230 return -EINVAL;
11231 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011232 goto done;
11233
11234 case NL80211_IFTYPE_AP:
11235 case NL80211_IFTYPE_P2P_GO:
11236 wdev->iftype = type;
11237 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -080011238 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011239 goto done;
11240
11241 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011242 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011243 return -EOPNOTSUPP;
11244 }
11245 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011246 hdd_err("Unsupported device mode: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011247 pAdapter->device_mode);
11248 return -EOPNOTSUPP;
11249 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011250done:
11251 /* Set bitmask based on updated value */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080011252 policy_mgr_set_concurrency_mode(pHddCtx->hdd_psoc,
11253 pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011254
Jeff Johnson2ae6f712016-09-23 15:08:48 -070011255 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011256
11257 EXIT();
11258 return 0;
11259}
11260
Rajeev Kumar98edb772016-01-19 12:42:19 -080011261/**
11262 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
11263 * @wiphy: Pointer to the wiphy structure
11264 * @ndev: Pointer to the net device
11265 * @type: Interface type
11266 * @flags: Flags for change interface
11267 * @params: Pointer to change interface parameters
11268 *
11269 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011270 */
11271static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
11272 struct net_device *ndev,
11273 enum nl80211_iftype type,
11274 u32 *flags,
11275 struct vif_params *params)
11276{
11277 int ret;
11278
11279 cds_ssr_protect(__func__);
11280 ret =
11281 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
11282 cds_ssr_unprotect(__func__);
11283
11284 return ret;
11285}
11286
11287#ifdef FEATURE_WLAN_TDLS
11288static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
11289 int index, uint8_t match)
11290{
11291 int i;
11292 for (i = 0; i < index; i++) {
11293 if (arr[i] == match)
11294 return true;
11295 }
11296 return false;
11297}
11298#endif
11299
11300/**
11301 * __wlan_hdd_change_station() - change station
11302 * @wiphy: Pointer to the wiphy structure
11303 * @dev: Pointer to the net device.
11304 * @mac: bssid
11305 * @params: Pointer to station parameters
11306 *
11307 * Return: 0 for success, error number on failure.
11308 */
11309#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
11310static int __wlan_hdd_change_station(struct wiphy *wiphy,
11311 struct net_device *dev,
11312 const uint8_t *mac,
11313 struct station_parameters *params)
11314#else
11315static int __wlan_hdd_change_station(struct wiphy *wiphy,
11316 struct net_device *dev,
11317 uint8_t *mac,
11318 struct station_parameters *params)
11319#endif
11320{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011321 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011322 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11323 hdd_context_t *pHddCtx;
11324 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +053011325 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011326#ifdef FEATURE_WLAN_TDLS
11327 tCsrStaParams StaParams = { 0 };
11328 uint8_t isBufSta = 0;
11329 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +053011330 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011331#endif
11332 int ret;
11333
11334 ENTER();
11335
Anurag Chouhan6d760662016-02-20 16:05:43 +053011336 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011337 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011338 return -EINVAL;
11339 }
11340
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011341 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011342 TRACE_CODE_HDD_CHANGE_STATION,
11343 pAdapter->sessionId, params->listen_interval));
11344
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011345 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11346 hdd_err("invalid session id: %d", pAdapter->sessionId);
11347 return -EINVAL;
11348 }
11349
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011350 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11351 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011352 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011353 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011354
11355 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11356
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011357 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011358
Krunal Sonib4326f22016-03-10 13:05:51 -080011359 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11360 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011361 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
11362 status =
11363 hdd_softap_change_sta_state(pAdapter,
11364 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -080011365 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011366
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011367 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011368 hdd_debug("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011369 return -EINVAL;
11370 }
11371 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011372 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11373 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011374#ifdef FEATURE_WLAN_TDLS
11375 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -070011376
11377 if (cds_is_sub_20_mhz_enabled()) {
11378 hdd_err("TDLS not allowed with sub 20 MHz");
11379 return -EINVAL;
11380 }
11381
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011382 StaParams.capability = params->capability;
11383 StaParams.uapsd_queues = params->uapsd_queues;
11384 StaParams.max_sp = params->max_sp;
11385
11386 /* Convert (first channel , number of channels) tuple to
11387 * the total list of channels. This goes with the assumption
11388 * that if the first channel is < 14, then the next channels
11389 * are an incremental of 1 else an incremental of 4 till the number
11390 * of channels.
11391 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011392 hdd_debug("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011393 if (0 != params->supported_channels_len) {
11394 int i = 0, j = 0, k = 0, no_of_channels = 0;
11395 int num_unique_channels;
11396 int next;
11397 for (i = 0;
11398 i < params->supported_channels_len
11399 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
11400 int wifi_chan_index;
11401 if (!wlan_hdd_is_duplicate_channel
11402 (StaParams.supported_channels, j,
11403 params->supported_channels[i])) {
11404 StaParams.
11405 supported_channels[j] =
11406 params->
11407 supported_channels[i];
11408 } else {
11409 continue;
11410 }
11411 wifi_chan_index =
11412 ((StaParams.supported_channels[j] <=
11413 HDD_CHANNEL_14) ? 1 : 4);
11414 no_of_channels =
11415 params->supported_channels[i + 1];
11416
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011417 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 -080011418 StaParams.
11419 supported_channels[j],
11420 wifi_chan_index,
11421 no_of_channels);
11422 for (k = 1; k <= no_of_channels &&
11423 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
11424 k++) {
11425 next =
11426 StaParams.
11427 supported_channels[j] +
11428 wifi_chan_index;
11429 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
11430 StaParams.
11431 supported_channels[j
11432 +
11433 1]
11434 = next;
11435 } else {
11436 continue;
11437 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011438 hdd_debug("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011439 j + 1,
11440 StaParams.
11441 supported_channels[j +
11442 1]);
11443 j += 1;
11444 }
11445 }
11446 num_unique_channels = j + 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011447 hdd_debug("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011448 for (i = 0; i < num_unique_channels; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011449 hdd_debug("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011450 StaParams.
11451 supported_channels[i]);
11452 }
11453 if (MAX_CHANNEL < num_unique_channels)
11454 num_unique_channels = MAX_CHANNEL;
11455 StaParams.supported_channels_len =
11456 num_unique_channels;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011457 hdd_debug("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011458 StaParams.supported_channels_len);
11459 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011460 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011461 params->supported_oper_classes,
11462 params->supported_oper_classes_len);
11463 StaParams.supported_oper_classes_len =
11464 params->supported_oper_classes_len;
11465
11466 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011467 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011468 params->ext_capab,
11469 sizeof(StaParams.extn_capability));
11470
11471 if (NULL != params->ht_capa) {
11472 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011473 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011474 sizeof(tSirHTCap));
11475 }
11476
11477 StaParams.supported_rates_len =
11478 params->supported_rates_len;
11479
11480 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
11481 * The supported_rates array , for all the structures propogating till Add Sta
11482 * to the firmware has to be modified , if the supplicant (ieee80211) is
11483 * modified to send more rates.
11484 */
11485
11486 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
11487 */
11488 if (StaParams.supported_rates_len >
11489 SIR_MAC_MAX_SUPP_RATES)
11490 StaParams.supported_rates_len =
11491 SIR_MAC_MAX_SUPP_RATES;
11492
11493 if (0 != StaParams.supported_rates_len) {
11494 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011495 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011496 params->supported_rates,
11497 StaParams.supported_rates_len);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011498 hdd_debug("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011499 StaParams.supported_rates_len);
11500 for (i = 0; i < StaParams.supported_rates_len;
11501 i++)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011502 hdd_debug("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011503 StaParams.supported_rates[i]);
11504 }
11505
11506 if (NULL != params->vht_capa) {
11507 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011508 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011509 params->vht_capa,
11510 sizeof(tSirVHTCap));
11511 }
11512
11513 if (0 != params->ext_capab_len) {
11514 /*Define A Macro : TODO Sunil */
11515 if ((1 << 4) & StaParams.extn_capability[3]) {
11516 isBufSta = 1;
11517 }
11518 /* TDLS Channel Switching Support */
11519 if ((1 << 6) & StaParams.extn_capability[3]) {
11520 isOffChannelSupported = 1;
11521 }
11522 }
11523
Nitesh Shah99934ac2016-09-05 15:54:08 +053011524 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053011525 (params->ht_capa || params->vht_capa ||
11526 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053011527 is_qos_wmm_sta = true;
11528
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011529 hdd_debug("%s: TDLS Peer is QOS capable"
Nitesh Shah99934ac2016-09-05 15:54:08 +053011530 " is_qos_wmm_sta= %d HTcapPresent = %d",
11531 __func__, is_qos_wmm_sta,
11532 StaParams.htcap_present);
11533
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011534 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053011535 &StaParams,
11536 isBufSta,
11537 isOffChannelSupported,
11538 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011539 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011540 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011541 return -EINVAL;
11542 }
11543
11544 status =
11545 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
11546 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011547 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011548 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011549 return -EINVAL;
11550 }
11551 }
11552#endif
11553 }
11554 EXIT();
11555 return ret;
11556}
11557
11558/**
11559 * wlan_hdd_change_station() - cfg80211 change station handler function
11560 * @wiphy: Pointer to the wiphy structure
11561 * @dev: Pointer to the net device.
11562 * @mac: bssid
11563 * @params: Pointer to station parameters
11564 *
11565 * This is the cfg80211 change station handler function which invokes
11566 * the internal function @__wlan_hdd_change_station with
11567 * SSR protection.
11568 *
11569 * Return: 0 for success, error number on failure.
11570 */
11571#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
11572static int wlan_hdd_change_station(struct wiphy *wiphy,
11573 struct net_device *dev,
11574 const u8 *mac,
11575 struct station_parameters *params)
11576#else
11577static int wlan_hdd_change_station(struct wiphy *wiphy,
11578 struct net_device *dev,
11579 u8 *mac,
11580 struct station_parameters *params)
11581#endif
11582{
11583 int ret;
11584
11585 cds_ssr_protect(__func__);
11586 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
11587 cds_ssr_unprotect(__func__);
11588
11589 return ret;
11590}
11591
11592/*
11593 * FUNCTION: __wlan_hdd_cfg80211_add_key
11594 * This function is used to initialize the key information
11595 */
11596static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11597 struct net_device *ndev,
11598 u8 key_index, bool pairwise,
11599 const u8 *mac_addr,
11600 struct key_params *params)
11601{
11602 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11603 tCsrRoamSetKey setKey;
11604 int status;
11605 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011606 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011607 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011608 hdd_context_t *pHddCtx;
11609 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
11610
11611 ENTER();
11612
Anurag Chouhan6d760662016-02-20 16:05:43 +053011613 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011614 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011615 return -EINVAL;
11616 }
11617
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011618 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011619 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011620 return -EINVAL;
11621 }
11622
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011623 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011624 TRACE_CODE_HDD_CFG80211_ADD_KEY,
11625 pAdapter->sessionId, params->key_len));
11626 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11627 status = wlan_hdd_validate_context(pHddCtx);
11628
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011629 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011630 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011631
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011632 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011633 hdd_device_mode_to_string(pAdapter->device_mode),
11634 pAdapter->device_mode);
11635
11636 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011637 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011638
11639 return -EINVAL;
11640 }
11641
11642 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011643 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011644
11645 return -EINVAL;
11646 }
11647
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011648 hdd_debug("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011649
11650 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011651 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011652 setKey.keyId = key_index;
11653 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011654 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011655
11656 switch (params->cipher) {
11657 case WLAN_CIPHER_SUITE_WEP40:
11658 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11659 break;
11660
11661 case WLAN_CIPHER_SUITE_WEP104:
11662 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
11663 break;
11664
11665 case WLAN_CIPHER_SUITE_TKIP:
11666 {
11667 u8 *pKey = &setKey.Key[0];
11668 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
11669
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011670 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011671
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011672 /* Supplicant sends the 32bytes key in this order
11673 *
11674 * |--------------|----------|----------|
11675 * | Tk1 |TX-MIC | RX Mic |
11676 * |--------------|----------|----------|
11677 * <---16bytes---><--8bytes--><--8bytes-->
11678 *
11679 * Sme expects the 32 bytes key to be in the below order
11680 *
11681 * |--------------|----------|----------|
11682 * | Tk1 |RX-MIC | TX Mic |
11683 * |--------------|----------|----------|
11684 * <---16bytes---><--8bytes--><--8bytes-->
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011685 */
11686 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011687 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011688
11689 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011690 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011691
11692 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011693 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011694
11695 break;
11696 }
11697
11698 case WLAN_CIPHER_SUITE_CCMP:
11699 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
11700 break;
11701
11702#ifdef FEATURE_WLAN_WAPI
11703 case WLAN_CIPHER_SUITE_SMS4:
11704 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011705 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011706 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
11707 mac_addr, params->key,
11708 params->key_len);
11709 return 0;
11710 }
11711#endif
11712
11713#ifdef FEATURE_WLAN_ESE
11714 case WLAN_CIPHER_SUITE_KRK:
11715 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
11716 break;
11717#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11718 case WLAN_CIPHER_SUITE_BTK:
11719 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
11720 break;
11721#endif
11722#endif
11723
11724#ifdef WLAN_FEATURE_11W
11725 case WLAN_CIPHER_SUITE_AES_CMAC:
11726 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
11727 break;
11728#endif
11729
11730 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011731 hdd_err("Unsupported cipher type: %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011732 return -EOPNOTSUPP;
11733 }
11734
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011735 hdd_debug("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011736
11737 if (!pairwise) {
11738 /* set group key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011739 hdd_debug("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011740 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011741 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011742 } else {
11743 /* set pairwise key */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011744 hdd_debug("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011745 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011746 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011747 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011748 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011749 /* if a key is already installed, block all subsequent ones */
11750 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011751 hdd_debug("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011752 return 0;
11753 }
11754
11755 setKey.keyDirection = eSIR_TX_RX;
11756 /*Set the group key */
11757 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11758 pAdapter->sessionId, &setKey, &roamId);
11759
11760 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011761 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011762 return -EINVAL;
11763 }
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011764 /* Save the keys here and call sme_roam_set_key for setting
11765 * the PTK after peer joins the IBSS network
11766 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011767 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011768 &setKey, sizeof(tCsrRoamSetKey));
11769
11770 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
11771 return status;
11772 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011773 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
11774 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011775 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
11776 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070011777 status = wlansap_set_key_sta(
11778 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011779 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011780 hdd_err("wlansap_set_key_sta failed status: %d",
11781 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011782 }
11783 }
11784
11785 /* Save the key in ap ctx for use on START_BASS and restart */
11786 if (pairwise ||
11787 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
11788 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011789 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011790 sizeof(tCsrRoamSetKey));
11791 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011792 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011793 sizeof(tCsrRoamSetKey));
11794
Krunal Sonib4326f22016-03-10 13:05:51 -080011795 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
11796 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011797 hdd_wext_state_t *pWextState =
11798 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11799 hdd_station_ctx_t *pHddStaCtx =
11800 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11801
11802 if (!pairwise) {
11803 /* set group key */
11804 if (pHddStaCtx->roam_info.deferKeyComplete) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011805 hdd_debug("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011806 __func__, __LINE__);
11807 hdd_perform_roam_set_key_complete(pAdapter);
11808 }
11809 }
11810
11811 pWextState->roamProfile.Keys.KeyLength[key_index] =
11812 (u8) params->key_len;
11813
11814 pWextState->roamProfile.Keys.defaultIndex = key_index;
11815
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011816 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011817 KeyMaterial[key_index][0], params->key,
11818 params->key_len);
11819
11820 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
11821
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011822 hdd_debug("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011823 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11824 setKey.keyDirection);
11825
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011826 /* The supplicant may attempt to set the PTK once
11827 * pre-authentication is done. Save the key in the
11828 * UMAC and include it in the ADD BSS request
11829 */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011830 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011831 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011832 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011833 hdd_debug("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011834 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011835 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011836 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011837 return -EINVAL;
11838 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011839
11840 /* issue set key request to SME */
11841 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11842 pAdapter->sessionId, &setKey, &roamId);
11843
11844 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011845 hdd_err("sme_roam_set_key failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011846 pHddStaCtx->roam_info.roamingState =
11847 HDD_ROAM_STATE_NONE;
11848 return -EINVAL;
11849 }
11850
Jeff Johnsonf3826e12017-01-12 09:49:40 -080011851 /* in case of IBSS as there was no information
11852 * available about WEP keys during IBSS join, group
11853 * key intialized with NULL key, so re-initialize
11854 * group key with correct value
11855 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011856 if ((eCSR_BSS_TYPE_START_IBSS ==
11857 pWextState->roamProfile.BSSType)
11858 &&
11859 !((IW_AUTH_KEY_MGMT_802_1X ==
11860 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
11861 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
11862 pHddStaCtx->conn_info.authType)
11863 )
11864 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
11865 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
11866 )
11867 ) {
11868 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053011869 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011870
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011871 hdd_debug("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011872 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
11873 setKey.keyDirection);
11874
11875 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
11876 pAdapter->sessionId, &setKey,
11877 &roamId);
11878
11879 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011880 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011881 pHddStaCtx->roam_info.roamingState =
11882 HDD_ROAM_STATE_NONE;
11883 return -EINVAL;
11884 }
11885 }
11886 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011887 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011888 return 0;
11889}
11890
11891static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
11892 struct net_device *ndev,
11893 u8 key_index, bool pairwise,
11894 const u8 *mac_addr,
11895 struct key_params *params)
11896{
11897 int ret;
11898 cds_ssr_protect(__func__);
11899 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
11900 mac_addr, params);
11901 cds_ssr_unprotect(__func__);
11902
11903 return ret;
11904}
11905
11906/*
11907 * FUNCTION: __wlan_hdd_cfg80211_get_key
11908 * This function is used to get the key information
11909 */
11910static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11911 struct net_device *ndev,
11912 u8 key_index, bool pairwise,
11913 const u8 *mac_addr, void *cookie,
11914 void (*callback)(void *cookie,
11915 struct key_params *)
11916 )
11917{
11918 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11919 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11920 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
11921 struct key_params params;
11922
11923 ENTER();
11924
Anurag Chouhan6d760662016-02-20 16:05:43 +053011925 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011926 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011927 return -EINVAL;
11928 }
11929
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011930 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011931 hdd_device_mode_to_string(pAdapter->device_mode),
11932 pAdapter->device_mode);
11933
11934 memset(&params, 0, sizeof(params));
11935
11936 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080011937 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011938 return -EINVAL;
11939 }
11940
11941 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
11942 case eCSR_ENCRYPT_TYPE_NONE:
11943 params.cipher = IW_AUTH_CIPHER_NONE;
11944 break;
11945
11946 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
11947 case eCSR_ENCRYPT_TYPE_WEP40:
11948 params.cipher = WLAN_CIPHER_SUITE_WEP40;
11949 break;
11950
11951 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
11952 case eCSR_ENCRYPT_TYPE_WEP104:
11953 params.cipher = WLAN_CIPHER_SUITE_WEP104;
11954 break;
11955
11956 case eCSR_ENCRYPT_TYPE_TKIP:
11957 params.cipher = WLAN_CIPHER_SUITE_TKIP;
11958 break;
11959
11960 case eCSR_ENCRYPT_TYPE_AES:
11961 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
11962 break;
11963
11964 default:
11965 params.cipher = IW_AUTH_CIPHER_NONE;
11966 break;
11967 }
11968
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011969 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011970 TRACE_CODE_HDD_CFG80211_GET_KEY,
11971 pAdapter->sessionId, params.cipher));
11972
11973 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
11974 params.seq_len = 0;
11975 params.seq = NULL;
11976 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
11977 callback(cookie, &params);
11978
11979 EXIT();
11980 return 0;
11981}
11982
11983static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
11984 struct net_device *ndev,
11985 u8 key_index, bool pairwise,
11986 const u8 *mac_addr, void *cookie,
11987 void (*callback)(void *cookie,
11988 struct key_params *)
11989 )
11990{
11991 int ret;
11992
11993 cds_ssr_protect(__func__);
11994 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
11995 mac_addr, cookie, callback);
11996 cds_ssr_unprotect(__func__);
11997
11998 return ret;
11999}
12000
12001/**
12002 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
12003 * @wiphy: wiphy interface context
12004 * @ndev: pointer to net device
12005 * @key_index: Key index used in 802.11 frames
12006 * @unicast: true if it is unicast key
12007 * @multicast: true if it is multicast key
12008 *
12009 * This function is required for cfg80211_ops API.
12010 * It is used to delete the key information
12011 * Underlying hardware implementation does not have API to delete the
12012 * encryption key. It is automatically deleted when the peer is
12013 * removed. Hence this function currently does nothing.
12014 * Future implementation may interprete delete key operation to
12015 * replacing the key with a random junk value, effectively making it
12016 * useless.
12017 *
12018 * Return: status code, always 0.
12019 */
12020
12021static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12022 struct net_device *ndev,
12023 u8 key_index,
12024 bool pairwise, const u8 *mac_addr)
12025{
12026 EXIT();
12027 return 0;
12028}
12029
12030/**
12031 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
12032 * @wiphy: Pointer to wiphy structure.
12033 * @dev: Pointer to net_device structure.
12034 * @key_index: key index
12035 * @pairwise: pairwise
12036 * @mac_addr: mac address
12037 *
12038 * This is the cfg80211 delete key handler function which invokes
12039 * the internal function @__wlan_hdd_cfg80211_del_key with
12040 * SSR protection.
12041 *
12042 * Return: 0 for success, error number on failure.
12043 */
12044static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
12045 struct net_device *dev,
12046 u8 key_index,
12047 bool pairwise, const u8 *mac_addr)
12048{
12049 int ret;
12050
12051 cds_ssr_protect(__func__);
12052 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
12053 pairwise, mac_addr);
12054 cds_ssr_unprotect(__func__);
12055
12056 return ret;
12057}
12058
12059/*
12060 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
12061 * This function is used to set the default tx key index
12062 */
12063static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12064 struct net_device *ndev,
12065 u8 key_index,
12066 bool unicast, bool multicast)
12067{
12068 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12069 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12070 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12071 hdd_context_t *pHddCtx;
12072 int status;
12073
12074 ENTER();
12075
Anurag Chouhan6d760662016-02-20 16:05:43 +053012076 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012077 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012078 return -EINVAL;
12079 }
12080
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012081 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012082 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012083 return -EINVAL;
12084 }
12085
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012086 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012087 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
12088 pAdapter->sessionId, key_index));
12089
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012090 hdd_debug("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012091 hdd_device_mode_to_string(pAdapter->device_mode),
12092 pAdapter->device_mode, key_index);
12093
12094 if (CSR_MAX_NUM_KEY <= key_index) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012095 hdd_err("Invalid key index: %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012096 return -EINVAL;
12097 }
12098
12099 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12100 status = wlan_hdd_validate_context(pHddCtx);
12101
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012102 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012103 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012104
Krunal Sonib4326f22016-03-10 13:05:51 -080012105 if ((pAdapter->device_mode == QDF_STA_MODE) ||
12106 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012107 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12108 pHddStaCtx->conn_info.ucEncryptionType) &&
12109 (eCSR_ENCRYPT_TYPE_AES !=
12110 pHddStaCtx->conn_info.ucEncryptionType)) {
12111 /* If default key index is not same as previous one,
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012112 * then update the default key index
12113 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012114
12115 tCsrRoamSetKey setKey;
12116 uint32_t roamId = 0xFF;
12117 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
12118
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012119 hdd_debug("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012120
12121 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012122 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012123 setKey.keyId = key_index;
12124 setKey.keyLength = Keys->KeyLength[key_index];
12125
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012126 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012127 &Keys->KeyMaterial[key_index][0],
12128 Keys->KeyLength[key_index]);
12129
12130 setKey.keyDirection = eSIR_TX_RX;
12131
Anurag Chouhanc5548422016-02-24 18:33:27 +053012132 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012133 &pHddStaCtx->conn_info.bssId);
12134
12135 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
12136 pWextState->roamProfile.EncryptionType.
12137 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012138 /* In the case of dynamic wep
12139 * supplicant hardcodes DWEP type to
12140 * eCSR_ENCRYPT_TYPE_WEP104 even
12141 * though ap is configured for WEP-40
12142 * encryption. In this canse the key
12143 * length is 5 but the encryption type
12144 * is 104 hence checking the key
12145 * lenght(5) and encryption type(104)
12146 * and switching encryption type to 40
12147 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012148 pWextState->roamProfile.EncryptionType.
12149 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12150 pWextState->roamProfile.mcEncryptionType.
12151 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
12152 }
12153
12154 setKey.encType =
12155 pWextState->roamProfile.EncryptionType.
12156 encryptionType[0];
12157
12158 /* Issue set key request */
12159 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
12160 pAdapter->sessionId, &setKey,
12161 &roamId);
12162
12163 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012164 hdd_err("sme_roam_set_key failed, status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012165 status);
12166 return -EINVAL;
12167 }
12168 }
Krunal Sonib4326f22016-03-10 13:05:51 -080012169 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012170 /* In SoftAp mode setting key direction for default mode */
12171 if ((eCSR_ENCRYPT_TYPE_TKIP !=
12172 pWextState->roamProfile.EncryptionType.encryptionType[0])
12173 && (eCSR_ENCRYPT_TYPE_AES !=
12174 pWextState->roamProfile.EncryptionType.
12175 encryptionType[0])) {
12176 /* Saving key direction for default key index to TX default */
12177 hdd_ap_ctx_t *pAPCtx =
12178 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
12179 pAPCtx->wepKey[key_index].keyDirection =
12180 eSIR_TX_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012181 hdd_debug("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053012182 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053012183 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012184 }
12185 }
12186
12187 EXIT();
12188 return status;
12189}
12190
12191static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
12192 struct net_device *ndev,
12193 u8 key_index,
12194 bool unicast, bool multicast)
12195{
12196 int ret;
12197 cds_ssr_protect(__func__);
12198 ret =
12199 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
12200 multicast);
12201 cds_ssr_unprotect(__func__);
12202
12203 return ret;
12204}
12205
Abhishek Singhc9941602016-08-09 16:06:22 +053012206/*
Abhishek Singhc9941602016-08-09 16:06:22 +053012207 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
12208 * interface that BSS might have been lost.
12209 * @pAdapter: adaptor
12210 * @bssid: bssid which might have been lost
12211 *
12212 * Return: bss which is unlinked from kernel cache
12213 */
12214struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
12215 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012216{
12217 struct net_device *dev = pAdapter->dev;
12218 struct wireless_dev *wdev = dev->ieee80211_ptr;
12219 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012220 struct cfg80211_bss *bss = NULL;
12221
Abhishek Singhb5e38ef2017-01-02 12:09:34 +053012222 bss = hdd_cfg80211_get_bss(wiphy, NULL, bssid,
Abhishek Singhc9941602016-08-09 16:06:22 +053012223 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012224 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012225 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012226 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012227 hdd_debug("cfg80211_unlink_bss called for BSSID "
Abhishek Singhc9941602016-08-09 16:06:22 +053012228 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012229 cfg80211_unlink_bss(wiphy, bss);
12230 }
12231 return bss;
12232}
12233
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012234#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4 , 3, 0)) || \
12235 defined (CFG80211_INFORM_BSS_FRAME_DATA)
12236static struct cfg80211_bss *
12237wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12238 struct ieee80211_channel *chan,
12239 struct ieee80211_mgmt *mgmt,
12240 size_t frame_len,
12241 int rssi, gfp_t gfp,
12242 uint64_t boottime_ns)
12243{
12244 struct cfg80211_bss *bss_status = NULL;
12245 struct cfg80211_inform_bss data = {0};
12246
12247 data.chan = chan;
12248 data.boottime_ns = boottime_ns;
12249 data.signal = rssi;
12250 bss_status = cfg80211_inform_bss_frame_data(wiphy, &data, mgmt,
12251 frame_len, gfp);
12252 return bss_status;
12253}
12254#else
12255static struct cfg80211_bss *
12256wlan_hdd_cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
12257 struct ieee80211_channel *chan,
12258 struct ieee80211_mgmt *mgmt,
12259 size_t frame_len,
12260 int rssi, gfp_t gfp,
12261 uint64_t boottime_ns)
12262{
12263 struct cfg80211_bss *bss_status = NULL;
12264
12265 bss_status = cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len,
12266 rssi, gfp);
12267 return bss_status;
12268}
12269#endif
Abhishek Singhc9941602016-08-09 16:06:22 +053012270
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012271/**
12272 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
12273 * @pAdapter: Pointer to adapter
12274 * @bss_desc: Pointer to bss descriptor
12275 *
12276 * This function is used to inform the BSS details to nl80211 interface.
12277 *
12278 * Return: struct cfg80211_bss pointer
12279 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053012280struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
12281 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012282{
12283 /*
12284 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
12285 * already exists in bss data base of cfg80211 for that particular BSS
12286 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
12287 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
12288 * As of now there is no possibility to get the mgmt(probe response)
12289 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
12290 * and passing to cfg80211_inform_bss_frame.
12291 */
12292 struct net_device *dev = pAdapter->dev;
12293 struct wireless_dev *wdev = dev->ieee80211_ptr;
12294 struct wiphy *wiphy = wdev->wiphy;
12295 int chan_no = bss_desc->channelId;
12296#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12297 qcom_ie_age *qie_age = NULL;
12298 int ie_length =
12299 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
12300#else
12301 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
12302#endif
12303 const char *ie =
12304 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
12305 unsigned int freq;
12306 struct ieee80211_channel *chan;
12307 struct ieee80211_mgmt *mgmt = NULL;
12308 struct cfg80211_bss *bss_status = NULL;
12309 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
12310 int rssi = 0;
12311 hdd_context_t *pHddCtx;
12312 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012313 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012314 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012315
12316 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12317 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012318 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012319 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012320
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012321 cfg_param = pHddCtx->config;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012322 mgmt = qdf_mem_malloc((sizeof(struct ieee80211_mgmt) + ie_length));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012323 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012324 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012325 return NULL;
12326 }
12327
12328 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
12329
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012330 /* Android does not want the timestamp from the frame.
Jeff Johnsonf3826e12017-01-12 09:49:40 -080012331 * Instead it wants a monotonic increasing value
12332 */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070012333 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012334 mgmt->u.probe_resp.timestamp =
12335 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012336
12337 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
12338 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
12339
12340#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
12341 /* GPS Requirement: need age ie per entry. Using vendor specific. */
12342 /* Assuming this is the last IE, copy at the end */
12343 ie_length -= sizeof(qcom_ie_age);
12344 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
12345 qie_age->element_id = QCOM_VENDOR_IE_ID;
12346 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
12347 qie_age->oui_1 = QCOM_OUI1;
12348 qie_age->oui_2 = QCOM_OUI2;
12349 qie_age->oui_3 = QCOM_OUI3;
12350 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053012351 /*
12352 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
12353 * all bss related timestamp is in units of ms. Due to this when scan
12354 * results are sent to lowi the scan age is high.To address this,
12355 * send age in units of 1/10 ms.
12356 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012357 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053012358 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012359 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070012360 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
12361 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070012362 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
12363 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012364#endif
12365
12366 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
12367 if (bss_desc->fProbeRsp) {
12368 mgmt->frame_control |=
12369 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
12370 } else {
12371 mgmt->frame_control |=
12372 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
12373 }
12374
12375 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070012376 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012377 freq =
12378 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012379 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012380 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070012381 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012382 freq =
12383 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070012384 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012385 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012386 hdd_err("Invalid channel: %d", chan_no);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012387 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012388 return NULL;
12389 }
12390
12391 chan = __ieee80211_get_channel(wiphy, freq);
12392 /* When the band is changed on the fly using the GUI, three things are done
12393 * 1. scan abort
12394 * 2. flush scan results from cache
12395 * 3. update the band with the new band user specified (refer to the
12396 * hdd_set_band_helper function) as part of the scan abort, message will be
12397 * queued to PE and we proceed with flushing and changinh the band.
12398 * PE will stop the scanning further and report back the results what ever
12399 * it had till now by calling the call back function.
12400 * if the time between update band and scandone call back is sufficient
12401 * enough the band change reflects in SME, SME validates the channels
12402 * and discards the channels correponding to previous band and calls back
12403 * with zero bss results. but if the time between band update and scan done
12404 * callback is very small then band change will not reflect in SME and SME
12405 * reports to HDD all the channels correponding to previous band.this is due
12406 * to race condition.but those channels are invalid to the new band and so
12407 * this function __ieee80211_get_channel will return NULL.Each time we
12408 * report scan result with this pointer null warning kernel trace is printed.
12409 * if the scan results contain large number of APs continuosly kernel
12410 * warning trace is printed and it will lead to apps watch dog bark.
12411 * So drop the bss and continue to next bss.
12412 */
12413 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053012414 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
12415 chan_no, freq);
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012416 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012417 return NULL;
12418 }
12419
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070012420 /* Based on .ini configuration, raw rssi can be reported for bss.
12421 * Raw rssi is typically used for estimating power.
12422 */
12423
12424 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
12425 bss_desc->rssi;
12426
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012427 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053012428 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012429
SaidiReddy Yenuga1fa40972016-11-15 13:44:15 +053012430 hdd_log(LOG1, "BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012431 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070012432 (int)(rssi / 100),
12433 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012434
Arun Khandavalli8a711cb2017-01-03 20:23:56 +053012435 bss_status = wlan_hdd_cfg80211_inform_bss_frame_data(wiphy, chan, mgmt,
12436 frame_len, rssi,
12437 GFP_KERNEL,
12438 bss_desc->scansystimensec);
Padma, Santhosh Kumar31bac742017-01-16 19:34:45 +053012439 pHddCtx->beacon_probe_rsp_cnt_per_scan++;
Mahesh Kumar Kalikot Veetil9c656182016-11-02 10:28:03 -070012440 qdf_mem_free(mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012441 return bss_status;
12442}
12443
12444/**
12445 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
12446 * @pAdapter: Pointer to adapter
12447 * @pRoamInfo: Pointer to roam info
12448 *
12449 * This function is used to update the BSS data base of CFG8011
12450 *
12451 * Return: struct cfg80211_bss pointer
12452 */
12453struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
12454 tCsrRoamInfo *pRoamInfo)
12455{
12456 tCsrRoamConnectedProfile roamProfile;
12457 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12458 struct cfg80211_bss *bss = NULL;
12459
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012460 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
12461 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
12462
12463 if (NULL != roamProfile.pBssDesc) {
12464 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12465 roamProfile.pBssDesc);
12466
12467 if (NULL == bss)
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012468 hdd_debug("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012469
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080012470 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012471 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012472 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012473 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012474 return bss;
12475}
12476/**
12477 * wlan_hdd_cfg80211_update_bss() - update bss
12478 * @wiphy: Pointer to wiphy
12479 * @pAdapter: Pointer to adapter
12480 * @scan_time: scan request timestamp
12481 *
12482 * Return: zero if success, non-zero otherwise
12483 */
12484int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
12485 hdd_adapter_t *pAdapter,
12486 uint32_t scan_time)
12487{
12488 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12489 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012490 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012491 tScanResultHandle pResult;
12492 struct cfg80211_bss *bss_status = NULL;
12493 hdd_context_t *pHddCtx;
12494 int ret;
12495
12496 ENTER();
12497
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012498 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12499 hdd_err("invalid session id: %d", pAdapter->sessionId);
12500 return -EINVAL;
12501 }
12502
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012503 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012504 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
12505 NO_SESSION, pAdapter->sessionId));
12506
12507 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12508 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012509 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012510 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012511
12512 /* start getting scan results and populate cgf80211 BSS database */
12513 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
12514
12515 /* no scan results */
12516 if (NULL == pResult) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012517 hdd_err("No scan result Status: %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053012518 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012519 }
12520
12521 pScanResult = sme_scan_result_get_first(hHal, pResult);
12522
12523 while (pScanResult) {
12524 /*
12525 * - cfg80211_inform_bss() is not updating ie field of bss
12526 * entry if entry already exists in bss data base of cfg80211
12527 * for that particular BSS ID. Using cfg80211_inform_bss_frame
12528 * to update thebss entry instead of cfg80211_inform_bss,
12529 * But this call expects mgmt packet as input. As of now
12530 * there is no possibility to get the mgmt(probe response)
12531 * frame from PE, converting bss_desc to
12532 * ieee80211_mgmt(probe response) and passing to c
12533 * fg80211_inform_bss_frame.
12534 * - Update BSS only if beacon timestamp is later than
12535 * scan request timestamp.
12536 */
12537 if ((scan_time == 0) ||
12538 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053012539 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012540 bss_status =
12541 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
12542 &pScanResult->BssDescriptor);
12543
12544 if (NULL == bss_status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012545 hdd_debug("NULL returned by cfg80211_inform_bss_frame");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012546 } else {
12547 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012548 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012549 bss_status);
12550 }
12551 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012552 hdd_debug("BSSID: " MAC_ADDRESS_STR " Skipped",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012553 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
12554 }
12555 pScanResult = sme_scan_result_get_next(hHal, pResult);
12556 }
12557
Archana Ramachandran2eb7a612017-03-23 22:58:42 -070012558 sme_scan_result_purge(pResult);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012559 /*
12560 * For SAP mode, scan is invoked by hostapd during SAP start
12561 * if hostapd is restarted, we need to flush previous scan
12562 * result so that it will reflect environment change
12563 */
Krunal Sonib4326f22016-03-10 13:05:51 -080012564 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012565#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
12566 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
12567#endif
12568 )
12569 sme_scan_flush_result(hHal);
12570
12571 EXIT();
12572 return 0;
12573}
12574
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012575/**
12576 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
12577 * @pAdapter: Pointer to adapter
12578 * @pRoamInfo: Pointer to roam info
12579 * @index: Index
12580 * @preauth: Preauth flag
12581 *
12582 * This function is used to notify the supplicant of a new PMKSA candidate.
12583 *
12584 * Return: 0 for success, non-zero for failure
12585 */
12586int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
12587 tCsrRoamInfo *pRoamInfo,
12588 int index, bool preauth)
12589{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012590 struct net_device *dev = pAdapter->dev;
12591 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
12592
12593 ENTER();
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012594 hdd_debug("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012595
12596 if (NULL == pRoamInfo) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012597 hdd_err("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012598 return -EINVAL;
12599 }
12600
12601 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012602 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012603 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
12604 cfg80211_pmksa_candidate_notify(dev, index,
12605 pRoamInfo->bssid.bytes,
12606 preauth, GFP_KERNEL);
12607 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012608 return 0;
12609}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012610
12611#ifdef FEATURE_WLAN_LFR_METRICS
12612/**
12613 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
12614 * @pAdapter: Pointer to adapter
12615 * @pRoamInfo: Pointer to roam info
12616 *
12617 * 802.11r/LFR metrics reporting function to report preauth initiation
12618 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012619 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012620 */
12621#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012622QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012623 tCsrRoamInfo *pRoamInfo)
12624{
12625 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12626 union iwreq_data wrqu;
12627
12628 ENTER();
12629
12630 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012631 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012632 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012633 }
12634
12635 /* create the event */
12636 memset(&wrqu, 0, sizeof(wrqu));
12637 memset(metrics_notification, 0, sizeof(metrics_notification));
12638
12639 wrqu.data.pointer = metrics_notification;
12640 wrqu.data.length = scnprintf(metrics_notification,
12641 sizeof(metrics_notification),
12642 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
12643 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12644
12645 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12646 metrics_notification);
12647
12648 EXIT();
12649
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012650 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012651}
12652
12653/**
12654 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12655 * @pAdapter: Pointer to adapter
12656 * @pRoamInfo: Pointer to roam info
12657 * @preauth_status: Preauth status
12658 *
12659 * 802.11r/LFR metrics reporting function to report handover initiation
12660 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012661 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012662 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012663QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012664wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
12665 tCsrRoamInfo *pRoamInfo,
12666 bool preauth_status)
12667{
12668 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12669 union iwreq_data wrqu;
12670
12671 ENTER();
12672
12673 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012674 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012675 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012676 }
12677
12678 /* create the event */
12679 memset(&wrqu, 0, sizeof(wrqu));
12680 memset(metrics_notification, 0, sizeof(metrics_notification));
12681
12682 scnprintf(metrics_notification, sizeof(metrics_notification),
12683 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
12684 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12685
12686 if (1 == preauth_status)
12687 strlcat(metrics_notification, " true",
12688 sizeof(metrics_notification));
12689 else
12690 strlcat(metrics_notification, " false",
12691 sizeof(metrics_notification));
12692
12693 wrqu.data.pointer = metrics_notification;
12694 wrqu.data.length = strlen(metrics_notification);
12695
12696 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12697 metrics_notification);
12698
12699 EXIT();
12700
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012701 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012702}
12703
12704/**
12705 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
12706 * @pAdapter: Pointer to adapter
12707 * @pRoamInfo: Pointer to roam info
12708 *
12709 * 802.11r/LFR metrics reporting function to report handover initiation
12710 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012711 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012712 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012713QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012714 tCsrRoamInfo *pRoamInfo)
12715{
12716 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
12717 union iwreq_data wrqu;
12718
12719 ENTER();
12720
12721 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012722 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012723 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012724 }
12725
12726 /* create the event */
12727 memset(&wrqu, 0, sizeof(wrqu));
12728 memset(metrics_notification, 0, sizeof(metrics_notification));
12729
12730 wrqu.data.pointer = metrics_notification;
12731 wrqu.data.length = scnprintf(metrics_notification,
12732 sizeof(metrics_notification),
12733 "QCOM: LFR_PREAUTH_HANDOVER "
12734 MAC_ADDRESS_STR,
12735 MAC_ADDR_ARRAY(pRoamInfo->bssid));
12736
12737 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
12738 metrics_notification);
12739
12740 EXIT();
12741
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012742 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012743}
12744#endif
12745
12746/**
12747 * hdd_select_cbmode() - select channel bonding mode
12748 * @pAdapter: Pointer to adapter
12749 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012750 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012751 *
12752 * Return: none
12753 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012754void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
12755 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012756{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012757 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012758 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012759 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012760
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012761 /*
12762 * CDS api expects secondary channel for calculating
12763 * the channel params
12764 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012765 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070012766 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
12767 if (operationChannel >= 1 && operationChannel <= 5)
12768 sec_ch = operationChannel + 4;
12769 else if (operationChannel >= 6 && operationChannel <= 13)
12770 sec_ch = operationChannel - 4;
12771 }
12772
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012773 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012774 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012775
12776 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012777 eHddDot11Mode hdd_dot11_mode;
12778 uint8_t iniDot11Mode =
12779 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
12780
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012781 hdd_debug("Dot11Mode is %u", iniDot11Mode);
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012782 switch (iniDot11Mode) {
12783 case eHDD_DOT11_MODE_AUTO:
Krishna Kumaar Natarajan4f1d7722017-03-03 21:12:51 -080012784 case eHDD_DOT11_MODE_11ax:
12785 case eHDD_DOT11_MODE_11ax_ONLY:
12786 if (sme_is_feature_supported_by_fw(DOT11AX))
12787 hdd_dot11_mode = eHDD_DOT11_MODE_11ax;
12788 else if (sme_is_feature_supported_by_fw(DOT11AC))
12789 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12790 else
12791 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12792 break;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012793 case eHDD_DOT11_MODE_11ac:
12794 case eHDD_DOT11_MODE_11ac_ONLY:
12795 if (sme_is_feature_supported_by_fw(DOT11AC))
12796 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
12797 else
12798 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12799 break;
12800 case eHDD_DOT11_MODE_11n:
12801 case eHDD_DOT11_MODE_11n_ONLY:
12802 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
12803 break;
12804 default:
12805 hdd_dot11_mode = iniDot11Mode;
12806 break;
12807 }
12808 ch_info->channel_width = ch_params->ch_width;
12809 ch_info->phy_mode =
12810 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012811 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012812 ch_info->cb_mode = ch_params->ch_width;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012813 hdd_debug("ch_info width %d, phymode %d channel %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070012814 ch_info->channel_width, ch_info->phy_mode,
12815 ch_info->channel);
12816 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012817}
12818
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012819/**
12820 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
12821 * @adapter: STA adapter
12822 * @roam_profile: STA roam profile
12823 *
12824 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
12825 *
12826 * Return: false if sta-sap conc is not allowed, else return true
12827 */
12828static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
12829 tCsrRoamProfile *roam_profile)
12830{
12831 hdd_context_t *hdd_ctx;
12832 hdd_adapter_t *ap_adapter;
12833 hdd_ap_ctx_t *hdd_ap_ctx;
12834 hdd_hostapd_state_t *hostapd_state;
12835 uint8_t channel = 0;
12836 QDF_STATUS status;
12837
12838 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
12839 if (!hdd_ctx) {
12840 hdd_err("HDD context is NULL");
12841 return true;
12842 }
12843
12844 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
12845 /* probably no sap running, no handling required */
12846 if (ap_adapter == NULL)
12847 return true;
12848
12849 /*
12850 * sap is not in started state, so it is fine to go ahead with sta.
12851 * if sap is currently doing CAC then don't allow sta to go further.
12852 */
12853 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
12854 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
12855 return true;
12856
12857 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
12858 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
12859 return false;
12860 }
12861
12862 /*
12863 * log and return error, if we allow STA to go through, we don't
12864 * know what is going to happen better stop sta connection
12865 */
12866 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
12867 if (NULL == hdd_ap_ctx) {
12868 hdd_err("AP context not found");
12869 return false;
12870 }
12871
12872 /* sap is on non-dfs channel, nothing to handle */
12873 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012874 hdd_debug("sap is on non-dfs channel, sta is allowed");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012875 return true;
12876 }
12877 /*
12878 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053012879 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012880 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080012881 status = policy_mgr_get_channel_from_scan_result(hdd_ctx->hdd_psoc,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012882 roam_profile, &channel);
12883
Nitesh Shah59774522016-09-16 15:14:21 +053012884 /*
12885 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
12886 * channels for roaming case.
12887 */
12888 if (CDS_IS_CHANNEL_24GHZ(channel)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080012889 hdd_debug("sap is on dfs, new sta conn on 2.4 is allowed");
Nitesh Shah59774522016-09-16 15:14:21 +053012890 return true;
12891 }
12892
12893 /*
12894 * If channel is 0 or DFS then better to call pcl and find out the
12895 * best channel. If channel is non-dfs 5 GHz then better move SAP
12896 * to STA's channel to make scc, so we have room for 3port MCC
12897 * scenario.
12898 */
12899 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080012900 channel = policy_mgr_get_nondfs_preferred_channel(
12901 hdd_ctx->hdd_psoc, PM_SAP_MODE, true);
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070012902
12903 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
12904 qdf_event_reset(&hostapd_state->qdf_event);
12905 status = wlansap_set_channel_change_with_csa(
12906 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
12907 hdd_ap_ctx->sapConfig.ch_width_orig);
12908
12909 if (QDF_STATUS_SUCCESS != status) {
12910 hdd_err("Set channel with CSA IE failed, can't allow STA");
12911 return false;
12912 }
12913
12914 /*
12915 * wait here for SAP to finish the channel switch. When channel
12916 * switch happens, SAP sends few beacons with CSA_IE. After
12917 * successfully Transmission of those beacons, it will move its
12918 * state from started to disconnected and move to new channel.
12919 * once it moves to new channel, sap again moves its state
12920 * machine from disconnected to started and set this event.
12921 * wait for 10 secs to finish this.
12922 */
12923 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
12924 if (!QDF_IS_STATUS_SUCCESS(status)) {
12925 hdd_err("wait for qdf_event failed, STA not allowed!!");
12926 return false;
12927 }
12928
12929 return true;
12930}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012931
Abhishek Singhcfb44482017-03-10 12:42:37 +053012932#ifdef WLAN_FEATURE_11W
12933/**
12934 * wlan_hdd_cfg80211_check_pmf_valid() - check if pmf status is ok
12935 * @roam_profile: pointer to roam profile
12936 *
12937 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
12938 * or pmf=2 is an explicit configuration in the supplicant
12939 * configuration, drop the connection request.
12940 *
12941 * Return: 0 if check result is valid, otherwise return error code
12942 */
12943static int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
12944{
12945 if (roam_profile->MFPEnabled &&
12946 !(roam_profile->MFPRequired ||
12947 roam_profile->MFPCapable)) {
12948 hdd_err("Drop connect req as supplicant has indicated PMF required for the non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
12949 roam_profile->MFPEnabled,
12950 roam_profile->MFPRequired,
12951 roam_profile->MFPCapable);
12952 return -EINVAL;
12953 }
12954 return 0;
12955}
12956#else
12957static inline
12958int wlan_hdd_cfg80211_check_pmf_valid(tCsrRoamProfile *roam_profile)
12959{
12960 return 0;
12961}
12962#endif
12963
Krunal Soni31949422016-07-29 17:17:53 -070012964/**
12965 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012966 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070012967 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012968 * @ssid_len: Length of ssid
12969 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070012970 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012971 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012972 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012973 *
12974 * This function is used to start the association process
12975 *
12976 * Return: 0 for success, non-zero for failure
12977 */
Krunal Soni31949422016-07-29 17:17:53 -070012978static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012979 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070012980 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012981 u8 operatingChannel,
12982 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012983{
12984 int status = 0;
Rajeev Kumard31e1542017-01-13 14:37:42 -080012985 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012986 hdd_wext_state_t *pWextState;
12987 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012988 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012989 uint32_t roamId;
12990 tCsrRoamProfile *pRoamProfile;
12991 eCsrAuthType RSNAuthType;
12992 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053012993 uint8_t channel = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012994
12995 ENTER();
12996
12997 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12998 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053012999 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013000
13001 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013002 if (status)
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013003 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013004
13005 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013006 hdd_err("wrong SSID len");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013007 status = -EINVAL;
13008 goto ret_status;
13009 }
13010
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013011 if (true == hdd_is_connection_in_progress(NULL, NULL)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013012 hdd_err("Connection refused: conn in progress");
13013 status = -EINVAL;
13014 goto ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013015 }
13016
Nitesh Shah273e4e52017-04-03 12:53:36 +053013017 wlan_hdd_tdls_disable_offchan_and_teardown_links(pHddCtx);
13018
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013019 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053013020 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
13021 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013022
13023 if (pRoamProfile) {
13024 hdd_station_ctx_t *pHddStaCtx;
13025 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13026
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013027 /* Restart the opportunistic timer
13028 *
13029 * If hw_mode_change_in_progress is true, then wait
13030 * till firmware sends the callback for hw_mode change.
13031 *
13032 * Else set connect_in_progress as true and proceed.
13033 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013034 policy_mgr_restart_opportunistic_timer(
13035 pHddCtx->hdd_psoc, false);
13036 if (policy_mgr_is_hw_mode_change_in_progress(
13037 pHddCtx->hdd_psoc)) {
13038 status = policy_mgr_wait_for_connection_update(
13039 pHddCtx->hdd_psoc);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013040 if (!QDF_IS_STATUS_SUCCESS(status)) {
13041 hdd_err("qdf wait for event failed!!");
13042 status = -EINVAL;
13043 goto ret_status;
13044 }
13045 }
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013046 hdd_set_connection_in_progress(true);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013047
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013048 if (HDD_WMM_USER_MODE_NO_QOS ==
13049 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
13050 /*QoS not enabled in cfg file */
13051 pRoamProfile->uapsd_mask = 0;
13052 } else {
13053 /*QoS enabled, update uapsd mask from cfg file */
13054 pRoamProfile->uapsd_mask =
13055 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
13056 }
13057
13058 pRoamProfile->SSIDs.numOfSSIDs = 1;
13059 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013060 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013061 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013062 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013063 ssid, ssid_len);
13064
Deepak Dhamdherea2785822016-11-17 01:17:45 -080013065 pRoamProfile->do_not_roam = !pAdapter->fast_roaming_allowed;
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013066 /* cleanup bssid hint */
13067 qdf_mem_zero(pRoamProfile->bssid_hint.bytes,
13068 QDF_MAC_ADDR_SIZE);
13069 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
13070 QDF_MAC_ADDR_SIZE);
13071
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013072 if (bssid) {
13073 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053013074 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013075 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013076 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013077 /*
13078 * Save BSSID in seperate variable as
13079 * pRoamProfile's BSSID is getting zeroed out in the
13080 * association process. In case of join failure
13081 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013082 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013083 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013084 bssid, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013085 hdd_debug("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013086 } else if (bssid_hint) {
Abhishek Singh3c9910e2017-01-06 17:56:47 +053013087 qdf_mem_copy(pRoamProfile->bssid_hint.bytes,
13088 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070013089 /*
13090 * Save BSSID in a separate variable as
13091 * pRoamProfile's BSSID is getting zeroed out in the
13092 * association process. In case of join failure
13093 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013094 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013095 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053013096 bssid_hint, QDF_MAC_ADDR_SIZE);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013097 hdd_debug("bssid_hint is given by upper layer %pM",
Krunal Soni35b404c2016-07-14 23:36:00 -070013098 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013099 }
13100
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013101 hdd_debug("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013102 pRoamProfile->SSIDs.SSIDList->SSID.length,
13103 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
13104 operatingChannel);
13105
13106 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
13107 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013108 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013109 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
13110 }
13111#ifdef FEATURE_WLAN_WAPI
13112 if (pAdapter->wapi_info.nWapiMode) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013113 hdd_debug("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013114 switch (pAdapter->wapi_info.wapiAuthMode) {
13115 case WAPI_AUTH_MODE_PSK:
13116 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013117 hdd_debug("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013118 pAdapter->wapi_info.wapiAuthMode);
13119 pRoamProfile->AuthType.authType[0] =
13120 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
13121 break;
13122 }
13123 case WAPI_AUTH_MODE_CERT:
13124 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013125 hdd_debug("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013126 pAdapter->wapi_info.wapiAuthMode);
13127 pRoamProfile->AuthType.authType[0] =
13128 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
13129 break;
13130 }
13131 } /* End of switch */
13132 if (pAdapter->wapi_info.wapiAuthMode ==
13133 WAPI_AUTH_MODE_PSK
13134 || pAdapter->wapi_info.wapiAuthMode ==
13135 WAPI_AUTH_MODE_CERT) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013136 hdd_debug("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013137 pRoamProfile->AuthType.numEntries = 1;
13138 pRoamProfile->EncryptionType.numEntries = 1;
13139 pRoamProfile->EncryptionType.encryptionType[0] =
13140 eCSR_ENCRYPT_TYPE_WPI;
13141 pRoamProfile->mcEncryptionType.numEntries = 1;
13142 pRoamProfile->mcEncryptionType.
13143 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
13144 }
13145 }
Krunal Soni31949422016-07-29 17:17:53 -070013146#endif
Mukul Sharma3d36c392017-01-18 18:39:12 +053013147 pmo_ucfg_flush_gtk_offload_req(pAdapter->hdd_vdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013148 pRoamProfile->csrPersona = pAdapter->device_mode;
13149
13150 if (operatingChannel) {
13151 pRoamProfile->ChannelInfo.ChannelList =
13152 &operatingChannel;
13153 pRoamProfile->ChannelInfo.numOfChannels = 1;
13154 } else {
13155 pRoamProfile->ChannelInfo.ChannelList = NULL;
13156 pRoamProfile->ChannelInfo.numOfChannels = 0;
13157 }
Krunal Sonib4326f22016-03-10 13:05:51 -080013158 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013159 && operatingChannel) {
13160 /*
13161 * Need to post the IBSS power save parameters
13162 * to WMA. WMA will configure this parameters
13163 * to firmware if power save is enabled by the
13164 * firmware.
13165 */
13166 status = hdd_set_ibss_power_save_params(pAdapter);
13167
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013168 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013169 hdd_err("Set IBSS Power Save Params Failed");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013170 status = -EINVAL;
13171 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013172 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013173 pRoamProfile->ch_params.ch_width =
13174 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053013175 /*
13176 * In IBSS mode while operating in 2.4 GHz,
13177 * the device supports only 20 MHz.
13178 */
13179 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
13180 pRoamProfile->ch_params.ch_width =
13181 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013182 hdd_select_cbmode(pAdapter, operatingChannel,
13183 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013184 }
13185
Abhishek Singhcfb44482017-03-10 12:42:37 +053013186 if (wlan_hdd_cfg80211_check_pmf_valid(
13187 &pWextState->roamProfile)) {
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013188 status = -EINVAL;
13189 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013190 }
13191
Krunal Soni31949422016-07-29 17:17:53 -070013192 /*
13193 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013194 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070013195 * enhancements, the supplicant is not issuing the scan command
13196 * now. So the unicast frames which are sent from the host are
13197 * not having the additional IEs. If it is P2P CLIENT and there
13198 * is no additional IE present in roamProfile, then use the
13199 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013200 */
13201
Krunal Sonib4326f22016-03-10 13:05:51 -080013202 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013203 (!pRoamProfile->pAddIEScan)) {
13204 pRoamProfile->pAddIEScan =
13205 &pAdapter->scan_info.scanAddIE.addIEdata[0];
13206 pRoamProfile->nAddIEScanLength =
13207 pAdapter->scan_info.scanAddIE.length;
13208 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013209
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013210 if ((policy_mgr_is_hw_dbs_capable(pHddCtx->hdd_psoc) == true)
13211 && (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013212 pRoamProfile))) {
13213 hdd_err("sap-sta conc will fail, can't allow sta");
13214 hdd_conn_set_connection_state(pAdapter,
13215 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013216 status = -ENOMEM;
13217 goto conn_failure;
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013218 }
13219
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013220 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013221 if (!sme_config) {
13222 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070013223 hdd_conn_set_connection_state(pAdapter,
13224 eConnectionState_NotConnected);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013225 status = -ENOMEM;
13226 goto conn_failure;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013227 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013228 sme_get_config_param(pHddCtx->hHal, sme_config);
13229 /* These values are not sessionized. So, any change in these SME
13230 * configs on an older or parallel interface will affect the
13231 * cb mode. So, restoring the default INI params before starting
13232 * interfaces such as sta, cli etc.,
13233 */
13234 sme_config->csrConfig.channelBondingMode5GHz =
13235 pHddCtx->config->nChannelBondingMode5GHz;
13236 sme_config->csrConfig.channelBondingMode24GHz =
13237 pHddCtx->config->nChannelBondingMode24GHz;
13238 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013239 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053013240 /*
13241 * Change conn_state to connecting before sme_roam_connect(),
13242 * because sme_roam_connect() has a direct path to call
13243 * hdd_sme_roam_callback(), which will change the conn_state
13244 * If direct path, conn_state will be accordingly changed to
13245 * NotConnected or Associated by either
13246 * hdd_association_completion_handler() or
13247 * hdd_dis_connect_handler() in sme_RoamCallback()if
13248 * sme_RomConnect is to be queued,
13249 * Connecting state will remain until it is completed.
13250 *
13251 * If connection state is not changed, connection state will
13252 * remain in eConnectionState_NotConnected state.
13253 * In hdd_association_completion_handler, "hddDisconInProgress"
13254 * is set to true if conn state is
13255 * eConnectionState_NotConnected.
13256 * If "hddDisconInProgress" is set to true then cfg80211 layer
13257 * is not informed of connect result indication which
13258 * is an issue.
13259 */
13260 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013261 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053013262 hdd_conn_set_connection_state(pAdapter,
13263 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013264
Komal Seelama89be8d2016-09-29 11:09:26 +053013265 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
13266 connect);
Rajeev Kumard31e1542017-01-13 14:37:42 -080013267 qdf_status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013268 pAdapter->sessionId, pRoamProfile,
13269 &roamId);
13270
Rajeev Kumard31e1542017-01-13 14:37:42 -080013271 if ((QDF_STATUS_SUCCESS != qdf_status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080013272 (QDF_STA_MODE == pAdapter->device_mode ||
13273 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013274 hdd_err("sme_roam_connect (session %d) failed with "
Rajeev Kumard31e1542017-01-13 14:37:42 -080013275 "qdf_status %d. -> NotConnected",
13276 pAdapter->sessionId, qdf_status);
13277 status = qdf_status_to_os_return(qdf_status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013278 /* change back to NotAssociated */
13279 hdd_conn_set_connection_state(pAdapter,
13280 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053013281 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
13282 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013283 }
13284
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013285 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013286 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013287
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013288 pRoamProfile->ChannelInfo.ChannelList = NULL;
13289 pRoamProfile->ChannelInfo.numOfChannels = 0;
13290
Nitesh Shah044fd672016-10-13 18:53:25 +053013291 if ((QDF_STA_MODE == pAdapter->device_mode)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013292 && policy_mgr_is_current_hwmode_dbs(pHddCtx->hdd_psoc)
13293 && !policy_mgr_is_hw_dbs_2x2_capable(
13294 pHddCtx->hdd_psoc)) {
13295 policy_mgr_get_channel_from_scan_result(
13296 pHddCtx->hdd_psoc,
13297 pRoamProfile, &channel);
Archana Ramachandrancc0ffb12017-02-17 18:30:43 -080013298 hdd_info("Move to single MAC mode(optimization) if applicable");
Nitesh Shah044fd672016-10-13 18:53:25 +053013299 if (channel)
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013300 policy_mgr_checkn_update_hw_mode_single_mac_mode(
13301 pHddCtx->hdd_psoc, channel);
Nitesh Shah044fd672016-10-13 18:53:25 +053013302 }
13303
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013304 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013305 hdd_err("No valid Roam profile");
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013306 status = -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013307 }
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013308 goto ret_status;
13309
13310conn_failure:
13311 /* Reset connect_in_progress */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080013312 hdd_set_connection_in_progress(false);
Nitesh Shaha3dfea32017-02-09 19:18:57 +053013313
13314ret_status:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013315 EXIT();
13316 return status;
13317}
13318
13319/**
13320 * wlan_hdd_cfg80211_set_auth_type() - set auth type
13321 * @pAdapter: Pointer to adapter
13322 * @auth_type: Auth type
13323 *
13324 * This function is used to set the authentication type (OPEN/SHARED).
13325 *
13326 * Return: 0 for success, non-zero for failure
13327 */
13328static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
13329 enum nl80211_auth_type auth_type)
13330{
13331 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13332 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13333
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013334 /*set authentication type */
13335 switch (auth_type) {
13336 case NL80211_AUTHTYPE_AUTOMATIC:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013337 hdd_debug("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013338 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
13339 break;
13340
13341 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013342 case NL80211_AUTHTYPE_FT:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013343 hdd_debug("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013344 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13345 break;
13346
13347 case NL80211_AUTHTYPE_SHARED_KEY:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013348 hdd_debug("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013349 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
13350 break;
13351#ifdef FEATURE_WLAN_ESE
13352 case NL80211_AUTHTYPE_NETWORK_EAP:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013353 hdd_debug("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013354 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
13355 break;
13356#endif
13357
13358 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013359 hdd_err("Unsupported authentication type: %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013360 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
13361 return -EINVAL;
13362 }
13363
13364 pWextState->roamProfile.AuthType.authType[0] =
13365 pHddStaCtx->conn_info.authType;
13366 return 0;
13367}
13368
13369/**
13370 * wlan_hdd_set_akm_suite() - set key management type
13371 * @pAdapter: Pointer to adapter
13372 * @key_mgmt: Key management type
13373 *
13374 * This function is used to set the key mgmt type(PSK/8021x).
13375 *
13376 * Return: 0 for success, non-zero for failure
13377 */
13378static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
13379{
13380 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13381
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013382#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
13383#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
13384 /*set key mgmt type */
13385 switch (key_mgmt) {
13386 case WLAN_AKM_SUITE_PSK:
13387 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013388 case WLAN_AKM_SUITE_FT_PSK:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013389 hdd_debug("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013390 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
13391 break;
13392
13393 case WLAN_AKM_SUITE_8021X_SHA256:
13394 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013395 case WLAN_AKM_SUITE_FT_8021X:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013396 hdd_debug("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013397 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13398 break;
13399#ifdef FEATURE_WLAN_ESE
13400#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
13401#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
13402 case WLAN_AKM_SUITE_CCKM:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013403 hdd_debug("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013404 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
13405 break;
13406#endif
13407#ifndef WLAN_AKM_SUITE_OSEN
13408#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
13409#endif
13410 case WLAN_AKM_SUITE_OSEN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013411 hdd_debug("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013412 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
13413 break;
13414
13415 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013416 hdd_err("Unsupported key mgmt type: %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013417 return -EINVAL;
13418
13419 }
13420 return 0;
13421}
13422
13423/**
13424 * wlan_hdd_cfg80211_set_cipher() - set encryption type
13425 * @pAdapter: Pointer to adapter
13426 * @cipher: Cipher type
13427 * @ucast: Unicast flag
13428 *
13429 * This function is used to set the encryption type
13430 * (NONE/WEP40/WEP104/TKIP/CCMP).
13431 *
13432 * Return: 0 for success, non-zero for failure
13433 */
13434static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
13435 u32 cipher, bool ucast)
13436{
13437 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13438 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13439 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13440
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013441 if (!cipher) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013442 hdd_debug("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013443 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13444 } else {
13445
13446 /*set encryption method */
13447 switch (cipher) {
13448 case IW_AUTH_CIPHER_NONE:
13449 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13450 break;
13451
13452 case WLAN_CIPHER_SUITE_WEP40:
13453 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
13454 break;
13455
13456 case WLAN_CIPHER_SUITE_WEP104:
13457 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
13458 break;
13459
13460 case WLAN_CIPHER_SUITE_TKIP:
13461 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
13462 break;
13463
13464 case WLAN_CIPHER_SUITE_CCMP:
13465 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13466 break;
13467#ifdef FEATURE_WLAN_WAPI
13468 case WLAN_CIPHER_SUITE_SMS4:
13469 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
13470 break;
13471#endif
13472
13473#ifdef FEATURE_WLAN_ESE
13474 case WLAN_CIPHER_SUITE_KRK:
13475 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
13476 break;
13477#ifdef WLAN_FEATURE_ROAM_OFFLOAD
13478 case WLAN_CIPHER_SUITE_BTK:
13479 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
13480 break;
13481#endif
13482#endif
13483 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013484 hdd_err("Unsupported cipher type: %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013485 return -EOPNOTSUPP;
13486 }
13487 }
13488
13489 if (ucast) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013490 hdd_debug("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013491 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13492 pWextState->roamProfile.EncryptionType.numEntries = 1;
13493 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13494 encryptionType;
13495 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013496 hdd_debug("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013497 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
13498 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
13499 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
13500 encryptionType;
13501 }
13502
13503 return 0;
13504}
13505
13506/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013507 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
13508 * @wext_state: Pointer to wext state
13509 * @gen_ie: Pointer to IE data
13510 * @len: length of IE data
13511 *
13512 * Return: 0 for success, non-zero for failure
13513 */
13514static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
13515 const uint8_t *gen_ie, uint16_t len)
13516{
13517 uint16_t cur_add_ie_len =
13518 wext_state->assocAddIE.length;
13519
13520 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13521 (wext_state->assocAddIE.length + len)) {
13522 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
13523 QDF_ASSERT(0);
13524 return -ENOMEM;
13525 }
13526 memcpy(wext_state->assocAddIE.addIEdata +
13527 cur_add_ie_len, gen_ie, len);
13528 wext_state->assocAddIE.length += len;
13529
13530 wext_state->roamProfile.pAddIEAssoc =
13531 wext_state->assocAddIE.addIEdata;
13532 wext_state->roamProfile.nAddIEAssocLength =
13533 wext_state->assocAddIE.length;
13534 return 0;
13535}
13536
13537/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013538 * wlan_hdd_cfg80211_set_ie() - set IEs
13539 * @pAdapter: Pointer to adapter
13540 * @ie: Pointer ot ie
13541 * @ie: IE length
13542 *
13543 * Return: 0 for success, non-zero for failure
13544 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013545static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013546 size_t ie_len)
13547{
13548 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13549 const uint8_t *genie = ie;
13550 uint16_t remLen = ie_len;
13551#ifdef FEATURE_WLAN_WAPI
13552 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
13553 u16 *tmp;
13554 uint16_t akmsuiteCount;
13555 int *akmlist;
13556#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013557 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013558
13559 /* clear previous assocAddIE */
13560 pWextState->assocAddIE.length = 0;
13561 pWextState->roamProfile.bWPSAssociation = false;
13562 pWextState->roamProfile.bOSENAssociation = false;
13563
13564 while (remLen >= 2) {
13565 uint16_t eLen = 0;
13566 uint8_t elementId;
13567 elementId = *genie++;
13568 eLen = *genie++;
13569 remLen -= 2;
13570
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013571 hdd_debug("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013572
13573 switch (elementId) {
13574 case DOT11F_EID_WPA:
13575 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 -070013576 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013577 return -EINVAL;
13578 } else if (0 ==
13579 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
13580 uint16_t curAddIELen =
13581 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013582 hdd_debug("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013583
13584 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13585 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013586 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013587 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013588 return -ENOMEM;
13589 }
13590 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13591 memcpy(pWextState->assocAddIE.addIEdata +
13592 curAddIELen, genie - 2, eLen + 2);
13593 pWextState->assocAddIE.length += eLen + 2;
13594
13595 pWextState->roamProfile.bWPSAssociation = true;
13596 pWextState->roamProfile.pAddIEAssoc =
13597 pWextState->assocAddIE.addIEdata;
13598 pWextState->roamProfile.nAddIEAssocLength =
13599 pWextState->assocAddIE.length;
13600 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013601 hdd_debug("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013602 memset(pWextState->WPARSNIE, 0,
13603 MAX_WPA_RSN_IE_LEN);
13604 memcpy(pWextState->WPARSNIE, genie - 2,
13605 (eLen + 2));
13606 pWextState->roamProfile.pWPAReqIE =
13607 pWextState->WPARSNIE;
13608 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
13609 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
13610 P2P_OUI_TYPE_SIZE))) {
13611 uint16_t curAddIELen =
13612 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013613 hdd_debug("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013614
13615 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13616 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013617 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013618 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013619 return -ENOMEM;
13620 }
13621 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
13622 memcpy(pWextState->assocAddIE.addIEdata +
13623 curAddIELen, genie - 2, eLen + 2);
13624 pWextState->assocAddIE.length += eLen + 2;
13625
13626 pWextState->roamProfile.pAddIEAssoc =
13627 pWextState->assocAddIE.addIEdata;
13628 pWextState->roamProfile.nAddIEAssocLength =
13629 pWextState->assocAddIE.length;
13630 }
13631#ifdef WLAN_FEATURE_WFD
13632 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
13633 WFD_OUI_TYPE_SIZE)) &&
13634 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080013635 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013636 pAdapter->device_mode)) {
13637 uint16_t curAddIELen =
13638 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013639 hdd_debug("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013640
13641 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13642 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013643 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013644 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013645 return -ENOMEM;
13646 }
13647 /* WFD IE is saved to Additional IE ; it should
13648 * be accumulated to handle WPS IE + P2P IE +
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013649 * WFD IE
13650 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013651 memcpy(pWextState->assocAddIE.addIEdata +
13652 curAddIELen, genie - 2, eLen + 2);
13653 pWextState->assocAddIE.length += eLen + 2;
13654
13655 pWextState->roamProfile.pAddIEAssoc =
13656 pWextState->assocAddIE.addIEdata;
13657 pWextState->roamProfile.nAddIEAssocLength =
13658 pWextState->assocAddIE.length;
13659 }
13660#endif
13661 /* Appending HS 2.0 Indication Element in Assiciation Request */
13662 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
13663 HS20_OUI_TYPE_SIZE))) {
13664 uint16_t curAddIELen =
13665 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013666 hdd_debug("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013667
13668 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13669 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013670 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013671 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013672 return -ENOMEM;
13673 }
13674 memcpy(pWextState->assocAddIE.addIEdata +
13675 curAddIELen, genie - 2, eLen + 2);
13676 pWextState->assocAddIE.length += eLen + 2;
13677
13678 pWextState->roamProfile.pAddIEAssoc =
13679 pWextState->assocAddIE.addIEdata;
13680 pWextState->roamProfile.nAddIEAssocLength =
13681 pWextState->assocAddIE.length;
13682 }
13683 /* Appending OSEN Information Element in Assiciation Request */
13684 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
13685 OSEN_OUI_TYPE_SIZE))) {
13686 uint16_t curAddIELen =
13687 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013688 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013689
13690 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13691 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013692 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013693 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013694 return -ENOMEM;
13695 }
13696 memcpy(pWextState->assocAddIE.addIEdata +
13697 curAddIELen, genie - 2, eLen + 2);
13698 pWextState->assocAddIE.length += eLen + 2;
13699
13700 pWextState->roamProfile.bOSENAssociation = true;
13701 pWextState->roamProfile.pAddIEAssoc =
13702 pWextState->assocAddIE.addIEdata;
13703 pWextState->roamProfile.nAddIEAssocLength =
13704 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013705 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
13706 MBO_OUI_TYPE_SIZE))){
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013707 hdd_debug("Set MBO IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013708 status = wlan_hdd_add_assoc_ie(pWextState,
13709 genie - 2, eLen + 2);
13710 if (status)
13711 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013712 } else {
13713 uint16_t add_ie_len =
13714 pWextState->assocAddIE.length;
13715
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013716 hdd_debug("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013717
13718 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13719 (pWextState->assocAddIE.length + eLen)) {
13720 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013721 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013722 return -ENOMEM;
13723 }
13724
13725 memcpy(pWextState->assocAddIE.addIEdata +
13726 add_ie_len, genie - 2, eLen + 2);
13727 pWextState->assocAddIE.length += eLen + 2;
13728
13729 pWextState->roamProfile.pAddIEAssoc =
13730 pWextState->assocAddIE.addIEdata;
13731 pWextState->roamProfile.nAddIEAssocLength =
13732 pWextState->assocAddIE.length;
13733 }
13734 break;
13735 case DOT11F_EID_RSN:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013736 hdd_debug("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013737 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
13738 memcpy(pWextState->WPARSNIE, genie - 2,
13739 (eLen + 2));
13740 pWextState->roamProfile.pRSNReqIE =
13741 pWextState->WPARSNIE;
13742 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
13743 break;
13744 /*
13745 * Appending Extended Capabilities with Interworking bit set
13746 * in Assoc Req.
13747 *
13748 * In assoc req this EXT Cap will only be taken into account if
13749 * interworkingService bit is set to 1. Currently
13750 * driver is only interested in interworkingService capability
13751 * from supplicant. If in future any other EXT Cap info is
13752 * required from supplicat, it needs to be handled while
13753 * sending Assoc Req in LIM.
13754 */
13755 case DOT11F_EID_EXTCAP:
13756 {
13757 uint16_t curAddIELen =
13758 pWextState->assocAddIE.length;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013759 hdd_debug("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013760
13761 if (SIR_MAC_MAX_ADD_IE_LENGTH <
13762 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070013763 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013764 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013765 return -ENOMEM;
13766 }
13767 memcpy(pWextState->assocAddIE.addIEdata +
13768 curAddIELen, genie - 2, eLen + 2);
13769 pWextState->assocAddIE.length += eLen + 2;
13770
13771 pWextState->roamProfile.pAddIEAssoc =
13772 pWextState->assocAddIE.addIEdata;
13773 pWextState->roamProfile.nAddIEAssocLength =
13774 pWextState->assocAddIE.length;
13775 break;
13776 }
13777#ifdef FEATURE_WLAN_WAPI
13778 case WLAN_EID_WAPI:
13779 /* Setting WAPI Mode to ON=1 */
13780 pAdapter->wapi_info.nWapiMode = 1;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013781 hdd_debug("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013782 tmp = (u16 *) ie;
13783 tmp = tmp + 2; /* Skip element Id and Len, Version */
13784 akmsuiteCount = WPA_GET_LE16(tmp);
13785 tmp = tmp + 1;
13786 akmlist = (int *)(tmp);
13787 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
13788 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
13789 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013790 hdd_err("Invalid akmSuite count: %u",
13791 akmsuiteCount);
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013792 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013793 return -EINVAL;
13794 }
13795
13796 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013797 hdd_debug("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013798 pAdapter->wapi_info.wapiAuthMode =
13799 WAPI_AUTH_MODE_PSK;
13800 }
13801 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013802 hdd_debug("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013803 pAdapter->wapi_info.wapiAuthMode =
13804 WAPI_AUTH_MODE_CERT;
13805 }
13806 break;
13807#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013808 case DOT11F_EID_SUPPOPERATINGCLASSES:
13809 {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013810 hdd_debug("Set Supported Operating Classes IE(len %d)", eLen + 2);
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053013811 status = wlan_hdd_add_assoc_ie(pWextState,
13812 genie - 2, eLen + 2);
13813 if (status)
13814 return status;
13815 break;
13816 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013817 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013818 hdd_err("Set UNKNOWN IE: %X", elementId);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080013819 /* when Unknown IE is received we break
13820 * and continue to the next IE in the buffer
13821 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013822 break;
13823 }
13824 genie += eLen;
13825 remLen -= eLen;
13826 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013827 return 0;
13828}
13829
13830/**
13831 * hdd_is_wpaie_present() - check for WPA ie
13832 * @ie: Pointer to ie
13833 * @ie_len: Ie length
13834 *
13835 * Parse the received IE to find the WPA IE
13836 *
13837 * Return: true if wpa ie is found else false
13838 */
13839static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
13840{
13841 uint8_t eLen = 0;
13842 uint16_t remLen = ie_len;
13843 uint8_t elementId = 0;
13844
13845 while (remLen >= 2) {
13846 elementId = *ie++;
13847 eLen = *ie++;
13848 remLen -= 2;
13849 if (eLen > remLen) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013850 hdd_err("Invalid IE length: %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013851 return false;
13852 }
13853 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
13854 /* OUI - 0x00 0X50 0XF2
13855 * WPA Information Element - 0x01
13856 * WPA version - 0x01
13857 */
13858 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
13859 return true;
13860 }
13861 ie += eLen;
13862 remLen -= eLen;
13863 }
13864 return false;
13865}
13866
13867/**
13868 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
13869 * @pAdapter: Pointer to adapter
13870 * @req: Pointer to security parameters
13871 *
13872 * Return: 0 for success, non-zero for failure
13873 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013874static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
13875 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013876{
13877 int status = 0;
13878 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13879 ENTER();
13880
13881 /*set wpa version */
13882 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
13883
13884 if (req->crypto.wpa_versions) {
13885 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
13886 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
13887 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
13888 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13889 }
13890 }
13891
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013892 hdd_debug("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013893
13894 /*set authentication type */
13895 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
13896
13897 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013898 hdd_err("Failed to set authentication type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013899 return status;
13900 }
13901
13902 /*set key mgmt type */
13903 if (req->crypto.n_akm_suites) {
13904 status =
13905 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
13906 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013907 hdd_err("Failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013908 return status;
13909 }
13910 }
13911
13912 /*set pairwise cipher type */
13913 if (req->crypto.n_ciphers_pairwise) {
13914 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
13915 req->crypto.
13916 ciphers_pairwise[0],
13917 true);
13918 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013919 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013920 return status;
13921 }
13922 } else {
13923 /*Reset previous cipher suite to none */
13924 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
13925 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013926 hdd_err("Failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013927 return status;
13928 }
13929 }
13930
13931 /*set group cipher type */
13932 status =
13933 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
13934 false);
13935
13936 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013937 hdd_err("Failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013938 return status;
13939 }
13940#ifdef WLAN_FEATURE_11W
13941 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
13942#endif
13943
13944 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
13945 if (req->ie_len) {
13946 status =
13947 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
13948 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013949 hdd_err("Failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013950 return status;
13951 }
13952 }
13953
13954 /*incase of WEP set default key information */
13955 if (req->key && req->key_len) {
Jeff Johnson68755312017-02-10 11:46:55 -080013956 u8 key_len = req->key_len;
13957 u8 key_idx = req->key_idx;
13958
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013959 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
13960 || (WLAN_CIPHER_SUITE_WEP104 ==
13961 req->crypto.ciphers_pairwise[0])
13962 ) {
13963 if (IW_AUTH_KEY_MGMT_802_1X
13964 ==
13965 (pWextState->
13966 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013967 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013968 return -EOPNOTSUPP;
Jeff Johnson68755312017-02-10 11:46:55 -080013969 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013970
Jeff Johnson68755312017-02-10 11:46:55 -080013971 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len)
13972 && (CSR_MAX_NUM_KEY > key_idx)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080013973 hdd_debug("setting default wep key, key_idx = %hu key_len %hu",
Jeff Johnson68755312017-02-10 11:46:55 -080013974 key_idx, key_len);
13975 qdf_mem_copy(&pWextState->roamProfile.
13976 Keys.
13977 KeyMaterial[key_idx][0],
13978 req->key, key_len);
13979 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013980 KeyLength[key_idx] = (u8) key_len;
Jeff Johnson68755312017-02-10 11:46:55 -080013981 pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013982 defaultIndex = (u8) key_idx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013983 }
13984 }
13985 }
13986
13987 return status;
13988}
13989
Agrawal Ashish3d000b42017-02-07 13:44:50 +053013990int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013991{
13992 unsigned long rc;
13993 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053013994 int status, result = 0;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080013995 tHalHandle hal;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013996
13997 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080013998 hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13999 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014000 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014001 sme_stop_roaming(hal, pAdapter->sessionId, eCsrHddIssued);
14002 }
14003 /*
14004 * If firmware has already started roaming process, driver
14005 * needs to defer the processing of this disconnect request.
14006 *
14007 */
14008 if (hdd_is_roaming_in_progress(pAdapter)) {
14009 /*
14010 * Defer the disconnect action until firmware roaming
14011 * result is received. If STA is in connected state after
14012 * that, send the disconnect command to CSR, otherwise
14013 * CSR would have already sent disconnect event to upper
14014 * layer.
14015 */
14016
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014017 hdd_warn("Roaming in progress, <try disconnect> deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014018 pAdapter->defer_disconnect = DEFER_DISCONNECT_TRY_DISCONNECT;
14019 pAdapter->cfg80211_disconnect_reason =
14020 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14021 return 0;
14022 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014023
Jeff Johnson9edf9572016-10-03 15:24:49 -070014024 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053014025 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
14026 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
14027 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014028 hdd_conn_set_connection_state(pAdapter,
14029 eConnectionState_Disconnecting);
14030 /* Issue disconnect to CSR */
14031 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014032
14033 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14034 pAdapter->sessionId,
14035 eCSR_DISCONNECT_REASON_UNSPECIFIED);
14036 /*
14037 * Wait here instead of returning directly, this will block the
14038 * next connect command and allow processing of the scan for
14039 * ssid and the previous connect command in CSR. Else we might
14040 * hit some race conditions leading to SME and HDD out of sync.
14041 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014042 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014043 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014044 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014045 hdd_err("sme_roam_disconnect failure, status: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014046 (int)status);
14047 pHddStaCtx->staDebugState = status;
14048 result = -EINVAL;
14049 goto disconnected;
14050 }
14051
14052 rc = wait_for_completion_timeout(
14053 &pAdapter->disconnect_comp_var,
14054 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014055 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014056 hdd_err("Sme disconnect event timed out session Id: %d staDebugState: %d",
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014057 pAdapter->sessionId, pHddStaCtx->staDebugState);
14058 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014059 }
14060 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014061 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014062 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014063 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014064 if (!rc) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014065 hdd_err("Disconnect event timed out session Id: %d staDebugState: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014066 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014067 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014068 }
14069 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014070disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053014071 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14072 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014073}
14074
14075/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014076 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
14077 * @adapter: Pointer to the HDD adapter
14078 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070014079 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014080 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014081 * This function will start reassociation if prev_bssid is set and bssid/
14082 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014083 *
Naveen Rawat07332902016-07-27 09:13:17 -070014084 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014085 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053014086#if defined(CFG80211_CONNECT_PREV_BSSID) || \
14087 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070014088static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14089 struct cfg80211_connect_params *req,
14090 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014091{
Naveen Rawat07332902016-07-27 09:13:17 -070014092 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014093 const uint8_t *bssid = NULL;
14094 uint16_t channel = 0;
14095
14096 if (req->bssid)
14097 bssid = req->bssid;
14098 else if (req->bssid_hint)
14099 bssid = req->bssid_hint;
14100
14101 if (req->channel)
14102 channel = req->channel->hw_value;
14103 else if (req->channel_hint)
14104 channel = req->channel_hint->hw_value;
14105
14106 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070014107 reassoc = true;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014108 hdd_debug(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053014109 channel, MAC_ADDR_ARRAY(bssid));
14110 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014111 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070014112 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014113 }
Naveen Rawat07332902016-07-27 09:13:17 -070014114 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014115}
14116#else
Naveen Rawat07332902016-07-27 09:13:17 -070014117static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
14118 struct cfg80211_connect_params *req,
14119 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014120{
Naveen Rawat07332902016-07-27 09:13:17 -070014121 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014122}
14123#endif
14124
14125/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014126 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
14127 * @wiphy: Pointer to wiphy
14128 * @dev: Pointer to network device
14129 * @req: Pointer to cfg80211 connect request
14130 *
14131 * This function is used to start the association process
14132 *
14133 * Return: 0 for success, non-zero for failure
14134 */
14135static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14136 struct net_device *ndev,
14137 struct cfg80211_connect_params *req)
14138{
14139 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014140 u16 channel;
14141#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14142 const u8 *bssid_hint = req->bssid_hint;
14143#else
14144 const u8 *bssid_hint = NULL;
14145#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014146 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
14147 hdd_context_t *pHddCtx;
14148
14149 ENTER();
14150
Anurag Chouhan6d760662016-02-20 16:05:43 +053014151 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014152 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014153 return -EINVAL;
14154 }
14155
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014156 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14157 hdd_err("invalid session id: %d", pAdapter->sessionId);
14158 return -EINVAL;
14159 }
14160
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014161 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014162 TRACE_CODE_HDD_CFG80211_CONNECT,
14163 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014164 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014165 hdd_device_mode_to_string(pAdapter->device_mode),
14166 pAdapter->device_mode);
14167
Krunal Sonib4326f22016-03-10 13:05:51 -080014168 if (pAdapter->device_mode != QDF_STA_MODE &&
14169 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014170 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014171 hdd_device_mode_to_string(pAdapter->device_mode),
14172 pAdapter->device_mode);
14173 return -EINVAL;
14174 }
14175
14176 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14177 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014178 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014179 return -EINVAL;
14180 }
14181
14182 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014183 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014184 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014185
Naveen Rawat07332902016-07-27 09:13:17 -070014186 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014187 return status;
14188
Agrawal Ashishf156e942016-08-04 14:54:47 +053014189 /* Try disconnecting if already in connected state */
14190 status = wlan_hdd_try_disconnect(pAdapter);
14191 if (0 > status) {
14192 hdd_err("Failed to disconnect the existing connection");
14193 return -EALREADY;
14194 }
14195
14196 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014197 if (req->channel) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014198 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14199 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014200 pAdapter->device_mode),
14201 req->channel->hw_value, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014202 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014203 return -ECONNREFUSED;
14204 }
14205 } else {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014206 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14207 policy_mgr_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014208 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014209 hdd_warn("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014210 return -ECONNREFUSED;
14211 }
14212 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070014213
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014214 /*initialise security parameters */
14215 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
14216
14217 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014218 hdd_err("Failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014219 return status;
14220 }
14221
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053014222 if (req->channel)
14223 channel = req->channel->hw_value;
14224 else
14225 channel = 0;
14226 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
14227 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014228 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014229 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014230 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014231 return status;
14232 }
14233 EXIT();
14234 return status;
14235}
14236
14237/**
14238 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
14239 * @wiphy: Pointer to wiphy
14240 * @dev: Pointer to network device
14241 * @req: Pointer to cfg80211 connect request
14242 *
14243 * Return: 0 for success, non-zero for failure
14244 */
14245static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
14246 struct net_device *ndev,
14247 struct cfg80211_connect_params *req)
14248{
14249 int ret;
14250 cds_ssr_protect(__func__);
14251 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
14252 cds_ssr_unprotect(__func__);
14253
14254 return ret;
14255}
14256
14257/**
14258 * wlan_hdd_disconnect() - hdd disconnect api
14259 * @pAdapter: Pointer to adapter
14260 * @reason: Disconnect reason code
14261 *
14262 * This function is used to issue a disconnect request to SME
14263 *
14264 * Return: 0 for success, non-zero for failure
14265 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014266static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014267{
14268 int status, result = 0;
14269 unsigned long rc;
14270 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14271 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014272 eConnectionState prev_conn_state;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014273 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014274
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014275 ENTER();
14276
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014277 status = wlan_hdd_validate_context(pHddCtx);
14278
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014279 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014280 return status;
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014281 if (pAdapter->device_mode == QDF_STA_MODE) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014282 hdd_debug("Stop firmware roaming");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014283 status = sme_stop_roaming(hal, pAdapter->sessionId,
14284 eCsrHddIssued);
14285 }
14286 /*
14287 * If firmware has already started roaming process, driver
14288 * needs to defer the processing of this disconnect request.
14289 */
14290 if (hdd_is_roaming_in_progress(pAdapter)) {
14291 /*
14292 * Defer the disconnect action until firmware roaming
14293 * result is received. If STA is in connected state after
14294 * that, send the disconnect command to CSR, otherwise
14295 * CSR would have already sent disconnect event to upper
14296 * layer.
14297 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014298 hdd_warn("Roaming in progress, disconnect command deferred");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014299 pAdapter->defer_disconnect =
14300 DEFER_DISCONNECT_CFG80211_DISCONNECT;
14301 pAdapter->cfg80211_disconnect_reason = reason;
14302 return 0;
14303 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014304
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014305 prev_conn_state = pHddStaCtx->conn_info.connState;
14306
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014307 /* stop tx queues */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014308 hdd_debug("Disabling queues");
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014309 wlan_hdd_netif_queue_control(pAdapter,
14310 WLAN_NETIF_TX_DISABLE_N_CARRIER, WLAN_CONTROL_PATH);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014311 hdd_debug("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014312 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
14313 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14314
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080014315 /* issue disconnect */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014316
14317 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14318 pAdapter->sessionId, reason);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014319 if ((QDF_STATUS_CMD_NOT_QUEUED == status) &&
14320 prev_conn_state != eConnectionState_Connecting) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014321 hdd_debug("status = %d, already disconnected", status);
Padma, Santhosh Kumar52456c62017-01-05 12:14:08 +053014322 result = 0;
14323 goto disconnected;
14324 } else if (QDF_STATUS_CMD_NOT_QUEUED == status) {
14325 /*
14326 * Wait here instead of returning directly, this will block the
14327 * next connect command and allow processing of the scan for
14328 * ssid and the previous connect command in CSR. Else we might
14329 * hit some race conditions leading to SME and HDD out of sync.
14330 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014331 hdd_debug("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014332 } else if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014333 hdd_err("csr_roam_disconnect failure, status: %d", (int)status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014334 pHddStaCtx->staDebugState = status;
14335 result = -EINVAL;
14336 goto disconnected;
14337 }
14338 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14339 msecs_to_jiffies
14340 (WLAN_WAIT_TIME_DISCONNECT));
14341
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014342 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014343 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014344 result = -ETIMEDOUT;
14345 }
14346disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014347 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
14348#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
14349 /* Sending disconnect event to userspace for kernel version < 3.11
14350 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
14351 */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014352 hdd_debug("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053014353 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
14354 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014355#endif
14356
14357 return result;
14358}
14359
14360/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014361 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
14362 * @reason: ieee80211 reason code.
14363 *
14364 * This utility function helps log string conversion of reason code.
14365 *
14366 * Return: string conversion of reason code, if match found;
14367 * "Unknown" otherwise.
14368 */
14369static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
14370{
14371 switch (reason) {
14372 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
14373 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
14374 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
14375 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
14376 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
14377 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
14378 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
14379 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
14380 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
14381 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
14382 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
14383 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
14384 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
14385 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
14386 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
14387 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
14388 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
14389 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
14390 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
14391 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
14392 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
14393 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
14394 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
14395 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
14396 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
14397 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
14398 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
14399 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
14400 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
14401 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
14402 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
14403 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
14404 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
14405 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
14406 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
14407 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
14408 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
14409 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
14410 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
14411 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
14412 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
14413 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
14414 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
14415 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
14416 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
14417 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
14418 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
14419 default:
14420 return "Unknown";
14421 }
14422}
14423
14424/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014425 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14426 * @wiphy: Pointer to wiphy
14427 * @dev: Pointer to network device
14428 * @reason: Disconnect reason code
14429 *
14430 * This function is used to issue a disconnect request to SME
14431 *
14432 * Return: 0 for success, non-zero for failure
14433 */
14434static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14435 struct net_device *dev, u16 reason)
14436{
14437 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14438 int status;
14439 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14440 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14441#ifdef FEATURE_WLAN_TDLS
14442 uint8_t staIdx;
14443#endif
14444
14445 ENTER();
14446
Anurag Chouhan6d760662016-02-20 16:05:43 +053014447 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014448 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014449 return -EINVAL;
14450 }
14451
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014452 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014453 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014454 return -EINVAL;
14455 }
14456
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014457 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014458 TRACE_CODE_HDD_CFG80211_DISCONNECT,
14459 pAdapter->sessionId, reason));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014460 hdd_debug("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014461 hdd_device_mode_to_string(pAdapter->device_mode),
14462 pAdapter->device_mode, reason);
14463
14464 status = wlan_hdd_validate_context(pHddCtx);
14465
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014466 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014467 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014468
14469 /* Issue disconnect request to SME, if station is in connected state */
14470 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
14471 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
14472 eCsrRoamDisconnectReason reasonCode =
14473 eCSR_DISCONNECT_REASON_UNSPECIFIED;
14474 hdd_scaninfo_t *pScanInfo;
14475
14476 switch (reason) {
14477 case WLAN_REASON_MIC_FAILURE:
14478 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
14479 break;
14480
14481 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
14482 case WLAN_REASON_DISASSOC_AP_BUSY:
14483 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
14484 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
14485 break;
14486
14487 case WLAN_REASON_PREV_AUTH_NOT_VALID:
14488 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
14489 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
14490 break;
14491
14492 case WLAN_REASON_DEAUTH_LEAVING:
14493 reasonCode =
14494 pHddCtx->config->
14495 gEnableDeauthToDisassocMap ?
14496 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
14497 eCSR_DISCONNECT_REASON_DEAUTH;
14498 break;
14499 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
14500 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
14501 break;
14502 default:
14503 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
14504 break;
14505 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014506 hdd_debug("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014507 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014508 pScanInfo = &pAdapter->scan_info;
14509 if (pScanInfo->mScanPending) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014510 hdd_debug("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014511 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
yeshwanth sriram guntuka310b3ac2016-11-15 23:25:26 +053014512 INVALID_SCAN_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014513 eCSR_SCAN_ABORT_DEFAULT);
14514 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053014515 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014516#ifdef FEATURE_WLAN_TDLS
14517 /* First clean up the tdls peers if any */
14518 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
14519 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
14520 pAdapter->sessionId)
14521 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
14522 uint8_t *mac;
14523 mac =
14524 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014525 hdd_debug("call sme_delete_tdls_peer_sta staId %d sessionId %d "
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014526 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014527 pHddCtx->tdlsConnInfo[staIdx].staId,
14528 pAdapter->sessionId,
14529 MAC_ADDR_ARRAY(mac));
14530 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
14531 (pAdapter),
14532 pAdapter->sessionId, mac);
14533 }
14534 }
14535#endif
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014536 hdd_debug("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014537 reasonCode);
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014538 hdd_debug("Disconnect request from user space with reason: %s",
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080014539 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014540 status = wlan_hdd_disconnect(pAdapter, reasonCode);
14541 if (0 != status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014542 hdd_err("wlan_hdd_disconnect failed, status: %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014543 return -EINVAL;
14544 }
14545 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014546 hdd_err("Unexpected cfg disconnect called while in state: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014547 pHddStaCtx->conn_info.connState);
14548 }
14549
14550 return status;
14551}
14552
14553/**
14554 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
14555 * @wiphy: Pointer to wiphy
14556 * @dev: Pointer to network device
14557 * @reason: Disconnect reason code
14558 *
14559 * Return: 0 for success, non-zero for failure
14560 */
14561static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
14562 struct net_device *dev, u16 reason)
14563{
14564 int ret;
14565 cds_ssr_protect(__func__);
14566 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
14567 cds_ssr_unprotect(__func__);
14568
14569 return ret;
14570}
14571
14572/**
14573 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
14574 * @pAdapter: Pointer to adapter
14575 * @param: Pointer to IBSS parameters
14576 *
14577 * This function is used to initialize the security settings in IBSS mode
14578 *
14579 * Return: 0 for success, non-zero for failure
14580 */
14581static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
14582 struct cfg80211_ibss_params
14583 *params)
14584{
14585 int status = 0;
14586 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14587 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
14588 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14589
14590 ENTER();
14591
14592 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014593 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014594 pHddStaCtx->ibss_enc_key_installed = 0;
14595
14596 if (params->ie_len && (NULL != params->ie)) {
14597 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14598 params->ie_len, WLAN_EID_RSN)) {
14599 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
14600 encryptionType = eCSR_ENCRYPT_TYPE_AES;
14601 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
14602 tDot11fIEWPA dot11WPAIE;
14603 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14604 u8 *ie;
14605
14606 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
14607 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
14608 params->ie_len,
14609 DOT11F_EID_WPA);
14610 if (NULL != ie) {
14611 pWextState->wpaVersion =
14612 IW_AUTH_WPA_VERSION_WPA;
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014613 /* Unpack the WPA IE
14614 * Skip past the EID byte and length byte
14615 * and four byte WiFi OUI
14616 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014617 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
14618 &ie[2 + 4],
14619 ie[1] - 4, &dot11WPAIE);
Jeff Johnsonf3826e12017-01-12 09:49:40 -080014620 /* Extract the multicast cipher, the
14621 * encType for unicast cipher for
14622 * wpa-none is none
14623 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014624 encryptionType =
14625 hdd_translate_wpa_to_csr_encryption_type
14626 (dot11WPAIE.multicast_cipher);
14627 }
14628 }
14629
14630 status =
14631 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
14632 params->ie_len);
14633
14634 if (0 > status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014635 hdd_err("Failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014636 return status;
14637 }
14638 }
14639
14640 pWextState->roamProfile.AuthType.authType[0] =
14641 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
14642
14643 if (params->privacy) {
14644 /* Security enabled IBSS, At this time there is no information
14645 * available about the security paramters, so initialise the
14646 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
14647 * The correct security parameters will be updated later in
14648 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
14649 * set inorder enable privacy bit in beacons
14650 */
14651
14652 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
14653 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014654 hdd_debug("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014655 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
14656 pWextState->roamProfile.EncryptionType.numEntries = 1;
14657 pWextState->roamProfile.EncryptionType.encryptionType[0] =
14658 encryptionType;
14659 return status;
14660}
14661
14662/**
14663 * __wlan_hdd_cfg80211_join_ibss() - join ibss
14664 * @wiphy: Pointer to wiphy
14665 * @dev: Pointer to network device
14666 * @param: Pointer to IBSS join parameters
14667 *
14668 * This function is used to create/join an IBSS network
14669 *
14670 * Return: 0 for success, non-zero for failure
14671 */
14672static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14673 struct net_device *dev,
14674 struct cfg80211_ibss_params *params)
14675{
14676 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14677 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14678 tCsrRoamProfile *pRoamProfile;
14679 int status;
14680 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14681 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053014682 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014683 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014684
14685 ENTER();
14686
Anurag Chouhan6d760662016-02-20 16:05:43 +053014687 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014688 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014689 return -EINVAL;
14690 }
14691
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014692 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014693 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014694 return -EINVAL;
14695 }
14696
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014697 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014698 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
14699 pAdapter->sessionId, pAdapter->device_mode));
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014700 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014701 hdd_device_mode_to_string(pAdapter->device_mode),
14702 pAdapter->device_mode);
14703
14704 status = wlan_hdd_validate_context(pHddCtx);
14705
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014706 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014707 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014708
14709 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053014710 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014711 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
14712 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
14713 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14714 int indx;
14715
14716 /* Get channel number */
14717 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014718 params->
14719 chandef.
14720 chan->
14721 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014722
14723 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
14724 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014725 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014726 return -EOPNOTSUPP;
14727 }
14728
14729 for (indx = 0; indx < numChans; indx++) {
14730 if (channelNum == validChan[indx]) {
14731 break;
14732 }
14733 }
14734 if (indx >= numChans) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014735 hdd_err("Not valid Channel: %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014736 return -EINVAL;
14737 }
14738 }
14739
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014740 if (!policy_mgr_allow_concurrency(pHddCtx->hdd_psoc,
14741 PM_IBSS_MODE, channelNum, HW_MODE_20_MHZ)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014742 hdd_err("This concurrency combination is not allowed");
14743 return -ECONNREFUSED;
14744 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014745
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014746 status = policy_mgr_reset_connection_update(pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014747 if (!QDF_IS_STATUS_SUCCESS(status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014748 hdd_err("qdf_reset_connection_update failed status: %d", status);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014749
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014750 status = policy_mgr_current_connections_update(pHddCtx->hdd_psoc,
14751 pAdapter->sessionId, channelNum,
Krunal Soni3091bcc2016-06-23 12:28:21 -070014752 SIR_UPDATE_REASON_JOIN_IBSS);
14753 if (QDF_STATUS_E_FAILURE == status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014754 hdd_err("connections update failed!!");
Krunal Soni3091bcc2016-06-23 12:28:21 -070014755 return -EINVAL;
14756 }
14757
14758 if (QDF_STATUS_SUCCESS == status) {
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080014759 status = policy_mgr_wait_for_connection_update(
14760 pHddCtx->hdd_psoc);
Krunal Soni3091bcc2016-06-23 12:28:21 -070014761 if (!QDF_IS_STATUS_SUCCESS(status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014762 hdd_err("qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014763 return -EINVAL;
14764 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014765 }
14766
14767 /*Try disconnecting if already in connected state */
14768 status = wlan_hdd_try_disconnect(pAdapter);
14769 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014770 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014771 return -EALREADY;
14772 }
14773
14774 pRoamProfile = &pWextState->roamProfile;
14775
14776 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014777 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014778 return -EINVAL;
14779 }
14780
14781 /* enable selected protection checks in IBSS mode */
14782 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
14783
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014784 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014785 WNI_CFG_IBSS_ATIM_WIN_SIZE,
14786 pHddCtx->config->
14787 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014788 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014789 }
14790
14791 /* BSSID is provided by upper layers hence no need to AUTO generate */
14792 if (NULL != params->bssid) {
14793 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014794 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014795 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014796 return -EIO;
14797 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014798 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014799 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
14800 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014801 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014802 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014803 return -EIO;
14804 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053014805 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014806 }
14807 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
14808 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
14809 pRoamProfile->beaconInterval = params->beacon_interval;
14810 else {
14811 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014812 hdd_debug("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014813 params->beacon_interval, pRoamProfile->beaconInterval);
14814 }
14815
14816 /* Set Channel */
14817 if (channelNum) {
14818 /* Set the Operational Channel */
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014819 hdd_debug("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014820 pRoamProfile->ChannelInfo.numOfChannels = 1;
14821 pHddStaCtx->conn_info.operationChannel = channelNum;
14822 pRoamProfile->ChannelInfo.ChannelList =
14823 &pHddStaCtx->conn_info.operationChannel;
14824 }
14825
14826 /* Initialize security parameters */
14827 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
14828 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014829 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014830 return status;
14831 }
14832
14833 /* Issue connect start */
14834 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
14835 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014836 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014837 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014838 operationChannel,
14839 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014840
14841 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014842 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014843 return status;
14844 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014845 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014846 return 0;
14847}
14848
14849/**
14850 * wlan_hdd_cfg80211_join_ibss() - join ibss
14851 * @wiphy: Pointer to wiphy
14852 * @dev: Pointer to network device
14853 * @param: Pointer to IBSS join parameters
14854 *
14855 * This function is used to create/join an IBSS network
14856 *
14857 * Return: 0 for success, non-zero for failure
14858 */
14859static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
14860 struct net_device *dev,
14861 struct cfg80211_ibss_params *params)
14862{
14863 int ret = 0;
14864
14865 cds_ssr_protect(__func__);
14866 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
14867 cds_ssr_unprotect(__func__);
14868
14869 return ret;
14870}
14871
14872/**
14873 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
14874 * @wiphy: Pointer to wiphy
14875 * @dev: Pointer to network device
14876 *
14877 * This function is used to leave an IBSS network
14878 *
14879 * Return: 0 for success, non-zero for failure
14880 */
14881static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14882 struct net_device *dev)
14883{
14884 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14885 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
14886 tCsrRoamProfile *pRoamProfile;
14887 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14888 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014889 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014890 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014891 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014892
14893 ENTER();
14894
Anurag Chouhan6d760662016-02-20 16:05:43 +053014895 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014896 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014897 return -EINVAL;
14898 }
14899
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014900 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014901 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014902 return -EINVAL;
14903 }
14904
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014905 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014906 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
14907 pAdapter->sessionId,
14908 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
14909 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014910 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014911 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014912
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014913 hdd_debug("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014914 hdd_device_mode_to_string(pAdapter->device_mode),
14915 pAdapter->device_mode);
14916 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014917 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014918 return -EIO;
14919 }
14920
14921 pRoamProfile = &pWextState->roamProfile;
14922
14923 /* Issue disconnect only if interface type is set to IBSS */
14924 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014925 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014926 return -EINVAL;
14927 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014928 /* Clearing add IE of beacon */
14929 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
14930 sizeof(tSirMacAddr));
14931 updateIE.smeSessionId = pAdapter->sessionId;
14932 updateIE.ieBufferlength = 0;
14933 updateIE.pAdditionIEBuffer = NULL;
14934 updateIE.append = true;
14935 updateIE.notify = true;
14936 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
14937 &updateIE,
14938 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014939 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080014940 }
14941
14942 /* Reset WNI_CFG_PROBE_RSP Flags */
14943 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014944
14945 /* Issue Disconnect request */
14946 INIT_COMPLETION(pAdapter->disconnect_comp_var);
14947 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
14948 pAdapter->sessionId,
14949 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014950 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080014951 hdd_err("sme_roam_disconnect failed status: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014952 hal_status);
14953 return -EAGAIN;
14954 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053014955
14956 /* wait for mc thread to cleanup and then return to upper stack
14957 * so by the time upper layer calls the change interface, we are
14958 * all set to proceed further
14959 */
14960 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
14961 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
14962 if (!rc) {
14963 hdd_err("Failed to disconnect, timed out");
14964 return -ETIMEDOUT;
14965 }
14966
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014967 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014968 return 0;
14969}
14970
14971/**
14972 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
14973 * @wiphy: Pointer to wiphy
14974 * @dev: Pointer to network device
14975 *
14976 * This function is used to leave an IBSS network
14977 *
14978 * Return: 0 for success, non-zero for failure
14979 */
14980static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
14981 struct net_device *dev)
14982{
14983 int ret = 0;
14984
14985 cds_ssr_protect(__func__);
14986 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
14987 cds_ssr_unprotect(__func__);
14988
14989 return ret;
14990}
14991
14992/**
14993 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
14994 * @wiphy: Pointer to wiphy
14995 * @changed: Parameters changed
14996 *
14997 * This function is used to set the phy parameters. RTS Threshold/FRAG
14998 * Threshold/Retry Count etc.
14999 *
15000 * Return: 0 for success, non-zero for failure
15001 */
15002static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
15003 u32 changed)
15004{
15005 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15006 tHalHandle hHal = pHddCtx->hHal;
15007 int status;
15008
15009 ENTER();
15010
Anurag Chouhan6d760662016-02-20 16:05:43 +053015011 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015012 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015013 return -EINVAL;
15014 }
15015
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015016 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015017 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
15018 NO_SESSION, wiphy->rts_threshold));
15019 status = wlan_hdd_validate_context(pHddCtx);
15020
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015021 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015022 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015023
15024 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
15025 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
15026 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
15027
15028 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
15029 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015030 hdd_err("Invalid RTS Threshold value: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015031 rts_threshold);
15032 return -EINVAL;
15033 }
15034
15035 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
15036 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015037 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015038 rts_threshold);
15039 return -EIO;
15040 }
15041
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015042 hdd_debug("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015043 }
15044
15045 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
15046 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
15047 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
15048 wiphy->frag_threshold;
15049
15050 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
15051 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015052 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015053 frag_threshold);
15054 return -EINVAL;
15055 }
15056
15057 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
15058 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015059 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015060 frag_threshold);
15061 return -EIO;
15062 }
15063
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015064 hdd_debug("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015065 }
15066
15067 if ((changed & WIPHY_PARAM_RETRY_SHORT)
15068 || (changed & WIPHY_PARAM_RETRY_LONG)) {
15069 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
15070 wiphy->retry_short : wiphy->retry_long;
15071
15072 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
15073 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015074 hdd_err("Invalid Retry count: %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015075 return -EINVAL;
15076 }
15077
15078 if (changed & WIPHY_PARAM_RETRY_SHORT) {
15079 if (0 != sme_cfg_set_int(hHal,
15080 WNI_CFG_LONG_RETRY_LIMIT,
15081 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015082 hdd_err("sme_cfg_set_int failed for long retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015083 retry_value);
15084 return -EIO;
15085 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015086 hdd_debug("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015087 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
15088 if (0 != sme_cfg_set_int(hHal,
15089 WNI_CFG_SHORT_RETRY_LIMIT,
15090 retry_value)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015091 hdd_err("sme_cfg_set_int failed for short retry count: %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015092 retry_value);
15093 return -EIO;
15094 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015095 hdd_debug("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015096 }
15097 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015098 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015099 return 0;
15100}
15101
15102/**
15103 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
15104 * @wiphy: Pointer to wiphy
15105 * @changed: Parameters changed
15106 *
15107 * Return: 0 for success, non-zero for failure
15108 */
15109static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
15110{
15111 int ret;
15112
15113 cds_ssr_protect(__func__);
15114 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
15115 cds_ssr_unprotect(__func__);
15116
15117 return ret;
15118}
15119
15120/**
15121 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
15122 * key
15123 * @wiphy: Pointer to wiphy
15124 * @dev: Pointer to network device
15125 * @key_index: Key index
15126 *
15127 * Return: 0
15128 */
15129static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15130 struct net_device *netdev,
15131 u8 key_index)
15132{
15133 ENTER();
15134 return 0;
15135}
15136
15137/**
15138 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
15139 * wlan_hdd_set_default_mgmt_key
15140 * @wiphy: pointer to wiphy
15141 * @netdev: pointer to net_device structure
15142 * @key_index: key index
15143 *
15144 * Return: 0 on success, error number on failure
15145 */
15146static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
15147 struct net_device *netdev,
15148 u8 key_index)
15149{
15150 int ret;
15151
15152 cds_ssr_protect(__func__);
15153 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
15154 cds_ssr_unprotect(__func__);
15155
15156 return ret;
15157}
15158
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015159/**
15160 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
15161 * @wiphy: Pointer to wiphy
15162 * @dev: Pointer to network device
15163 * @params: Pointer to tx queue parameters
15164 *
15165 * Return: 0
15166 */
15167static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
15168 struct net_device *dev,
15169 struct ieee80211_txq_params *params)
15170{
15171 ENTER();
15172 return 0;
15173}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015174
15175/**
15176 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
15177 * @wiphy: pointer to wiphy
15178 * @netdev: pointer to net_device structure
15179 * @params: pointer to ieee80211_txq_params
15180 *
15181 * Return: 0 on success, error number on failure
15182 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015183static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
15184 struct net_device *dev,
15185 struct ieee80211_txq_params *params)
15186{
15187 int ret;
15188
15189 cds_ssr_protect(__func__);
15190 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
15191 cds_ssr_unprotect(__func__);
15192
15193 return ret;
15194}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015195
15196/**
15197 * __wlan_hdd_cfg80211_del_station() - delete station v2
15198 * @wiphy: Pointer to wiphy
15199 * @param: Pointer to delete station parameter
15200 *
15201 * Return: 0 for success, non-zero for failure
15202 */
15203static
15204int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15205 struct net_device *dev,
15206 struct tagCsrDelStaParams *pDelStaParams)
15207{
15208 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15209 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015210 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015211 hdd_hostapd_state_t *hapd_state;
15212 int status;
15213 uint8_t staId;
15214 uint8_t *mac;
15215
15216 ENTER();
15217
Anurag Chouhan6d760662016-02-20 16:05:43 +053015218 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015219 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015220 return -EINVAL;
15221 }
15222
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015223 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015224 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015225 return -EINVAL;
15226 }
15227
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015228 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015229 TRACE_CODE_HDD_CFG80211_DEL_STA,
15230 pAdapter->sessionId, pAdapter->device_mode));
15231
15232 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15233 status = wlan_hdd_validate_context(pHddCtx);
15234
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015235 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015236 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015237
15238 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
15239
Krunal Sonib4326f22016-03-10 13:05:51 -080015240 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
15241 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015242
15243 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
15244 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015245 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015246 return 0;
15247 }
15248
Anurag Chouhanc5548422016-02-24 18:33:27 +053015249 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015250 uint16_t i;
15251 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
15252 if ((pAdapter->aStaInfo[i].isUsed) &&
15253 (!pAdapter->aStaInfo[i].
15254 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015255 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015256 mac,
15257 pAdapter->aStaInfo[i].
15258 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015259 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015260 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15261 hdd_ipa_wlan_evt(pAdapter,
15262 pAdapter->
15263 aStaInfo[i].
15264 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015265 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015266 mac);
15267 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015268 hdd_debug("Delete STA with MAC::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015269 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015270 MAC_ADDR_ARRAY(mac));
15271
15272 if (pHddCtx->dev_dfs_cac_status ==
15273 DFS_CAC_IN_PROGRESS)
15274 goto fn_end;
15275
Wei Song2f76f642016-11-18 16:32:53 +080015276 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015277 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053015278 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015279 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015280 hdd_softap_sta_deauth(pAdapter,
15281 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015282 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015283 pAdapter->aStaInfo[i].
15284 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053015285 qdf_status =
15286 qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015287 &hapd_state->
15288 qdf_sta_disassoc_event,
15289 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015290 if (!QDF_IS_STATUS_SUCCESS(
15291 qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015292 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015293 }
15294 }
15295 }
15296 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015297 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015298 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053015299 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015300 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015301 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015302 hdd_debug("Skip DEL STA as this is not used::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015303 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015304 MAC_ADDR_ARRAY(mac));
15305 return -ENOENT;
15306 }
15307
15308 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
15309 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070015310 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015311 }
15312
15313 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
15314 true) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015315 hdd_debug("Skip DEL STA as deauth is in progress::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015316 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015317 MAC_ADDR_ARRAY(mac));
15318 return -ENOENT;
15319 }
15320
15321 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
15322
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015323 hdd_debug("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015324 MAC_ADDR_ARRAY(mac));
15325
15326 /* Case: SAP in ACS selected DFS ch and client connected
15327 * Now Radar detected. Then if random channel is another
15328 * DFS ch then new CAC is initiated and no TX allowed.
15329 * So do not send any mgmt frames as it will timeout
15330 * during CAC.
15331 */
15332
15333 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
15334 goto fn_end;
15335
Wei Song2f76f642016-11-18 16:32:53 +080015336 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053015337 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
15338 (pAdapter), pAdapter->sessionId,
15339 (uint8_t *)&pDelStaParams->peerMacAddr,
15340 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015341 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015342 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015343 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015344 pAdapter->aStaInfo[staId].isDeauthInProgress =
15345 false;
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015346 hdd_debug("STA removal failed for ::"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015347 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015348 MAC_ADDR_ARRAY(mac));
15349 return -ENOENT;
15350 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053015351 qdf_status = qdf_wait_single_event(
Naveen Rawatb56880c2016-12-13 17:56:03 -080015352 &hapd_state->
15353 qdf_sta_disassoc_event,
15354 SME_CMD_TIMEOUT_VALUE);
Anurag Chouhance0dc992016-02-16 18:18:03 +053015355 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015356 hdd_warn("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015357 }
15358 }
15359 }
15360
15361fn_end:
15362 EXIT();
15363 return 0;
15364}
15365
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015366#if defined(USE_CFG80211_DEL_STA_V2)
15367/**
15368 * wlan_hdd_del_station() - delete station wrapper
15369 * @adapter: pointer to the hdd adapter
15370 *
15371 * Return: None
15372 */
15373void wlan_hdd_del_station(hdd_adapter_t *adapter)
15374{
15375 struct station_del_parameters del_sta;
15376 del_sta.mac = NULL;
15377 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
15378 del_sta.reason_code = eCsrForcedDeauthSta;
15379
15380 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
15381 &del_sta);
15382}
15383#else
15384void wlan_hdd_del_station(hdd_adapter_t *adapter)
15385{
15386 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
15387}
15388#endif
15389
15390#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015391/**
15392 * wlan_hdd_cfg80211_del_station() - delete station v2
15393 * @wiphy: Pointer to wiphy
15394 * @param: Pointer to delete station parameter
15395 *
15396 * Return: 0 for success, non-zero for failure
15397 */
15398int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15399 struct net_device *dev,
15400 struct station_del_parameters *param)
15401#else
15402/**
15403 * wlan_hdd_cfg80211_del_station() - delete station
15404 * @wiphy: Pointer to wiphy
15405 * @mac: Pointer to station mac address
15406 *
15407 * Return: 0 for success, non-zero for failure
15408 */
15409#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15410int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15411 struct net_device *dev,
15412 const uint8_t *mac)
15413#else
15414int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
15415 struct net_device *dev,
15416 uint8_t *mac)
15417#endif
15418#endif
15419{
15420 int ret;
15421 struct tagCsrDelStaParams delStaParams;
15422
15423 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015424#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015425 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080015426 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015427 return -EINVAL;
15428 }
15429 wlansap_populate_del_sta_params(param->mac, param->reason_code,
15430 param->subtype, &delStaParams);
15431#else
15432 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
15433 (SIR_MAC_MGMT_DEAUTH >> 4),
15434 &delStaParams);
15435#endif
15436 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
15437 cds_ssr_unprotect(__func__);
15438
15439 return ret;
15440}
15441
15442/**
15443 * __wlan_hdd_cfg80211_add_station() - add station
15444 * @wiphy: Pointer to wiphy
15445 * @mac: Pointer to station mac address
15446 * @pmksa: Pointer to add station parameter
15447 *
15448 * Return: 0 for success, non-zero for failure
15449 */
15450static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15451 struct net_device *dev,
15452 const uint8_t *mac,
15453 struct station_parameters *params)
15454{
15455 int status = -EPERM;
15456#ifdef FEATURE_WLAN_TDLS
15457 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15458 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
15459 u32 mask, set;
15460
15461 ENTER();
15462
Anurag Chouhan6d760662016-02-20 16:05:43 +053015463 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015464 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015465 return -EINVAL;
15466 }
15467
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015468 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015469 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015470 return -EINVAL;
15471 }
15472
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015473 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015474 TRACE_CODE_HDD_CFG80211_ADD_STA,
15475 pAdapter->sessionId, params->listen_interval));
15476
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015477 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015478 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015479
15480 mask = params->sta_flags_mask;
15481
15482 set = params->sta_flags_set;
15483
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015484 hdd_debug("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015485 MAC_ADDR_ARRAY(mac));
15486
15487 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15488 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
15489 status =
15490 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
15491 }
15492 }
15493#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015494 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015495 return status;
15496}
15497
15498/**
15499 * wlan_hdd_cfg80211_add_station() - add station
15500 * @wiphy: Pointer to wiphy
15501 * @mac: Pointer to station mac address
15502 * @pmksa: Pointer to add station parameter
15503 *
15504 * Return: 0 for success, non-zero for failure
15505 */
15506#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
15507static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15508 struct net_device *dev,
15509 const uint8_t *mac,
15510 struct station_parameters *params)
15511#else
15512static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
15513 struct net_device *dev, uint8_t *mac,
15514 struct station_parameters *params)
15515#endif
15516{
15517 int ret;
15518
15519 cds_ssr_protect(__func__);
15520 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
15521 cds_ssr_unprotect(__func__);
15522
15523 return ret;
15524}
15525
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015526/**
15527 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
15528 * @wiphy: Pointer to wiphy
15529 * @dev: Pointer to network device
15530 * @pmksa: Pointer to set pmksa parameter
15531 *
15532 * Return: 0 for success, non-zero for failure
15533 */
15534static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15535 struct net_device *dev,
15536 struct cfg80211_pmksa *pmksa)
15537{
15538 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15539 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15540 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015541 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015542 int status;
15543 tPmkidCacheInfo pmk_id;
15544
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015545 ENTER();
15546
Anurag Chouhan6d760662016-02-20 16:05:43 +053015547 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015548 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015549 return -EINVAL;
15550 }
15551
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015552 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015553 hdd_err("Invalid session id: %d", pAdapter->sessionId);
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015554 return -EINVAL;
15555 }
15556
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015557 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015558 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015559 return -EINVAL;
15560 }
15561
15562 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015563 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015564 pmksa->bssid, pmksa->pmkid);
15565 return -EINVAL;
15566 }
15567
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015568 hdd_debug("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015569 MAC_ADDR_ARRAY(pmksa->bssid));
15570
15571 status = wlan_hdd_validate_context(pHddCtx);
15572
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015573 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015574 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015575
15576 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15577
Anurag Chouhan600c3a02016-03-01 10:33:54 +053015578 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
15579 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015580
15581 /* Add to the PMKSA ID Cache in CSR */
15582 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
15583 &pmk_id, 1, false);
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_SET_PMKSA,
15587 pAdapter->sessionId, result));
15588
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015589 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015590 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015591}
15592
15593/**
15594 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
15595 * @wiphy: Pointer to wiphy
15596 * @dev: Pointer to network device
15597 * @pmksa: Pointer to set pmksa parameter
15598 *
15599 * Return: 0 for success, non-zero for failure
15600 */
15601static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
15602 struct net_device *dev,
15603 struct cfg80211_pmksa *pmksa)
15604{
15605 int ret;
15606
15607 cds_ssr_protect(__func__);
15608 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
15609 cds_ssr_unprotect(__func__);
15610
15611 return ret;
15612}
15613
15614/**
15615 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15616 * @wiphy: Pointer to wiphy
15617 * @dev: Pointer to network device
15618 * @pmksa: Pointer to pmksa parameter
15619 *
15620 * Return: 0 for success, non-zero for failure
15621 */
15622static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15623 struct net_device *dev,
15624 struct cfg80211_pmksa *pmksa)
15625{
15626 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15627 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15628 tHalHandle halHandle;
15629 int status = 0;
15630
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015631 ENTER();
15632
Anurag Chouhan6d760662016-02-20 16:05:43 +053015633 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015634 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015635 return -EINVAL;
15636 }
15637
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015638 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15639 hdd_err("invalid session id: %d", pAdapter->sessionId);
15640 return -EINVAL;
15641 }
15642
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015643 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015644 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015645 return -EINVAL;
15646 }
15647
15648 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015649 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015650 return -EINVAL;
15651 }
15652
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015653 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015654 MAC_ADDR_ARRAY(pmksa->bssid));
15655
15656 status = wlan_hdd_validate_context(pHddCtx);
15657
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015658 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015659 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015660
15661 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15662
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015663 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053015664 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
15665 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015666 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015667 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015668 sme_roam_del_pmkid_from_cache(halHandle,
15669 pAdapter->sessionId, pmksa->bssid,
15670 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015671 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015672 MAC_ADDR_ARRAY(pmksa->bssid));
15673 status = -EINVAL;
15674 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015675 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015676 return status;
15677}
15678
15679/**
15680 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
15681 * @wiphy: Pointer to wiphy
15682 * @dev: Pointer to network device
15683 * @pmksa: Pointer to pmksa parameter
15684 *
15685 * Return: 0 for success, non-zero for failure
15686 */
15687static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
15688 struct net_device *dev,
15689 struct cfg80211_pmksa *pmksa)
15690{
15691 int ret;
15692
15693 cds_ssr_protect(__func__);
15694 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
15695 cds_ssr_unprotect(__func__);
15696
15697 return ret;
15698
15699}
15700
15701/**
15702 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15703 * @wiphy: Pointer to wiphy
15704 * @dev: Pointer to network device
15705 *
15706 * Return: 0 for success, non-zero for failure
15707 */
15708static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15709 struct net_device *dev)
15710{
15711 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15712 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15713 tHalHandle halHandle;
15714 int status = 0;
15715
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015716 ENTER();
15717
Anurag Chouhan6d760662016-02-20 16:05:43 +053015718 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015719 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015720 return -EINVAL;
15721 }
15722
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015723 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15724 hdd_err("invalid session id: %d", pAdapter->sessionId);
15725 return -EINVAL;
15726 }
15727
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015728 hdd_debug("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015729
15730 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
15731 status = wlan_hdd_validate_context(pHddCtx);
15732
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015733 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015734 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015735
15736 /* Retrieve halHandle */
15737 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
15738
15739 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015740 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015741 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
15742 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015743 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015744 status = -EINVAL;
15745 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015746 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015747 return status;
15748}
15749
15750/**
15751 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
15752 * @wiphy: Pointer to wiphy
15753 * @dev: Pointer to network device
15754 *
15755 * Return: 0 for success, non-zero for failure
15756 */
15757static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
15758 struct net_device *dev)
15759{
15760 int ret;
15761
15762 cds_ssr_protect(__func__);
15763 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
15764 cds_ssr_unprotect(__func__);
15765
15766 return ret;
15767}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015768
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015769#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015770/**
15771 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15772 * @wiphy: Pointer to wiphy
15773 * @dev: Pointer to network device
15774 * @ftie: Pointer to fast transition ie parameter
15775 *
15776 * Return: 0 for success, non-zero for failure
15777 */
15778static int
15779__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15780 struct net_device *dev,
15781 struct cfg80211_update_ft_ies_params *ftie)
15782{
15783 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15784 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15785 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
15786 int status;
15787
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015788 ENTER();
15789
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015790 status = wlan_hdd_validate_context(hdd_ctx);
15791 if (status)
15792 return status;
15793
Anurag Chouhan6d760662016-02-20 16:05:43 +053015794 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015795 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015796 return -EINVAL;
15797 }
15798
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015799 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15800 hdd_err("invalid session id: %d", pAdapter->sessionId);
15801 return -EINVAL;
15802 }
15803
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015804 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015805 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
15806 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
15807 /* Added for debug on reception of Re-assoc Req. */
15808 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015809 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015810 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015811 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015812 }
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015813 hdd_debug("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015814 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015815
15816 /* Pass the received FT IEs to SME */
15817 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
15818 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015819 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015820 return 0;
15821}
15822
15823/**
15824 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
15825 * @wiphy: Pointer to wiphy
15826 * @dev: Pointer to network device
15827 * @ftie: Pointer to fast transition ie parameter
15828 *
15829 * Return: 0 for success, non-zero for failure
15830 */
15831static int
15832wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
15833 struct net_device *dev,
15834 struct cfg80211_update_ft_ies_params *ftie)
15835{
15836 int ret;
15837
15838 cds_ssr_protect(__func__);
15839 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
15840 cds_ssr_unprotect(__func__);
15841
15842 return ret;
15843}
15844#endif
15845
Mukul Sharma3d36c392017-01-18 18:39:12 +053015846void wlan_hdd_cfg80211_update_replay_counter_callback(
15847 void *cb_ctx, struct pmo_gtk_rsp_params *gtk_rsp_param)
15848
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015849{
Mukul Sharma3d36c392017-01-18 18:39:12 +053015850 hdd_adapter_t *pAdapter = (hdd_adapter_t *)cb_ctx;
15851 uint8_t temp_replay_counter[8];
15852 int i;
15853 uint8_t *p;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015854
15855 ENTER();
15856
Mukul Sharma3d36c392017-01-18 18:39:12 +053015857 if (!pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015858 hdd_err("HDD adapter is Null");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015859 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015860 }
15861
Mukul Sharma3d36c392017-01-18 18:39:12 +053015862 if (!gtk_rsp_param) {
15863 hdd_err("gtk_rsp_param is Null");
15864 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015865 }
15866
Mukul Sharma3d36c392017-01-18 18:39:12 +053015867 if (gtk_rsp_param->status_flag != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015868 hdd_err("wlan Failed to get replay counter value");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015869 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015870 }
15871
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015872 hdd_debug("updated replay counter: %llu from fwr",
Mukul Sharma3d36c392017-01-18 18:39:12 +053015873 gtk_rsp_param->replay_counter);
15874 /* convert little to big endian since supplicant works on big endian */
15875 p = (uint8_t *)&gtk_rsp_param->replay_counter;
15876 for (i = 0; i < 8; i++)
15877 temp_replay_counter[7 - i] = (uint8_t) p[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015878
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015879 hdd_debug("gtk_rsp_param bssid %pM", gtk_rsp_param->bssid.bytes);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015880 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080015881 cfg80211_gtk_rekey_notify(pAdapter->dev,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015882 gtk_rsp_param->bssid.bytes,
15883 temp_replay_counter, GFP_KERNEL);
15884out:
15885 EXIT();
15886
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015887}
15888
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015889static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015890int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
Mukul Sharma3d36c392017-01-18 18:39:12 +053015891 struct net_device *dev,
15892 struct cfg80211_gtk_rekey_data *data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015893{
15894 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015895 int result, i;
15896 struct pmo_gtk_req *gtk_req = NULL;
15897 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
15898 uint8_t *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015899 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015900
15901 ENTER();
15902
Anurag Chouhan6d760662016-02-20 16:05:43 +053015903 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015904 hdd_err("Command not allowed in FTM mode");
Mukul Sharma3d36c392017-01-18 18:39:12 +053015905 result = -EINVAL;
15906 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015907 }
15908
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015909 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
15910 hdd_err("invalid session id: %d", pAdapter->sessionId);
Mukul Sharma3d36c392017-01-18 18:39:12 +053015911 result = -EINVAL;
15912 goto out;
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053015913 }
15914
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053015915 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015916 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
15917 pAdapter->sessionId, pAdapter->device_mode));
15918
Mukul Sharma3d36c392017-01-18 18:39:12 +053015919 result = wlan_hdd_validate_context(hdd_ctx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015920 if (0 != result)
Mukul Sharma3d36c392017-01-18 18:39:12 +053015921 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015922
Mukul Sharma3d36c392017-01-18 18:39:12 +053015923 gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
15924 if (!gtk_req) {
15925 hdd_err("cannot allocate gtk_req");
15926 result = -ENOMEM;
15927 goto out;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015928 }
15929
Mukul Sharma3d36c392017-01-18 18:39:12 +053015930 /* convert big to little endian since driver work on little endian */
15931 buf = (uint8_t *)&gtk_req->replay_counter;
15932 for (i = 0; i < 8; i++)
15933 buf[7 - i] = data->replay_ctr[i];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015934
Srinivas Girigowda13d39252017-03-06 16:12:15 -080015935 hdd_debug("current replay counter: %llu in user space",
Mukul Sharma3d36c392017-01-18 18:39:12 +053015936 gtk_req->replay_counter);
15937 qdf_mem_copy(gtk_req->kek, data->kek, NL80211_KEK_LEN);
15938 qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
15939 status = pmo_ucfg_cache_gtk_offload_req(pAdapter->hdd_vdev, gtk_req);
15940 if (status != QDF_STATUS_SUCCESS) {
15941 hdd_err("Failed to cache GTK Offload");
15942 result = qdf_status_to_os_return(status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015943 }
Mukul Sharma3d36c392017-01-18 18:39:12 +053015944out:
15945 if (gtk_req)
15946 qdf_mem_free(gtk_req);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053015947 EXIT();
Mukul Sharma3d36c392017-01-18 18:39:12 +053015948
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015949 return result;
15950}
15951
15952/**
15953 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
15954 * @wiphy: Pointer to wiphy
15955 * @dev: Pointer to network device
15956 * @data: Pointer to rekey data
15957 *
15958 * This function is used to offload GTK rekeying job to the firmware.
15959 *
15960 * Return: 0 for success, non-zero for failure
15961 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070015962static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015963int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
15964 struct net_device *dev,
15965 struct cfg80211_gtk_rekey_data *data)
15966{
15967 int ret;
15968
15969 cds_ssr_protect(__func__);
15970 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
15971 cds_ssr_unprotect(__func__);
15972
15973 return ret;
15974}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015975
15976/**
15977 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
15978 * @wiphy: Pointer to wiphy
15979 * @dev: Pointer to network device
15980 * @param: Pointer to access control parameter
15981 *
15982 * Return: 0 for success, non-zero for failure
15983 */
15984static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
15985 struct net_device *dev,
15986 const struct cfg80211_acl_data *params)
15987{
15988 int i;
15989 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
15990 hdd_hostapd_state_t *pHostapdState;
15991 tsap_Config_t *pConfig;
15992 v_CONTEXT_t p_cds_context = NULL;
15993 hdd_context_t *pHddCtx;
15994 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053015995 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015996
15997 ENTER();
15998
Anurag Chouhan6d760662016-02-20 16:05:43 +053015999 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016000 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016001 return -EINVAL;
16002 }
16003
16004 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016005 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016006 return -EINVAL;
16007 }
16008
16009 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16010 status = wlan_hdd_validate_context(pHddCtx);
16011
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016012 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016013 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016014
16015 p_cds_context = pHddCtx->pcds_context;
16016 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
16017
16018 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016019 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016020 return -EINVAL;
16021 }
16022
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016023 hdd_debug("acl policy: %d num acl entries: %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016024 params->n_acl_entries);
16025
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016026 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016027 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
16028 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080016029 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016030 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
16031
16032 /* default value */
16033 pConfig->num_accept_mac = 0;
16034 pConfig->num_deny_mac = 0;
16035
16036 /**
16037 * access control policy
16038 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
16039 * listed in hostapd.deny file.
16040 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
16041 * listed in hostapd.accept file.
16042 */
16043 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
16044 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
16045 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
16046 params->acl_policy) {
16047 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
16048 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016049 hdd_warn("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016050 params->acl_policy);
16051 return -ENOTSUPP;
16052 }
16053
16054 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
16055 pConfig->num_accept_mac = params->n_acl_entries;
16056 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016057 hdd_debug("** Add ACL MAC entry %i in WhiletList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016058 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016059 MAC_ADDR_ARRAY(
16060 params->mac_addrs[i].addr));
16061
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016062 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016063 params->mac_addrs[i].addr,
16064 sizeof(qcmacaddr));
16065 }
16066 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
16067 pConfig->num_deny_mac = params->n_acl_entries;
16068 for (i = 0; i < params->n_acl_entries; i++) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016069 hdd_debug("** Add ACL MAC entry %i in BlackList :"
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016070 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016071 MAC_ADDR_ARRAY(
16072 params->mac_addrs[i].addr));
16073
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016074 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016075 params->mac_addrs[i].addr,
16076 sizeof(qcmacaddr));
16077 }
16078 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070016079 qdf_status = wlansap_set_mac_acl(
16080 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016081 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016082 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016083 return -EINVAL;
16084 }
16085 } else {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016086 hdd_debug("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016087 hdd_device_mode_to_string(pAdapter->device_mode),
16088 pAdapter->device_mode);
16089 return -EINVAL;
16090 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016091 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016092 return 0;
16093}
16094
16095/**
16096 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
16097 * __wlan_hdd_cfg80211_set_mac_acl
16098 * @wiphy: pointer to wiphy structure
16099 * @dev: pointer to net_device
16100 * @params: pointer to cfg80211_acl_data
16101 *
16102 * Return; 0 on success, error number otherwise
16103 */
16104static int
16105wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
16106 struct net_device *dev,
16107 const struct cfg80211_acl_data *params)
16108{
16109 int ret;
16110
16111 cds_ssr_protect(__func__);
16112 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
16113 cds_ssr_unprotect(__func__);
16114
16115 return ret;
16116}
16117
16118#ifdef WLAN_NL80211_TESTMODE
16119#ifdef FEATURE_WLAN_LPHB
16120/**
16121 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
16122 * @pHddCtx: Pointer to hdd context
16123 * @lphbInd: Pointer to low power heart beat indication parameter
16124 *
16125 * Return: none
16126 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070016127static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
16128 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016129{
16130 struct sk_buff *skb;
16131
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016132 hdd_debug("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016133
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016134 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016135 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016136
16137 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016138 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016139 return;
16140 }
16141
16142 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
16143 wiphy, sizeof(tSirLPHBInd),
16144 GFP_ATOMIC);
16145 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016146 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016147 return;
16148 }
16149
16150 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016151 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016152 goto nla_put_failure;
16153 }
16154 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016155 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016156 goto nla_put_failure;
16157 }
16158 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016159 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016160 goto nla_put_failure;
16161 }
16162 cfg80211_testmode_event(skb, GFP_ATOMIC);
16163 return;
16164
16165nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016166 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016167 kfree_skb(skb);
16168
16169 return;
16170}
16171#endif /* FEATURE_WLAN_LPHB */
16172
16173/**
16174 * __wlan_hdd_cfg80211_testmode() - test mode
16175 * @wiphy: Pointer to wiphy
16176 * @data: Data pointer
16177 * @len: Data length
16178 *
16179 * Return: 0 for success, non-zero for failure
16180 */
16181static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16182 void *data, int len)
16183{
16184 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
16185 int err;
16186 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
16187
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016188 ENTER();
16189
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016190 err = wlan_hdd_validate_context(pHddCtx);
16191 if (err)
16192 return err;
16193
16194 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
16195 len, wlan_hdd_tm_policy);
16196 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016197 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016198 return err;
16199 }
16200
16201 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016202 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016203 return -EINVAL;
16204 }
16205
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053016206 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053016207 TRACE_CODE_HDD_CFG80211_TESTMODE,
16208 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016209 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
16210#ifdef FEATURE_WLAN_LPHB
16211 /* Low Power Heartbeat configuration request */
16212 case WLAN_HDD_TM_CMD_WLAN_HB:
16213 {
16214 int buf_len;
16215 void *buf;
16216 tSirLPHBReq *hb_params = NULL;
16217 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016218 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016219
16220 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016221 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016222 return -EINVAL;
16223 }
16224
16225 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16226 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16227
16228 hb_params_temp = (tSirLPHBReq *) buf;
16229 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
16230 && (hb_params_temp->params.lphbTcpParamReq.
16231 timePeriodSec == 0))
16232 return -EINVAL;
16233
16234 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016235 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016236 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016237 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016238 return -ENOMEM;
16239 }
16240
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016241 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016242 smeStatus =
16243 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
16244 hb_params,
16245 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016246 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016247 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016248 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016249 }
16250 return 0;
16251 }
16252#endif /* FEATURE_WLAN_LPHB */
16253
16254#if defined(QCA_WIFI_FTM)
16255 case WLAN_HDD_TM_CMD_WLAN_FTM:
16256 {
16257 int buf_len;
16258 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016259 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016260 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070016261 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016262 return -EINVAL;
16263 }
16264
16265 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
16266 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
16267
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016268 hdd_debug("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016269
16270 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
16271
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016272 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016273 err = -EBUSY;
16274 break;
16275 }
16276#endif
16277
16278 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016279 hdd_err("command: %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016280 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
16281 return -EOPNOTSUPP;
16282 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053016283 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016284 return err;
16285}
16286
16287/**
16288 * wlan_hdd_cfg80211_testmode() - test mode
16289 * @wiphy: Pointer to wiphy
16290 * @dev: Pointer to network device
16291 * @data: Data pointer
16292 * @len: Data length
16293 *
16294 * Return: 0 for success, non-zero for failure
16295 */
16296static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
16297#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
16298 struct wireless_dev *wdev,
16299#endif
16300 void *data, int len)
16301{
16302 int ret;
16303
16304 cds_ssr_protect(__func__);
16305 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
16306 cds_ssr_unprotect(__func__);
16307
16308 return ret;
16309}
16310
16311#if defined(QCA_WIFI_FTM)
16312/**
16313 * wlan_hdd_testmode_rx_event() - test mode rx event handler
16314 * @buf: Pointer to buffer
16315 * @buf_len: Buffer length
16316 *
16317 * Return: none
16318 */
16319void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
16320{
16321 struct sk_buff *skb;
16322 hdd_context_t *hdd_ctx;
16323
16324 if (!buf || !buf_len) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016325 hdd_err("buf or buf_len invalid, buf: %p buf_len: %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016326 return;
16327 }
16328
Anurag Chouhan6d760662016-02-20 16:05:43 +053016329 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016330 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016331 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016332 return;
16333 }
16334
16335 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
16336 buf_len, GFP_KERNEL);
16337 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016338 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016339 return;
16340 }
16341
16342 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
16343 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
16344 goto nla_put_failure;
16345
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016346 hdd_debug("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016347
16348 cfg80211_testmode_event(skb, GFP_KERNEL);
16349 return;
16350
16351nla_put_failure:
16352 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016353 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016354}
16355#endif
16356#endif /* CONFIG_NL80211_TESTMODE */
16357
16358#ifdef QCA_HT_2040_COEX
16359/**
16360 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16361 * @wiphy: Pointer to wiphy
16362 * @dev: Pointer to network device
16363 * @chandef: Pointer to channel definition parameter
16364 *
16365 * Return: 0 for success, non-zero for failure
16366 */
16367static int
16368__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16369 struct net_device *dev,
16370 struct cfg80211_chan_def *chandef)
16371{
16372 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
16373 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016374 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016375 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053016376 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016377
Anurag Chouhan6d760662016-02-20 16:05:43 +053016378 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016379 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016380 return -EINVAL;
16381 }
16382
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016383 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
16384 hdd_err("invalid session id: %d", pAdapter->sessionId);
16385 return -EINVAL;
16386 }
16387
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016388 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
16389 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053016390 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016391 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016392
Anurag Chouhan600c3a02016-03-01 10:33:54 +053016393 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016394 sme_get_config_param(pHddCtx->hHal, &sme_config);
16395 switch (chandef->width) {
16396 case NL80211_CHAN_WIDTH_20:
16397 if (sme_config.csrConfig.channelBondingMode24GHz !=
16398 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16399 sme_config.csrConfig.channelBondingMode24GHz =
16400 eCSR_INI_SINGLE_CHANNEL_CENTERED;
16401 sme_update_config(pHddCtx->hHal, &sme_config);
16402 cbModeChange = true;
16403 }
16404 break;
16405
16406 case NL80211_CHAN_WIDTH_40:
16407 if (sme_config.csrConfig.channelBondingMode24GHz ==
16408 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
16409 if (NL80211_CHAN_HT40MINUS ==
16410 cfg80211_get_chandef_type(chandef))
16411 sme_config.csrConfig.channelBondingMode24GHz =
16412 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
16413 else
16414 sme_config.csrConfig.channelBondingMode24GHz =
16415 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
16416 sme_update_config(pHddCtx->hHal, &sme_config);
16417 cbModeChange = true;
16418 }
16419 break;
16420
16421 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070016422 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016423 return -EINVAL;
16424 }
16425
16426 if (!cbModeChange)
16427 return 0;
16428
Krunal Sonib4326f22016-03-10 13:05:51 -080016429 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016430 return 0;
16431
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016432 hdd_debug("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016433 sme_config.csrConfig.channelBondingMode24GHz);
16434
16435 /* Change SAP ht2040 mode */
16436 status = hdd_set_sap_ht2040_mode(pAdapter,
16437 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053016438 if (status != QDF_STATUS_SUCCESS) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016439 hdd_err("Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016440 return -EINVAL;
16441 }
16442
16443 return 0;
16444}
16445
16446/**
16447 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
16448 * @wiphy: Pointer to wiphy
16449 * @dev: Pointer to network device
16450 * @chandef: Pointer to channel definition parameter
16451 *
16452 * Return: 0 for success, non-zero for failure
16453 */
16454static int
16455wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
16456 struct net_device *dev,
16457 struct cfg80211_chan_def *chandef)
16458{
16459 int ret;
16460
16461 cds_ssr_protect(__func__);
16462 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
16463 cds_ssr_unprotect(__func__);
16464
16465 return ret;
16466}
16467#endif
16468
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016469#ifdef CHANNEL_SWITCH_SUPPORTED
16470/**
16471 * __wlan_hdd_cfg80211_channel_switch()- function to switch
16472 * channel in SAP/GO
16473 * @wiphy: wiphy pointer
16474 * @dev: dev pointer.
16475 * @csa_params: Change channel params
16476 *
16477 * This function is called to switch channel in SAP/GO
16478 *
16479 * Return: 0 if success else return non zero
16480 */
16481static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16482 struct net_device *dev,
16483 struct cfg80211_csa_settings *csa_params)
16484{
16485 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
16486 hdd_context_t *hdd_ctx;
16487 uint8_t channel;
16488 uint16_t freq;
16489 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080016490 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016491
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016492 hdd_debug("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016493 csa_params->chandef.chan->center_freq);
16494
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053016495 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
16496 hdd_err("invalid session id: %d", adapter->sessionId);
16497 return -EINVAL;
16498 }
16499
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016500 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
16501 ret = wlan_hdd_validate_context(hdd_ctx);
16502
16503 if (0 != ret)
16504 return ret;
16505
Krunal Sonib4326f22016-03-10 13:05:51 -080016506 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
16507 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016508 return -ENOTSUPP;
16509
16510 freq = csa_params->chandef.chan->center_freq;
16511 channel = cds_freq_to_chan(freq);
16512
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053016513 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
16514
16515 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016516 return ret;
16517}
16518
16519/**
16520 * wlan_hdd_cfg80211_channel_switch()- function to switch
16521 * channel in SAP/GO
16522 * @wiphy: wiphy pointer
16523 * @dev: dev pointer.
16524 * @csa_params: Change channel params
16525 *
16526 * This function is called to switch channel in SAP/GO
16527 *
16528 * Return: 0 if success else return non zero
16529 */
16530static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
16531 struct net_device *dev,
16532 struct cfg80211_csa_settings *csa_params)
16533{
16534 int ret;
16535
16536 cds_ssr_protect(__func__);
16537 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
16538 cds_ssr_unprotect(__func__);
16539 return ret;
16540}
16541#endif
16542
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016543/**
16544 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
16545 * translation from NL to policy manager type
16546 * @type: Generic connection mode type defined in NL
16547 *
16548 *
16549 * This function provides the type translation
16550 *
16551 * Return: cds_con_mode enum
16552 */
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016553enum policy_mgr_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016554 enum nl80211_iftype type)
16555{
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016556 enum policy_mgr_con_mode mode = PM_MAX_NUM_OF_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016557 switch (type) {
16558 case NL80211_IFTYPE_STATION:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016559 mode = PM_STA_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016560 break;
16561 case NL80211_IFTYPE_P2P_CLIENT:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016562 mode = PM_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016563 break;
16564 case NL80211_IFTYPE_P2P_GO:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016565 mode = PM_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016566 break;
16567 case NL80211_IFTYPE_AP:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016568 mode = PM_SAP_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016569 break;
16570 case NL80211_IFTYPE_ADHOC:
Tushnim Bhattacharyya87161582017-03-09 13:03:31 -080016571 mode = PM_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016572 break;
16573 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016574 hdd_err("Unsupported interface type: %d", type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016575 }
16576 return mode;
16577}
16578
16579/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016580 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16581 * @wiphy: Handle to struct wiphy to get handle to module context.
16582 * @chandef: Contains information about the capture channel to be set.
16583 *
16584 * This interface is called if and only if monitor mode interface alone is
16585 * active.
16586 *
16587 * Return: 0 success or error code on failure.
16588 */
16589static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16590 struct cfg80211_chan_def *chandef)
16591{
16592 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
16593 hdd_adapter_t *adapter;
16594 hdd_station_ctx_t *sta_ctx;
16595 struct hdd_mon_set_ch_info *ch_info;
16596 QDF_STATUS status;
16597 tHalHandle hal_hdl;
16598 struct qdf_mac_addr bssid;
16599 tCsrRoamProfile roam_profile;
16600 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016601 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016602 int ret;
16603 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
16604
16605 ENTER();
16606
16607 ret = wlan_hdd_validate_context(hdd_ctx);
16608 if (ret)
16609 return ret;
16610
16611 hal_hdl = hdd_ctx->hHal;
16612
16613 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
16614 if (!adapter)
16615 return -EIO;
16616
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016617 hdd_debug("%s: set monitor mode Channel %d and freq %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016618 adapter->dev->name, chan_num, chandef->chan->center_freq);
16619
16620 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
16621 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016622 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
16623 roam_profile.ChannelInfo.numOfChannels = 1;
16624 roam_profile.phyMode = ch_info->phy_mode;
16625 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070016626 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016627
16628 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
16629 QDF_MAC_ADDR_SIZE);
16630
16631 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070016632 /*
16633 * CDS api expects secondary channel for calculating
16634 * the channel params
16635 */
16636 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
16637 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
16638 if (chan_num >= 1 && chan_num <= 5)
16639 sec_ch = chan_num + 4;
16640 else if (chan_num >= 6 && chan_num <= 13)
16641 sec_ch = chan_num - 4;
16642 }
16643 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016644 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
16645 &roam_profile);
16646 if (status) {
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016647 hdd_err("Failed to set sme_RoamChannel for monitor mode status: %d",
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016648 status);
16649 ret = qdf_status_to_os_return(status);
16650 return ret;
16651 }
16652 EXIT();
16653 return 0;
16654}
16655
16656/**
16657 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
16658 * @wiphy: Handle to struct wiphy to get handle to module context.
16659 * @chandef: Contains information about the capture channel to be set.
16660 *
16661 * This interface is called if and only if monitor mode interface alone is
16662 * active.
16663 *
16664 * Return: 0 success or error code on failure.
16665 */
16666static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
16667 struct cfg80211_chan_def *chandef)
16668{
16669 int ret;
16670
16671 cds_ssr_protect(__func__);
16672 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
16673 cds_ssr_unprotect(__func__);
16674 return ret;
16675}
16676
16677/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016678 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
16679 * @adapter: pointer to adapter
16680 *
16681 * Wrapper function to clear link layer stats.
16682 * return - void
16683 */
16684void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
16685{
16686 tSirLLStatsClearReq link_layer_stats_clear_req;
16687 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
16688
Mukul Sharma491021c2016-09-29 21:39:19 +053016689 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
16690 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016691 link_layer_stats_clear_req.stopReq = 0;
16692 link_layer_stats_clear_req.reqId = 1;
16693 link_layer_stats_clear_req.staId = adapter->sessionId;
16694 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
16695
16696 return;
16697}
16698
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016699/**
16700 * hdd_process_defer_disconnect() - Handle the deferred disconnect
16701 * @adapter: HDD Adapter
16702 *
16703 * If roaming is in progress and there is a request to
16704 * disconnect the session, then it is deferred. Once
16705 * roaming is complete/aborted, then this routine is
16706 * used to resume the disconnect that was deferred
16707 *
16708 * Return: None
16709 */
16710void hdd_process_defer_disconnect(hdd_adapter_t *adapter)
16711{
16712 switch (adapter->defer_disconnect) {
16713 case DEFER_DISCONNECT_CFG80211_DISCONNECT:
16714 adapter->defer_disconnect = 0;
16715 wlan_hdd_disconnect(adapter,
16716 adapter->cfg80211_disconnect_reason);
16717 break;
16718 case DEFER_DISCONNECT_TRY_DISCONNECT:
16719 wlan_hdd_try_disconnect(adapter);
16720 adapter->defer_disconnect = 0;
16721 break;
16722 default:
Srinivas Girigowda13d39252017-03-06 16:12:15 -080016723 hdd_debug("Invalid source to defer:%d. Hence not handling it",
Varun Reddy Yeturua5784142017-03-10 12:11:44 -080016724 adapter->defer_disconnect);
16725 break;
16726 }
16727}
16728
Kapil Gupta4f0c0c12017-02-07 15:21:15 +053016729#define CNT_DIFF(cur, prev) \
16730 ((cur >= prev) ? (cur - prev) : (cur + (MAX_COUNT - (prev) + 1)))
16731#define MAX_COUNT 0xffffffff
16732static void hdd_update_chan_info(hdd_context_t *hdd_ctx,
16733 struct scan_chan_info *chan,
16734 struct scan_chan_info *info, uint32_t cmd_flag)
16735{
16736 if ((info->cmd_flag != WMI_CHAN_InFO_START_RESP) &&
16737 (info->cmd_flag != WMI_CHAN_InFO_END_RESP))
16738 hdd_err("cmd flag is invalid: %d", info->cmd_flag);
16739
16740 mutex_lock(&hdd_ctx->chan_info_lock);
16741
16742 if (info->cmd_flag == WMI_CHAN_InFO_START_RESP)
16743 qdf_mem_zero(chan, sizeof(*chan));
16744
16745 chan->freq = info->freq;
16746 chan->noise_floor = info->noise_floor;
16747 chan->clock_freq = info->clock_freq;
16748 chan->cmd_flag = info->cmd_flag;
16749 chan->cycle_count = CNT_DIFF(info->cycle_count, chan->cycle_count);
16750
16751 chan->rx_clear_count =
16752 CNT_DIFF(info->rx_clear_count, chan->rx_clear_count);
16753
16754 chan->tx_frame_count =
16755 CNT_DIFF(info->tx_frame_count, chan->tx_frame_count);
16756
16757 mutex_unlock(&hdd_ctx->chan_info_lock);
16758
16759}
16760#undef CNT_DIFF
16761#undef MAX_COUNT
16762
16763/**
16764 * wlan_hdd_chan_info_cb() - channel info callback
16765 * @chan_info: struct scan_chan_info
16766 *
16767 * Store channel info into HDD context
16768 *
16769 * Return: None.
16770 */
16771static void wlan_hdd_chan_info_cb(struct scan_chan_info *info)
16772{
16773 hdd_context_t *hdd_ctx;
16774 struct scan_chan_info *chan;
16775 uint8_t idx;
16776
16777 ENTER();
16778
16779 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
16780 if (wlan_hdd_validate_context(hdd_ctx) != 0) {
16781 hdd_err("hdd_ctx is invalid");
16782 return;
16783 }
16784
16785 if (!hdd_ctx->chan_info) {
16786 hdd_err("chan_info is NULL");
16787 return;
16788 }
16789
16790 chan = hdd_ctx->chan_info;
16791 for (idx = 0; idx < SIR_MAX_NUM_CHANNELS; idx++) {
16792 if (chan[idx].freq == info->freq) {
16793 hdd_update_chan_info(hdd_ctx, &chan[idx], info,
16794 info->cmd_flag);
16795 hdd_info("cmd:%d freq:%u nf:%d cc:%u rcc:%u clk:%u cmd:%d tfc:%d index:%d",
16796 chan[idx].cmd_flag, chan[idx].freq,
16797 chan[idx].noise_floor,
16798 chan[idx].cycle_count, chan[idx].rx_clear_count,
16799 chan[idx].clock_freq, chan[idx].cmd_flag,
16800 chan[idx].tx_frame_count, idx);
16801 if (chan[idx].freq == 0)
16802 break;
16803
16804 }
16805 }
16806
16807 EXIT();
16808}
16809
16810/**
16811 * wlan_hdd_init_chan_info() - init chan info in hdd context
16812 * @hdd_ctx: HDD context pointer
16813 *
16814 * Return: none
16815 */
16816void wlan_hdd_init_chan_info(hdd_context_t *hdd_ctx)
16817{
16818 uint8_t num_2g, num_5g, index = 0;
16819
16820 if (!hdd_ctx->config->fEnableSNRMonitoring) {
16821 hdd_info("SNR monitoring is disabled");
16822 return;
16823 }
16824
16825 hdd_ctx->chan_info =
16826 qdf_mem_malloc(sizeof(struct scan_chan_info)
16827 * QDF_MAX_NUM_CHAN);
16828 if (hdd_ctx->chan_info == NULL) {
16829 hdd_err("Failed to malloc for chan info");
16830 return;
16831 }
16832 mutex_init(&hdd_ctx->chan_info_lock);
16833
16834 num_2g = QDF_ARRAY_SIZE(hdd_channels_2_4_ghz);
16835 for (; index < num_2g; index++) {
16836 hdd_ctx->chan_info[index].freq =
16837 hdd_channels_2_4_ghz[index].center_freq;
16838 }
16839
16840 num_5g = QDF_ARRAY_SIZE(hdd_channels_5_ghz);
16841 for (; (index - num_2g) < num_5g; index++) {
16842 if (cds_is_dsrc_channel(
16843 hdd_channels_5_ghz[index - num_2g].center_freq))
16844 continue;
16845 hdd_ctx->chan_info[index].freq =
16846 hdd_channels_5_ghz[index - num_2g].center_freq;
16847 }
16848 sme_set_chan_info_callback(hdd_ctx->hHal,
16849 &wlan_hdd_chan_info_cb);
16850}
16851
16852/**
16853 * wlan_hdd_deinit_chan_info() - deinit chan info in hdd context
16854 * @hdd_ctx: hdd context pointer
16855 *
16856 * Return: none
16857 */
16858void wlan_hdd_deinit_chan_info(hdd_context_t *hdd_ctx)
16859{
16860 struct scan_chan_info *chan;
16861
16862 chan = hdd_ctx->chan_info;
16863 hdd_ctx->chan_info = NULL;
16864 if (chan)
16865 qdf_mem_free(chan);
16866}
16867
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053016868/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016869 * struct cfg80211_ops - cfg80211_ops
16870 *
16871 * @add_virtual_intf: Add virtual interface
16872 * @del_virtual_intf: Delete virtual interface
16873 * @change_virtual_intf: Change virtual interface
16874 * @change_station: Change station
16875 * @add_beacon: Add beacon in sap mode
16876 * @del_beacon: Delete beacon in sap mode
16877 * @set_beacon: Set beacon in sap mode
16878 * @start_ap: Start ap
16879 * @change_beacon: Change beacon
16880 * @stop_ap: Stop ap
16881 * @change_bss: Change bss
16882 * @add_key: Add key
16883 * @get_key: Get key
16884 * @del_key: Delete key
16885 * @set_default_key: Set default key
16886 * @set_channel: Set channel
16887 * @scan: Scan
16888 * @connect: Connect
16889 * @disconnect: Disconnect
16890 * @join_ibss = Join ibss
16891 * @leave_ibss = Leave ibss
16892 * @set_wiphy_params = Set wiphy params
16893 * @set_tx_power = Set tx power
16894 * @get_tx_power = get tx power
16895 * @remain_on_channel = Remain on channel
16896 * @cancel_remain_on_channel = Cancel remain on channel
16897 * @mgmt_tx = Tx management frame
16898 * @mgmt_tx_cancel_wait = Cancel management tx wait
16899 * @set_default_mgmt_key = Set default management key
16900 * @set_txq_params = Set tx queue parameters
16901 * @get_station = Get station
16902 * @set_power_mgmt = Set power management
16903 * @del_station = Delete station
16904 * @add_station = Add station
16905 * @set_pmksa = Set pmksa
16906 * @del_pmksa = Delete pmksa
16907 * @flush_pmksa = Flush pmksa
16908 * @update_ft_ies = Update FT IEs
16909 * @tdls_mgmt = Tdls management
16910 * @tdls_oper = Tdls operation
16911 * @set_rekey_data = Set rekey data
16912 * @sched_scan_start = Scheduled scan start
16913 * @sched_scan_stop = Scheduled scan stop
16914 * @resume = Resume wlan
16915 * @suspend = Suspend wlan
16916 * @set_mac_acl = Set mac acl
16917 * @testmode_cmd = Test mode command
16918 * @set_ap_chanwidth = Set AP channel bandwidth
16919 * @dump_survey = Dump survey
16920 * @key_mgmt_set_pmk = Set pmk key management
16921 */
16922static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
16923 .add_virtual_intf = wlan_hdd_add_virtual_intf,
16924 .del_virtual_intf = wlan_hdd_del_virtual_intf,
16925 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
16926 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016927 .start_ap = wlan_hdd_cfg80211_start_ap,
16928 .change_beacon = wlan_hdd_cfg80211_change_beacon,
16929 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016930 .change_bss = wlan_hdd_cfg80211_change_bss,
16931 .add_key = wlan_hdd_cfg80211_add_key,
16932 .get_key = wlan_hdd_cfg80211_get_key,
16933 .del_key = wlan_hdd_cfg80211_del_key,
16934 .set_default_key = wlan_hdd_cfg80211_set_default_key,
16935 .scan = wlan_hdd_cfg80211_scan,
16936 .connect = wlan_hdd_cfg80211_connect,
16937 .disconnect = wlan_hdd_cfg80211_disconnect,
16938 .join_ibss = wlan_hdd_cfg80211_join_ibss,
16939 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
16940 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
16941 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
16942 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
16943 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
16944 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
16945 .mgmt_tx = wlan_hdd_mgmt_tx,
16946 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
16947 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
16948 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053016949 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016950 .get_station = wlan_hdd_cfg80211_get_station,
16951 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
16952 .del_station = wlan_hdd_cfg80211_del_station,
16953 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016954 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
16955 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
16956 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080016957#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016958 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
16959#endif
16960#ifdef FEATURE_WLAN_TDLS
16961 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
16962 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
16963#endif
16964#ifdef WLAN_FEATURE_GTK_OFFLOAD
16965 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
16966#endif /* WLAN_FEATURE_GTK_OFFLOAD */
16967#ifdef FEATURE_WLAN_SCAN_PNO
16968 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
16969 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
16970#endif /*FEATURE_WLAN_SCAN_PNO */
16971 .resume = wlan_hdd_cfg80211_resume_wlan,
16972 .suspend = wlan_hdd_cfg80211_suspend_wlan,
16973 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
16974#ifdef WLAN_NL80211_TESTMODE
16975 .testmode_cmd = wlan_hdd_cfg80211_testmode,
16976#endif
16977#ifdef QCA_HT_2040_COEX
16978 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
16979#endif
16980 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053016981#ifdef CHANNEL_SWITCH_SUPPORTED
16982 .channel_switch = wlan_hdd_cfg80211_channel_switch,
16983#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070016984 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053016985#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
16986 defined(CFG80211_ABORT_SCAN)
16987 .abort_scan = wlan_hdd_cfg80211_abort_scan,
16988#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080016989};