blob: bf4b33a674e63f5feda0a9d93a8e324766d4f105 [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
Jeff Johnson9c50e782016-06-29 15:28:56 -070035/* denote that this file does not allow legacy hddLog */
36#define HDD_DISALLOW_LEGACY_HDDLOG 1
37
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080038#include <linux/version.h>
39#include <linux/module.h>
40#include <linux/kernel.h>
41#include <linux/init.h>
42#include <linux/etherdevice.h>
43#include <linux/wireless.h>
44#include <wlan_hdd_includes.h>
45#include <net/arp.h>
46#include <net/cfg80211.h>
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053047#include <qdf_trace.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080048#include <wlan_hdd_wowl.h>
49#include <ani_global.h>
50#include "sir_params.h"
51#include "dot11f.h"
52#include "wlan_hdd_assoc.h"
53#include "wlan_hdd_wext.h"
54#include "sme_api.h"
Peng Xu278d0122015-09-24 16:34:17 -070055#include "sme_power_save_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080056#include "wlan_hdd_p2p.h"
57#include "wlan_hdd_cfg80211.h"
58#include "wlan_hdd_hostapd.h"
59#include "wlan_hdd_softap_tx_rx.h"
60#include "wlan_hdd_main.h"
61#include "wlan_hdd_power.h"
62#include "wlan_hdd_trace.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053063#include "qdf_types.h"
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053064#include "qdf_trace.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080065#include "cds_utils.h"
66#include "cds_sched.h"
67#include "wlan_hdd_scan.h"
68#include <qc_sap_ioctl.h>
69#include "wlan_hdd_tdls.h"
70#include "wlan_hdd_wmm.h"
71#include "wma_types.h"
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +053072#include "wma.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080073#include "wlan_hdd_misc.h"
74#include "wlan_hdd_nan.h"
75#include <wlan_hdd_ipa.h>
76#include "wlan_logging_sock_svc.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053077#include "sap_api.h"
Agrawal Ashish21ba2572016-09-03 16:40:10 +053078#include "csr_api.h"
Agrawal Ashish467dde42016-09-08 18:44:22 +053079#include "pld_common.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053080
Paul Zhang3a210c52016-12-08 10:18:12 +080081#ifdef WLAN_UMAC_CONVERGENCE
82#include "wlan_cfg80211.h"
83#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080084
85#ifdef FEATURE_WLAN_EXTSCAN
86#include "wlan_hdd_ext_scan.h"
87#endif
88
89#ifdef WLAN_FEATURE_LINK_LAYER_STATS
90#include "wlan_hdd_stats.h"
91#endif
92#include "cds_concurrency.h"
93#include "qwlan_version.h"
94#include "wlan_hdd_memdump.h"
95
96#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070097#include "wlan_hdd_tsf.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080098
Ravi Joshideb5a8d2015-11-09 19:11:43 -080099#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +0530100#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -0700101#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700102#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530103#include "wlan_hdd_disa.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800104
Leo Changfdb45c32016-10-28 11:09:23 -0700105#include <cdp_txrx_cmn.h>
106#include <cdp_txrx_misc.h>
107
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800108#define g_mode_rates_size (12)
109#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800110#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
111 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
112
113/*
114 * Android CTS verifier needs atleast this much wait time (in msec)
115 */
116#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
117
118/*
119 * Refer @tCfgProtection structure for definition of the bit map.
120 * below value is obtained by setting the following bit-fields.
121 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
122 */
123#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
124
125#define HDD2GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700126 .band = NL80211_BAND_2GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800127 .center_freq = (freq), \
128 .hw_value = (chan), \
129 .flags = (flag), \
130 .max_antenna_gain = 0, \
131 .max_power = 30, \
132}
133
134#define HDD5GHZCHAN(freq, chan, flag) { \
Dustin Browna30892e2016-10-12 17:28:36 -0700135 .band = NL80211_BAND_5GHZ, \
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800136 .center_freq = (freq), \
137 .hw_value = (chan), \
138 .flags = (flag), \
139 .max_antenna_gain = 0, \
140 .max_power = 30, \
141}
142
143#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
144 { \
145 .bitrate = rate, \
146 .hw_value = rate_id, \
147 .flags = flag, \
148 }
149
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800150#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
151#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800152
153#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800154
Agrawal Ashish65634612016-08-18 13:24:32 +0530155#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
156 mode <= DFS_MODE_DEPRIORITIZE))
157#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
158 || (channel >= 36 && channel <= 184))
159
Peng Xu4d67c8f2015-10-16 16:02:26 -0700160#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530161#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700162
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800163static const u32 hdd_cipher_suites[] = {
164 WLAN_CIPHER_SUITE_WEP40,
165 WLAN_CIPHER_SUITE_WEP104,
166 WLAN_CIPHER_SUITE_TKIP,
167#ifdef FEATURE_WLAN_ESE
168#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
169#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
170 WLAN_CIPHER_SUITE_BTK,
171 WLAN_CIPHER_SUITE_KRK,
172 WLAN_CIPHER_SUITE_CCMP,
173#else
174 WLAN_CIPHER_SUITE_CCMP,
175#endif
176#ifdef FEATURE_WLAN_WAPI
177 WLAN_CIPHER_SUITE_SMS4,
178#endif
179#ifdef WLAN_FEATURE_11W
180 WLAN_CIPHER_SUITE_AES_CMAC,
181#endif
182};
183
Abhishek Singhf512bf32016-05-04 16:47:46 +0530184static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800185 HDD2GHZCHAN(2412, 1, 0),
186 HDD2GHZCHAN(2417, 2, 0),
187 HDD2GHZCHAN(2422, 3, 0),
188 HDD2GHZCHAN(2427, 4, 0),
189 HDD2GHZCHAN(2432, 5, 0),
190 HDD2GHZCHAN(2437, 6, 0),
191 HDD2GHZCHAN(2442, 7, 0),
192 HDD2GHZCHAN(2447, 8, 0),
193 HDD2GHZCHAN(2452, 9, 0),
194 HDD2GHZCHAN(2457, 10, 0),
195 HDD2GHZCHAN(2462, 11, 0),
196 HDD2GHZCHAN(2467, 12, 0),
197 HDD2GHZCHAN(2472, 13, 0),
198 HDD2GHZCHAN(2484, 14, 0),
199};
200
Abhishek Singhf512bf32016-05-04 16:47:46 +0530201static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800202 HDD5GHZCHAN(5180, 36, 0),
203 HDD5GHZCHAN(5200, 40, 0),
204 HDD5GHZCHAN(5220, 44, 0),
205 HDD5GHZCHAN(5240, 48, 0),
206 HDD5GHZCHAN(5260, 52, 0),
207 HDD5GHZCHAN(5280, 56, 0),
208 HDD5GHZCHAN(5300, 60, 0),
209 HDD5GHZCHAN(5320, 64, 0),
210 HDD5GHZCHAN(5500, 100, 0),
211 HDD5GHZCHAN(5520, 104, 0),
212 HDD5GHZCHAN(5540, 108, 0),
213 HDD5GHZCHAN(5560, 112, 0),
214 HDD5GHZCHAN(5580, 116, 0),
215 HDD5GHZCHAN(5600, 120, 0),
216 HDD5GHZCHAN(5620, 124, 0),
217 HDD5GHZCHAN(5640, 128, 0),
218 HDD5GHZCHAN(5660, 132, 0),
219 HDD5GHZCHAN(5680, 136, 0),
220 HDD5GHZCHAN(5700, 140, 0),
221 HDD5GHZCHAN(5720, 144, 0),
222 HDD5GHZCHAN(5745, 149, 0),
223 HDD5GHZCHAN(5765, 153, 0),
224 HDD5GHZCHAN(5785, 157, 0),
225 HDD5GHZCHAN(5805, 161, 0),
226 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800227 HDD5GHZCHAN(5852, 170, 0),
228 HDD5GHZCHAN(5855, 171, 0),
229 HDD5GHZCHAN(5860, 172, 0),
230 HDD5GHZCHAN(5865, 173, 0),
231 HDD5GHZCHAN(5870, 174, 0),
232 HDD5GHZCHAN(5875, 175, 0),
233 HDD5GHZCHAN(5880, 176, 0),
234 HDD5GHZCHAN(5885, 177, 0),
235 HDD5GHZCHAN(5890, 178, 0),
236 HDD5GHZCHAN(5895, 179, 0),
237 HDD5GHZCHAN(5900, 180, 0),
238 HDD5GHZCHAN(5905, 181, 0),
239 HDD5GHZCHAN(5910, 182, 0),
240 HDD5GHZCHAN(5915, 183, 0),
241 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800242};
243
244static struct ieee80211_rate g_mode_rates[] = {
245 HDD_G_MODE_RATETAB(10, 0x1, 0),
246 HDD_G_MODE_RATETAB(20, 0x2, 0),
247 HDD_G_MODE_RATETAB(55, 0x4, 0),
248 HDD_G_MODE_RATETAB(110, 0x8, 0),
249 HDD_G_MODE_RATETAB(60, 0x10, 0),
250 HDD_G_MODE_RATETAB(90, 0x20, 0),
251 HDD_G_MODE_RATETAB(120, 0x40, 0),
252 HDD_G_MODE_RATETAB(180, 0x80, 0),
253 HDD_G_MODE_RATETAB(240, 0x100, 0),
254 HDD_G_MODE_RATETAB(360, 0x200, 0),
255 HDD_G_MODE_RATETAB(480, 0x400, 0),
256 HDD_G_MODE_RATETAB(540, 0x800, 0),
257};
258
259static struct ieee80211_rate a_mode_rates[] = {
260 HDD_G_MODE_RATETAB(60, 0x10, 0),
261 HDD_G_MODE_RATETAB(90, 0x20, 0),
262 HDD_G_MODE_RATETAB(120, 0x40, 0),
263 HDD_G_MODE_RATETAB(180, 0x80, 0),
264 HDD_G_MODE_RATETAB(240, 0x100, 0),
265 HDD_G_MODE_RATETAB(360, 0x200, 0),
266 HDD_G_MODE_RATETAB(480, 0x400, 0),
267 HDD_G_MODE_RATETAB(540, 0x800, 0),
268};
269
270static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530271 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800272 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700273 .band = NL80211_BAND_2GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800274 .bitrates = g_mode_rates,
275 .n_bitrates = g_mode_rates_size,
276 .ht_cap.ht_supported = 1,
277 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
278 | IEEE80211_HT_CAP_GRN_FLD
279 | IEEE80211_HT_CAP_DSSSCCK40
280 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
281 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
282 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
283 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
284 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
285 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
286 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
287};
288
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800289static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530290 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800291 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
Dustin Browna30892e2016-10-12 17:28:36 -0700292 .band = NL80211_BAND_5GHZ,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800293 .bitrates = a_mode_rates,
294 .n_bitrates = a_mode_rates_size,
295 .ht_cap.ht_supported = 1,
296 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
297 | IEEE80211_HT_CAP_GRN_FLD
298 | IEEE80211_HT_CAP_DSSSCCK40
299 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
300 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
301 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
302 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
303 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
304 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
305 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
306 .vht_cap.vht_supported = 1,
307};
308
309/* This structure contain information what kind of frame are expected in
310 TX/RX direction for each kind of interface */
311static const struct ieee80211_txrx_stypes
312 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
313 [NL80211_IFTYPE_STATION] = {
314 .tx = 0xffff,
315 .rx = BIT(SIR_MAC_MGMT_ACTION) |
316 BIT(SIR_MAC_MGMT_PROBE_REQ),
317 },
318 [NL80211_IFTYPE_AP] = {
319 .tx = 0xffff,
320 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
321 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
322 BIT(SIR_MAC_MGMT_PROBE_REQ) |
323 BIT(SIR_MAC_MGMT_DISASSOC) |
324 BIT(SIR_MAC_MGMT_AUTH) |
325 BIT(SIR_MAC_MGMT_DEAUTH) |
326 BIT(SIR_MAC_MGMT_ACTION),
327 },
328 [NL80211_IFTYPE_ADHOC] = {
329 .tx = 0xffff,
330 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
331 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
332 BIT(SIR_MAC_MGMT_PROBE_REQ) |
333 BIT(SIR_MAC_MGMT_DISASSOC) |
334 BIT(SIR_MAC_MGMT_AUTH) |
335 BIT(SIR_MAC_MGMT_DEAUTH) |
336 BIT(SIR_MAC_MGMT_ACTION),
337 },
338 [NL80211_IFTYPE_P2P_CLIENT] = {
339 .tx = 0xffff,
340 .rx = BIT(SIR_MAC_MGMT_ACTION) |
341 BIT(SIR_MAC_MGMT_PROBE_REQ),
342 },
343 [NL80211_IFTYPE_P2P_GO] = {
344 /* This is also same as for SoftAP */
345 .tx = 0xffff,
346 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
347 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
348 BIT(SIR_MAC_MGMT_PROBE_REQ) |
349 BIT(SIR_MAC_MGMT_DISASSOC) |
350 BIT(SIR_MAC_MGMT_AUTH) |
351 BIT(SIR_MAC_MGMT_DEAUTH) |
352 BIT(SIR_MAC_MGMT_ACTION),
353 },
354};
355
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800356/* Interface limits and combinations registered by the driver */
357
358/* STA ( + STA ) combination */
359static const struct ieee80211_iface_limit
360 wlan_hdd_sta_iface_limit[] = {
361 {
362 .max = 3, /* p2p0 is a STA as well */
363 .types = BIT(NL80211_IFTYPE_STATION),
364 },
365};
366
367/* ADHOC (IBSS) limit */
368static const struct ieee80211_iface_limit
369 wlan_hdd_adhoc_iface_limit[] = {
370 {
371 .max = 1,
372 .types = BIT(NL80211_IFTYPE_STATION),
373 },
374 {
375 .max = 1,
376 .types = BIT(NL80211_IFTYPE_ADHOC),
377 },
378};
379
380/* AP ( + AP ) combination */
381static const struct ieee80211_iface_limit
382 wlan_hdd_ap_iface_limit[] = {
383 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530384 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800385 .types = BIT(NL80211_IFTYPE_AP),
386 },
387};
388
389/* P2P limit */
390static const struct ieee80211_iface_limit
391 wlan_hdd_p2p_iface_limit[] = {
392 {
393 .max = 1,
394 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
395 },
396 {
397 .max = 1,
398 .types = BIT(NL80211_IFTYPE_P2P_GO),
399 },
400};
401
402static const struct ieee80211_iface_limit
403 wlan_hdd_sta_ap_iface_limit[] = {
404 {
405 /* We need 1 extra STA interface for OBSS scan when SAP starts
406 * with HT40 in STA+SAP concurrency mode
407 */
408 .max = (1 + SAP_MAX_OBSS_STA_CNT),
409 .types = BIT(NL80211_IFTYPE_STATION),
410 },
411 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530412 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800413 .types = BIT(NL80211_IFTYPE_AP),
414 },
415};
416
417/* STA + P2P combination */
418static const struct ieee80211_iface_limit
419 wlan_hdd_sta_p2p_iface_limit[] = {
420 {
421 /* One reserved for dedicated P2PDEV usage */
422 .max = 2,
423 .types = BIT(NL80211_IFTYPE_STATION)
424 },
425 {
426 /* Support for two identical (GO + GO or CLI + CLI)
427 * or dissimilar (GO + CLI) P2P interfaces
428 */
429 .max = 2,
430 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
431 },
432};
433
434/* STA + AP + P2PGO combination */
435static const struct ieee80211_iface_limit
436wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
437 /* Support for AP+P2PGO interfaces */
438 {
439 .max = 2,
440 .types = BIT(NL80211_IFTYPE_STATION)
441 },
442 {
443 .max = 1,
444 .types = BIT(NL80211_IFTYPE_P2P_GO)
445 },
446 {
447 .max = 1,
448 .types = BIT(NL80211_IFTYPE_AP)
449 }
450};
451
452/* SAP + P2P combination */
453static const struct ieee80211_iface_limit
454wlan_hdd_sap_p2p_iface_limit[] = {
455 {
456 /* 1 dedicated for p2p0 which is a STA type */
457 .max = 1,
458 .types = BIT(NL80211_IFTYPE_STATION)
459 },
460 {
461 /* The p2p interface in SAP+P2P can be GO/CLI.
462 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
463 */
464 .max = 1,
465 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
466 },
467 {
468 /* SAP+GO to support only one SAP interface */
469 .max = 1,
470 .types = BIT(NL80211_IFTYPE_AP)
471 }
472};
473
474/* P2P + P2P combination */
475static const struct ieee80211_iface_limit
476wlan_hdd_p2p_p2p_iface_limit[] = {
477 {
478 /* 1 dedicated for p2p0 which is a STA type */
479 .max = 1,
480 .types = BIT(NL80211_IFTYPE_STATION)
481 },
482 {
483 /* The p2p interface in P2P+P2P can be GO/CLI.
484 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
485 */
486 .max = 2,
487 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
488 },
489};
490
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700491static const struct ieee80211_iface_limit
492 wlan_hdd_mon_iface_limit[] = {
493 {
494 .max = 3, /* Monitor interface */
495 .types = BIT(NL80211_IFTYPE_MONITOR),
496 },
497};
498
499static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800500 wlan_hdd_iface_combination[] = {
501 /* STA */
502 {
503 .limits = wlan_hdd_sta_iface_limit,
504 .num_different_channels = 2,
505 .max_interfaces = 3,
506 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
507 },
508 /* ADHOC */
509 {
510 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700511 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800512 .max_interfaces = 2,
513 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
514 },
515 /* AP */
516 {
517 .limits = wlan_hdd_ap_iface_limit,
518 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530519 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800520 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
521 },
522 /* P2P */
523 {
524 .limits = wlan_hdd_p2p_iface_limit,
525 .num_different_channels = 2,
526 .max_interfaces = 2,
527 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
528 },
529 /* STA + AP */
530 {
531 .limits = wlan_hdd_sta_ap_iface_limit,
532 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530533 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800534 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
535 .beacon_int_infra_match = true,
536 },
537 /* STA + P2P */
538 {
539 .limits = wlan_hdd_sta_p2p_iface_limit,
540 .num_different_channels = 2,
541 /* one interface reserved for P2PDEV dedicated usage */
542 .max_interfaces = 4,
543 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
544 .beacon_int_infra_match = true,
545 },
546 /* STA + P2P GO + SAP */
547 {
548 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
549 /* we can allow 3 channels for three different persona
550 * but due to firmware limitation, allow max 2 concrnt channels.
551 */
552 .num_different_channels = 2,
553 /* one interface reserved for P2PDEV dedicated usage */
554 .max_interfaces = 4,
555 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
556 .beacon_int_infra_match = true,
557 },
558 /* SAP + P2P */
559 {
560 .limits = wlan_hdd_sap_p2p_iface_limit,
561 .num_different_channels = 2,
562 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
563 .max_interfaces = 3,
564 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
565 .beacon_int_infra_match = true,
566 },
567 /* P2P + P2P */
568 {
569 .limits = wlan_hdd_p2p_p2p_iface_limit,
570 .num_different_channels = 2,
571 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
572 .max_interfaces = 3,
573 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
574 .beacon_int_infra_match = true,
575 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530576 /* Monitor */
577 {
578 .limits = wlan_hdd_mon_iface_limit,
579 .max_interfaces = 3,
580 .num_different_channels = 2,
581 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
582 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800583};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800584
585static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Arun Khandavalli2476ef52016-04-26 20:19:43 +0530586struct hdd_bpf_context bpf_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800587
588#ifdef WLAN_NL80211_TESTMODE
589enum wlan_hdd_tm_attr {
590 WLAN_HDD_TM_ATTR_INVALID = 0,
591 WLAN_HDD_TM_ATTR_CMD = 1,
592 WLAN_HDD_TM_ATTR_DATA = 2,
593 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
594 WLAN_HDD_TM_ATTR_TYPE = 4,
595 /* keep last */
596 WLAN_HDD_TM_ATTR_AFTER_LAST,
597 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
598};
599
600enum wlan_hdd_tm_cmd {
601 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
602 WLAN_HDD_TM_CMD_WLAN_HB = 1,
603};
604
605#define WLAN_HDD_TM_DATA_MAX_LEN 5000
606
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530607enum wlan_hdd_vendor_ie_access_policy {
608 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
609 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
610};
611
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800612static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
613 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
614 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
615 .len = WLAN_HDD_TM_DATA_MAX_LEN},
616};
617#endif /* WLAN_NL80211_TESTMODE */
618
619#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
620static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
621 .flags = WIPHY_WOWLAN_MAGIC_PKT,
622 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
623 .pattern_min_len = 1,
624 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
625};
626#endif
627
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800628/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530629 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
630 * @flags: Pointer to the flags to Add channel switch flag.
631 *
632 * This Function adds Channel Switch support flag, if channel switch is
633 * supported by kernel.
634 * Return: void.
635 */
636#ifdef CHANNEL_SWITCH_SUPPORTED
637static inline void hdd_add_channel_switch_support(uint32_t *flags)
638{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800639 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530640 return;
641}
642#else
643static inline void hdd_add_channel_switch_support(uint32_t *flags)
644{
645 return;
646}
647#endif
648
Manikandan Mohan22b83722015-12-15 15:03:23 -0800649#ifdef FEATURE_WLAN_TDLS
650
651/* TDLS capabilities params */
652#define PARAM_MAX_TDLS_SESSION \
653 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
654#define PARAM_TDLS_FEATURE_SUPPORT \
655 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
656
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530657/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800658 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
659 * @wiphy: WIPHY structure pointer
660 * @wdev: Wireless device structure pointer
661 * @data: Pointer to the data received
662 * @data_len: Length of the data received
663 *
664 * This function provides TDLS capabilities
665 *
666 * Return: 0 on success and errno on failure
667 */
668static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
669 struct wireless_dev *wdev,
670 const void *data,
671 int data_len)
672{
673 int status;
674 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
675 struct sk_buff *skb;
676 uint32_t set = 0;
677
Jeff Johnson1f61b612016-02-12 16:28:33 -0800678 ENTER_DEV(wdev->netdev);
679
Anurag Chouhan6d760662016-02-20 16:05:43 +0530680 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800681 hdd_err("Command not allowed in FTM mode");
682 return -EPERM;
683 }
684
685 status = wlan_hdd_validate_context(hdd_ctx);
686 if (status)
687 return status;
688
689 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
690 NLMSG_HDRLEN);
691 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700692 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800693 goto fail;
694 }
695
696 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Jeff Johnson020db452016-06-29 14:37:26 -0700697 hdd_err("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800698 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
699 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700700 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800701 goto fail;
702 }
703 } else {
704 set = set | WIFI_TDLS_SUPPORT;
705 set = set | (hdd_ctx->config->fTDLSExternalControl ?
706 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
707 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
708 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Jeff Johnson020db452016-06-29 14:37:26 -0700709 hdd_notice("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800710 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
711 hdd_ctx->max_num_tdls_sta) ||
712 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
713 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700714 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800715 goto fail;
716 }
717 }
718 return cfg80211_vendor_cmd_reply(skb);
719fail:
720 if (skb)
721 kfree_skb(skb);
722 return -EINVAL;
723}
724
725/**
726 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
727 * @wiphy: WIPHY structure pointer
728 * @wdev: Wireless device structure pointer
729 * @data: Pointer to the data received
730 * @data_len: Length of the data received
731 *
732 * This function provides TDLS capabilities
733 *
734 * Return: 0 on success and errno on failure
735 */
736static int
737wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
738 struct wireless_dev *wdev,
739 const void *data,
740 int data_len)
741{
742 int ret;
743
744 cds_ssr_protect(__func__);
745 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
746 data, data_len);
747 cds_ssr_unprotect(__func__);
748
749 return ret;
750}
751#endif
752
753#ifdef QCA_HT_2040_COEX
754static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
755#endif
756
757#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
758/*
759 * FUNCTION: wlan_hdd_send_avoid_freq_event
760 * This is called when wlan driver needs to send vendor specific
761 * avoid frequency range event to userspace
762 */
763int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
764 tHddAvoidFreqList *pAvoidFreqList)
765{
766 struct sk_buff *vendor_event;
767
768 ENTER();
769
770 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700771 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800772 return -EINVAL;
773 }
774
775 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700776 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800777 return -EINVAL;
778 }
779
780 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
781 NULL,
782 sizeof(tHddAvoidFreqList),
783 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
784 GFP_KERNEL);
785 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700786 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800787 return -EINVAL;
788 }
789
790 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
791 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
792
793 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
794
795 EXIT();
796 return 0;
797}
798#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
799
800/* vendor specific events */
801static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
802#ifdef FEATURE_WLAN_CH_AVOID
803 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
804 .vendor_id =
805 QCA_NL80211_VENDOR_ID,
806 .subcmd =
807 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
808 },
809#endif /* FEATURE_WLAN_CH_AVOID */
810
811#ifdef WLAN_FEATURE_NAN
812 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
813 .vendor_id =
814 QCA_NL80211_VENDOR_ID,
815 .subcmd =
816 QCA_NL80211_VENDOR_SUBCMD_NAN
817 },
818#endif
819
820#ifdef WLAN_FEATURE_STATS_EXT
821 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
822 .vendor_id =
823 QCA_NL80211_VENDOR_ID,
824 .subcmd =
825 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
826 },
827#endif /* WLAN_FEATURE_STATS_EXT */
828#ifdef FEATURE_WLAN_EXTSCAN
829 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
830 .vendor_id =
831 QCA_NL80211_VENDOR_ID,
832 .subcmd =
833 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
834 },
835 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
836 .vendor_id =
837 QCA_NL80211_VENDOR_ID,
838 .subcmd =
839 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
840 },
841 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
842 .
843 vendor_id
844 =
845 QCA_NL80211_VENDOR_ID,
846 .subcmd =
847 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
848 },
849 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
850 .
851 vendor_id
852 =
853 QCA_NL80211_VENDOR_ID,
854 .
855 subcmd =
856 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
857 },
858 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
859 .
860 vendor_id
861 =
862 QCA_NL80211_VENDOR_ID,
863 .
864 subcmd
865 =
866 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
867 },
868 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
869 .
870 vendor_id
871 =
872 QCA_NL80211_VENDOR_ID,
873 .subcmd =
874 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
875 },
876 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
877 .vendor_id =
878 QCA_NL80211_VENDOR_ID,
879 .subcmd =
880 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
881 },
882 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
883 .
884 vendor_id
885 =
886 QCA_NL80211_VENDOR_ID,
887 .subcmd =
888 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
889 },
890 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
891 .
892 vendor_id
893 =
894 QCA_NL80211_VENDOR_ID,
895 .subcmd =
896 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
897 },
898 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
899 .
900 vendor_id
901 =
902 QCA_NL80211_VENDOR_ID,
903 .
904 subcmd
905 =
906 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
907 },
908 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
909 .
910 vendor_id
911 =
912 QCA_NL80211_VENDOR_ID,
913 .
914 subcmd =
915 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
916 },
917 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
918 .
919 vendor_id
920 =
921 QCA_NL80211_VENDOR_ID,
922 .
923 subcmd
924 =
925 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
926 },
927 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
928 .
929 vendor_id
930 =
931 QCA_NL80211_VENDOR_ID,
932 .
933 subcmd
934 =
935 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
936 },
937 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
938 .vendor_id = QCA_NL80211_VENDOR_ID,
939 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
940 },
941 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
942 .vendor_id = QCA_NL80211_VENDOR_ID,
943 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
944 },
945#endif /* FEATURE_WLAN_EXTSCAN */
946
947#ifdef WLAN_FEATURE_LINK_LAYER_STATS
948 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
949 .vendor_id =
950 QCA_NL80211_VENDOR_ID,
951 .subcmd =
952 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
953 },
954 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
955 .vendor_id =
956 QCA_NL80211_VENDOR_ID,
957 .subcmd =
958 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
959 },
960 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
961 .vendor_id =
962 QCA_NL80211_VENDOR_ID,
963 .subcmd =
964 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
965 },
966 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
967 .vendor_id =
968 QCA_NL80211_VENDOR_ID,
969 .subcmd =
970 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
971 },
972 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
973 .vendor_id =
974 QCA_NL80211_VENDOR_ID,
975 .subcmd =
976 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
977 },
978 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
979 .vendor_id =
980 QCA_NL80211_VENDOR_ID,
981 .subcmd =
982 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
983 },
984#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
985 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
986 .vendor_id =
987 QCA_NL80211_VENDOR_ID,
988 .subcmd =
989 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
990 },
991 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
992 .vendor_id = QCA_NL80211_VENDOR_ID,
993 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
994 },
995#ifdef WLAN_FEATURE_ROAM_OFFLOAD
996 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
997 .vendor_id =
998 QCA_NL80211_VENDOR_ID,
999 .subcmd =
1000 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
1001 },
1002#endif
1003 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
1004 .vendor_id =
1005 QCA_NL80211_VENDOR_ID,
1006 .subcmd =
1007 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1008 },
1009 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1010 .vendor_id =
1011 QCA_NL80211_VENDOR_ID,
1012 .subcmd =
1013 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1014 },
1015 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1016 .vendor_id =
1017 QCA_NL80211_VENDOR_ID,
1018 .subcmd =
1019 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1020 },
1021 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1022 .vendor_id =
1023 QCA_NL80211_VENDOR_ID,
1024 .subcmd =
1025 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1026 },
1027 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1028 .vendor_id =
1029 QCA_NL80211_VENDOR_ID,
1030 .subcmd =
1031 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1032 },
1033#ifdef FEATURE_WLAN_EXTSCAN
1034 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1035 .vendor_id = QCA_NL80211_VENDOR_ID,
1036 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1037 },
1038 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1039 .vendor_id = QCA_NL80211_VENDOR_ID,
1040 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1041 },
1042 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1043 .vendor_id = QCA_NL80211_VENDOR_ID,
1044 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1045 },
1046 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1047 .vendor_id = QCA_NL80211_VENDOR_ID,
1048 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1049 },
1050 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1051 .vendor_id = QCA_NL80211_VENDOR_ID,
1052 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1053 },
1054#endif /* FEATURE_WLAN_EXTSCAN */
1055 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1056 .vendor_id = QCA_NL80211_VENDOR_ID,
1057 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1058 },
1059#ifdef WLAN_FEATURE_MEMDUMP
1060 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1061 .vendor_id = QCA_NL80211_VENDOR_ID,
1062 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1063 },
1064#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001065#ifdef WLAN_FEATURE_TSF
1066 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1067 .vendor_id = QCA_NL80211_VENDOR_ID,
1068 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1069 },
1070#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001071 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1072 .vendor_id = QCA_NL80211_VENDOR_ID,
1073 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1074 },
1075 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1076 .vendor_id = QCA_NL80211_VENDOR_ID,
1077 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1078 },
1079 /* OCB events */
1080 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1081 .vendor_id = QCA_NL80211_VENDOR_ID,
1082 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1083 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001084#ifdef FEATURE_LFR_SUBNET_DETECTION
1085 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1086 .vendor_id = QCA_NL80211_VENDOR_ID,
1087 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1088 },
1089#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001090
1091#ifdef WLAN_FEATURE_NAN_DATAPATH
1092 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1093 .vendor_id = QCA_NL80211_VENDOR_ID,
1094 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1095 },
1096#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001097
1098 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1099 .vendor_id = QCA_NL80211_VENDOR_ID,
1100 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1101 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301102 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1103 .vendor_id = QCA_NL80211_VENDOR_ID,
1104 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1105 },
Paul Zhang3a210c52016-12-08 10:18:12 +08001106#ifdef WLAN_UMAC_CONVERGENCE
1107 COMMON_VENDOR_EVENTS
1108#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001109};
1110
1111/**
1112 * __is_driver_dfs_capable() - get driver DFS capability
1113 * @wiphy: pointer to wireless wiphy structure.
1114 * @wdev: pointer to wireless_dev structure.
1115 * @data: Pointer to the data to be passed via vendor interface
1116 * @data_len:Length of the data to be passed
1117 *
1118 * This function is called by userspace to indicate whether or not
1119 * the driver supports DFS offload.
1120 *
1121 * Return: 0 on success, negative errno on failure
1122 */
1123static int __is_driver_dfs_capable(struct wiphy *wiphy,
1124 struct wireless_dev *wdev,
1125 const void *data,
1126 int data_len)
1127{
1128 u32 dfs_capability = 0;
1129 struct sk_buff *temp_skbuff;
1130 int ret_val;
1131 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1132
Jeff Johnson1f61b612016-02-12 16:28:33 -08001133 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001134
1135 ret_val = wlan_hdd_validate_context(hdd_ctx);
1136 if (ret_val)
1137 return ret_val;
1138
Anurag Chouhan6d760662016-02-20 16:05:43 +05301139 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001140 hdd_err("Command not allowed in FTM mode");
1141 return -EPERM;
1142 }
1143
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001144 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001145
1146 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1147 NLMSG_HDRLEN);
1148
1149 if (temp_skbuff != NULL) {
1150 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1151 dfs_capability);
1152 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001153 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001154 kfree_skb(temp_skbuff);
1155
1156 return ret_val;
1157 }
1158
1159 return cfg80211_vendor_cmd_reply(temp_skbuff);
1160 }
1161
Jeff Johnson020db452016-06-29 14:37:26 -07001162 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001163 return -ENOMEM;
1164}
1165
1166/**
1167 * is_driver_dfs_capable() - get driver DFS capability
1168 * @wiphy: pointer to wireless wiphy structure.
1169 * @wdev: pointer to wireless_dev structure.
1170 * @data: Pointer to the data to be passed via vendor interface
1171 * @data_len:Length of the data to be passed
1172 *
1173 * This function is called by userspace to indicate whether or not
1174 * the driver supports DFS offload. This is an SSR-protected
1175 * wrapper function.
1176 *
1177 * Return: 0 on success, negative errno on failure
1178 */
1179static int is_driver_dfs_capable(struct wiphy *wiphy,
1180 struct wireless_dev *wdev,
1181 const void *data,
1182 int data_len)
1183{
1184 int ret;
1185
1186 cds_ssr_protect(__func__);
1187 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1188 cds_ssr_unprotect(__func__);
1189
1190 return ret;
1191}
1192
1193/**
1194 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1195 *
1196 * @adapter: SAP adapter pointer
1197 *
1198 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1199 * radio. So in case of DFS MCC scenario override current SAP given config
1200 * to follow concurrent SAP DFS config
1201 *
1202 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1203 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001204int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1205{
1206 hdd_adapter_t *con_sap_adapter;
1207 tsap_Config_t *sap_config, *con_sap_config;
1208 int con_ch;
1209
1210 /*
1211 * Check if AP+AP case, once primary AP chooses a DFS
1212 * channel secondary AP should always follow primary APs channel
1213 */
1214 if (!cds_concurrent_beaconing_sessions_running())
1215 return 0;
1216
1217 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1218 if (!con_sap_adapter)
1219 return 0;
1220
1221 sap_config = &adapter->sessionCtx.ap.sapConfig;
1222 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1223 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1224
1225 if (!CDS_IS_DFS_CH(con_ch))
1226 return 0;
1227
Jeff Johnson020db452016-06-29 14:37:26 -07001228 hdd_err("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001229 sap_config->channel, con_ch);
Jeff Johnson020db452016-06-29 14:37:26 -07001230 hdd_notice("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001231 sap_config->channel = con_ch;
1232
1233 if (con_sap_config->acs_cfg.acs_mode == true) {
1234 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1235 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001236 hdd_err("Primary AP channel config error");
1237 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001238 con_ch, con_sap_config->acs_cfg.pri_ch,
1239 con_sap_config->acs_cfg.ht_sec_ch);
1240 return -EINVAL;
1241 }
1242 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1243 * MCC restriction. So free ch list allocated in do_acs
1244 * func for Sec AP and realloc for Pri AP ch list size
1245 */
1246 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301247 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001248
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301249 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001250 &con_sap_config->acs_cfg,
1251 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301252 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001253 sizeof(uint8_t) *
1254 con_sap_config->acs_cfg.ch_list_count);
1255 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001256 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001257 return -ENOMEM;
1258 }
1259
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301260 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001261 con_sap_config->acs_cfg.ch_list,
1262 con_sap_config->acs_cfg.ch_list_count);
1263
1264 } else {
1265 sap_config->acs_cfg.pri_ch = con_ch;
1266 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1267 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1268 }
1269
1270 return con_ch;
1271}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001272
1273/**
1274 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1275 * @sap_cfg: pointer to SAP config struct
1276 *
1277 * This function sets the default ACS start and end channel for the given band
1278 * and also parses the given ACS channel list.
1279 *
1280 * Return: None
1281 */
1282
1283static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1284 bool vht_enabled)
1285{
1286 int i;
1287 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1288 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001289 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1290 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001291 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1292 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001293 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1294 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001295 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1296 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001297 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1298 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001299 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1300 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001301 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1302 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001303 }
1304
1305 if (ht_enabled)
1306 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1307
1308 if (vht_enabled)
1309 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1310
1311
1312 /* Parse ACS Chan list from hostapd */
1313 if (!sap_cfg->acs_cfg.ch_list)
1314 return;
1315
1316 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1317 sap_cfg->acs_cfg.end_ch =
1318 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1319 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301320 /* avoid channel as start channel */
1321 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1322 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001323 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1324 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1325 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1326 }
1327}
1328
1329
1330static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1331
1332/**
1333 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1334 * @adapter: pointer to SAP adapter struct
1335 *
1336 * This function starts the ACS procedure if there are no
1337 * constraints like MBSSID DFS restrictions.
1338 *
1339 * Return: Status of ACS Start procedure
1340 */
1341
1342static int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
1343{
1344
1345 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1346 tsap_Config_t *sap_config;
1347 tpWLAN_SAPEventCB acs_event_callback;
1348 int status;
1349
1350 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301351 if (hdd_ctx->acs_policy.acs_channel)
1352 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1353 else
1354 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001355
1356 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1357 if (status < 0) {
1358 return status;
1359 } else {
1360 if (status > 0) {
1361 /*notify hostapd about channel override */
1362 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1363 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1364 return 0;
1365 }
1366 }
1367 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1368 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001369 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001370 return -EINVAL;
1371 }
1372
1373 acs_event_callback = hdd_hostapd_sap_event_cb;
1374
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301375 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301376 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Jeff Johnson020db452016-06-29 14:37:26 -07001377 hdd_notice("ACS Started for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001378 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001379 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001380 acs_event_callback, sap_config, adapter->dev);
1381
1382
1383 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001384 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001385 return -EINVAL;
1386 }
1387 sap_config->acs_cfg.acs_mode = true;
1388 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1389
1390 return 0;
1391}
1392
1393/**
1394 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1395 * @wiphy: Linux wiphy struct pointer
1396 * @wdev: Linux wireless device struct pointer
1397 * @data: ACS information from hostapd
1398 * @data_len: ACS information length
1399 *
1400 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1401 * and starts ACS procedure.
1402 *
1403 * Return: ACS procedure start status
1404 */
1405
1406static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1407 struct wireless_dev *wdev,
1408 const void *data, int data_len)
1409{
1410 struct net_device *ndev = wdev->netdev;
1411 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1412 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1413 tsap_Config_t *sap_config;
1414 struct sk_buff *temp_skbuff;
1415 int status = -EINVAL, i = 0;
1416 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1417 bool ht_enabled, ht40_enabled, vht_enabled;
1418 uint8_t ch_width;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05301419 uint8_t weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001420
1421 /* ***Note*** Donot set SME config related to ACS operation here because
1422 * ACS operation is not synchronouse and ACS for Second AP may come when
1423 * ACS operation for first AP is going on. So only do_acs is split to
1424 * seperate start_acs routine. Also SME-PMAC struct that is used to
1425 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1426 * config shall be set only from start_acs.
1427 */
1428
1429 /* nla_policy Policy template. Policy not applied as some attributes are
1430 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1431 *
1432 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1433 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1434 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1435 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1436 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1437 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1438 */
1439
Jeff Johnson1f61b612016-02-12 16:28:33 -08001440 ENTER_DEV(ndev);
1441
Anurag Chouhan6d760662016-02-20 16:05:43 +05301442 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001443 hdd_err("Command not allowed in FTM mode");
1444 return -EPERM;
1445 }
1446
1447 if (hdd_ctx->config->force_sap_acs) {
Jeff Johnson020db452016-06-29 14:37:26 -07001448 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001449 return -EPERM;
1450 }
1451
1452 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301453 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001454 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301455
Naveen Rawat64e477e2016-05-20 10:34:56 -07001456 if (cds_is_sub_20_mhz_enabled()) {
1457 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1458 status = -EINVAL;
1459 goto out;
1460 }
1461
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001462 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301463 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001464
1465 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1466 NULL);
1467 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001468 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001469 goto out;
1470 }
1471
1472 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001473 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001474 goto out;
1475 }
1476 sap_config->acs_cfg.hw_mode = nla_get_u8(
1477 tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1478
1479 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1480 ht_enabled =
1481 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1482 else
1483 ht_enabled = 0;
1484
1485 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1486 ht40_enabled =
1487 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1488 else
1489 ht40_enabled = 0;
1490
1491 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1492 vht_enabled =
1493 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1494 else
1495 vht_enabled = 0;
1496
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301497 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1498 vht_enabled = 0;
1499 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1500 }
1501
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001502 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1503 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1504 } else {
1505 if (ht_enabled && ht40_enabled)
1506 ch_width = 40;
1507 else
1508 ch_width = 20;
1509 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301510
1511 /* this may be possible, when sap_force_11n_for_11ac is set */
1512 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1513 if (ht_enabled && ht40_enabled)
1514 ch_width = 40;
1515 else
1516 ch_width = 20;
1517 }
1518
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001519 if (ch_width == 80)
1520 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1521 else if (ch_width == 40)
1522 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1523 else
1524 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1525
1526 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1527 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1528 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1529 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1530 * since it contains the frequency values of the channels in
1531 * the channel list.
1532 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1533 * is present
1534 */
1535 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1536 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1537 sap_config->acs_cfg.ch_list_count = nla_len(
1538 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1539 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301540 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001541 sizeof(uint8_t) *
1542 sap_config->acs_cfg.ch_list_count);
1543 if (sap_config->acs_cfg.ch_list == NULL)
1544 goto out;
1545
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301546 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001547 sap_config->acs_cfg.ch_list_count);
1548 }
1549 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1550 uint32_t *freq =
1551 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1552 sap_config->acs_cfg.ch_list_count = nla_len(
1553 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1554 sizeof(uint32_t);
1555 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301556 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001557 sap_config->acs_cfg.ch_list_count);
1558 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001559 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001560 status = -ENOMEM;
1561 goto out;
1562 }
1563
1564 /* convert frequency to channel */
1565 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1566 sap_config->acs_cfg.ch_list[i] =
1567 ieee80211_frequency_to_channel(freq[i]);
1568 }
1569 }
1570
1571 hdd_debug("get pcl for DO_ACS vendor command");
1572
1573 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08001574 status = cds_get_pcl(CDS_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05301575 sap_config->acs_cfg.pcl_channels,
1576 &sap_config->acs_cfg.pcl_ch_count,
1577 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301578 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07001579 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001580
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001581 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301582 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
1583 !hdd_ctx->config->sap_force_11n_for_11ac) {
Jeff Johnson020db452016-06-29 14:37:26 -07001584 hdd_notice("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001585 vht_enabled = 1;
1586 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1587 sap_config->acs_cfg.ch_width =
1588 hdd_ctx->config->vhtChannelWidth;
1589 /* No VHT80 in 2.4G so perform ACS accordingly */
1590 if (sap_config->acs_cfg.end_ch <= 14 &&
1591 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ)
1592 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
1593 }
1594
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05301595 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
1596
Jeff Johnson020db452016-06-29 14:37:26 -07001597 hdd_notice("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 -08001598 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
1599 ch_width, ht_enabled, vht_enabled,
1600 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
1601
1602 if (sap_config->acs_cfg.ch_list_count) {
Jeff Johnson020db452016-06-29 14:37:26 -07001603 hdd_notice("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001604 sap_config->acs_cfg.ch_list_count);
1605 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Jeff Johnson020db452016-06-29 14:37:26 -07001606 hdd_notice("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001607 }
1608 sap_config->acs_cfg.acs_mode = true;
1609 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001610 /* ***Note*** Completion variable usage is not allowed
1611 * here since ACS scan operation may take max 2.2 sec
1612 * for 5G band:
1613 * 9 Active channel X 40 ms active scan time +
1614 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001615 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
1616 * for this long. So we split up the scanning part.
1617 */
1618 set_bit(ACS_PENDING, &adapter->event_flags);
Jeff Johnson020db452016-06-29 14:37:26 -07001619 hdd_notice("ACS Pending for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001620 status = 0;
1621 } else {
1622 status = wlan_hdd_cfg80211_start_acs(adapter);
1623 }
1624
1625out:
1626 if (0 == status) {
1627 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1628 NLMSG_HDRLEN);
1629 if (temp_skbuff != NULL)
1630 return cfg80211_vendor_cmd_reply(temp_skbuff);
1631 }
Liangwei Dong8baf7c82016-10-11 01:26:59 -04001632 wlan_hdd_undo_acs(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001633 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1634
1635 return status;
1636}
1637
1638 /**
1639 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1640 * @wiphy: Linux wiphy struct pointer
1641 * @wdev: Linux wireless device struct pointer
1642 * @data: ACS information from hostapd
1643 * @data_len: ACS information len
1644 *
1645 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1646 * and starts ACS procedure.
1647 *
1648 * Return: ACS procedure start status
1649 */
1650
1651static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1652 struct wireless_dev *wdev,
1653 const void *data, int data_len)
1654{
1655 int ret;
1656
1657 cds_ssr_protect(__func__);
1658 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
1659 cds_ssr_unprotect(__func__);
1660
1661 return ret;
1662}
1663
1664/**
Liangwei Dong8baf7c82016-10-11 01:26:59 -04001665 * wlan_hdd_undo_acs : Do cleanup of DO_ACS
1666 * @adapter: Pointer to adapter struct
1667 *
1668 * This function handle cleanup of what was done in DO_ACS, including free
1669 * memory.
1670 *
1671 * Return: void
1672 */
1673
1674void wlan_hdd_undo_acs(hdd_adapter_t *adapter)
1675{
1676 if (adapter == NULL)
1677 return;
1678 if (adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) {
1679 qdf_mem_free(adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list);
1680 adapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list = NULL;
1681 }
1682}
1683
1684/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001685 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
1686 * @work: Linux workqueue struct pointer for ACS work
1687 *
1688 * This function starts the ACS procedure which was marked pending when an ACS
1689 * procedure was in progress for a concurrent SAP interface.
1690 *
1691 * Return: None
1692 */
1693
1694static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
1695{
1696 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
1697 acs_pending_work.work);
1698 wlan_hdd_cfg80211_start_acs(adapter);
1699}
1700
1701/**
1702 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
1703 * @adapter: Pointer to SAP adapter struct
1704 * @pri_channel: SAP ACS procedure selected Primary channel
1705 * @sec_channel: SAP ACS procedure selected secondary channel
1706 *
1707 * This is a callback function from SAP module on ACS procedure is completed.
1708 * This function send the ACS selected channel information to hostapd
1709 *
1710 * Return: None
1711 */
1712
1713void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
1714{
1715 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1716 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
1717 struct sk_buff *vendor_event;
1718 int ret_val;
1719 hdd_adapter_t *con_sap_adapter;
1720 uint16_t ch_width;
1721
1722 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08001723 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001724 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
1725 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
1726 GFP_KERNEL);
1727
1728 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001729 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001730 return;
1731 }
1732
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001733 ret_val = nla_put_u8(vendor_event,
1734 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
1735 sap_cfg->acs_cfg.pri_ch);
1736 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001737 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001738 kfree_skb(vendor_event);
1739 return;
1740 }
1741
1742 ret_val = nla_put_u8(vendor_event,
1743 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
1744 sap_cfg->acs_cfg.ht_sec_ch);
1745 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001746 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001747 kfree_skb(vendor_event);
1748 return;
1749 }
1750
1751 ret_val = nla_put_u8(vendor_event,
1752 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
1753 sap_cfg->acs_cfg.vht_seg0_center_ch);
1754 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001755 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001756 kfree_skb(vendor_event);
1757 return;
1758 }
1759
1760 ret_val = nla_put_u8(vendor_event,
1761 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
1762 sap_cfg->acs_cfg.vht_seg1_center_ch);
1763 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001764 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001765 kfree_skb(vendor_event);
1766 return;
1767 }
1768
1769 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
1770 ch_width = 80;
1771 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1772 ch_width = 40;
1773 else
1774 ch_width = 20;
1775
1776 ret_val = nla_put_u16(vendor_event,
1777 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
1778 ch_width);
1779 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001780 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001781 kfree_skb(vendor_event);
1782 return;
1783 }
1784 if (sap_cfg->acs_cfg.pri_ch > 14)
1785 ret_val = nla_put_u8(vendor_event,
1786 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1787 QCA_ACS_MODE_IEEE80211A);
1788 else
1789 ret_val = nla_put_u8(vendor_event,
1790 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1791 QCA_ACS_MODE_IEEE80211G);
1792
1793 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001794 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001795 kfree_skb(vendor_event);
1796 return;
1797 }
1798
Jeff Johnson46b40792016-06-29 14:03:14 -07001799 hdd_notice("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 -08001800 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
1801 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
1802 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
1803
1804 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1805 /* ***Note*** As already mentioned Completion variable usage is not
1806 * allowed here since ACS scan operation may take max 2.2 sec.
1807 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
1808 * operation.
1809 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
1810 * when Primary AP ACS is complete and secondary AP ACS is started here
1811 * immediately, Primary AP start_bss may come inbetween ACS operation
1812 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
1813 * delay. This path and below constraint will be removed on sessionizing
1814 * SAP acs parameters and decoupling SAP from PMAC (WIP).
1815 * As per design constraint user space control application must take
1816 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
1817 * this code path. Sec AP hostapd should be started after Primary AP
1818 * start beaconing which can be confirmed by getchannel iwpriv command
1819 */
1820
1821 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
1822 if (con_sap_adapter &&
1823 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001824 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
1825 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001826 /* Lets give 500ms for OBSS + START_BSS to complete */
1827 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
1828 msecs_to_jiffies(500));
1829 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
1830 }
1831
1832 return;
1833}
1834
1835static int
1836__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1837 struct wireless_dev *wdev,
1838 const void *data,
1839 int data_len)
1840{
1841 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1842 struct sk_buff *skb = NULL;
1843 uint32_t fset = 0;
1844 int ret;
1845
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001846 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301847
Anurag Chouhan6d760662016-02-20 16:05:43 +05301848 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001849 hdd_err("Command not allowed in FTM mode");
1850 return -EPERM;
1851 }
1852
1853 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301854 if (ret)
1855 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001856
1857 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001858 hdd_notice("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001859 fset |= WIFI_FEATURE_INFRA;
1860 }
1861 if (true == hdd_is_5g_supported(pHddCtx)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001862 hdd_notice("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001863 fset |= WIFI_FEATURE_INFRA_5G;
1864 }
1865#ifdef WLAN_FEATURE_P2P
1866 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
1867 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Jeff Johnson020db452016-06-29 14:37:26 -07001868 hdd_notice("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001869 fset |= WIFI_FEATURE_P2P;
1870 }
1871#endif
1872 fset |= WIFI_FEATURE_SOFT_AP;
1873
1874 /* HOTSPOT is a supplicant feature, enable it by default */
1875 fset |= WIFI_FEATURE_HOTSPOT;
1876
1877#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301878 if (pHddCtx->config->extscan_enabled &&
1879 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001880 hdd_notice("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001881 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
1882 }
1883#endif
1884 if (wlan_hdd_nan_is_supported()) {
Jeff Johnson020db452016-06-29 14:37:26 -07001885 hdd_notice("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001886 fset |= WIFI_FEATURE_NAN;
1887 }
1888 if (sme_is_feature_supported_by_fw(RTT)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001889 hdd_notice("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001890 fset |= WIFI_FEATURE_D2D_RTT;
1891 fset |= WIFI_FEATURE_D2AP_RTT;
1892 }
1893#ifdef FEATURE_WLAN_SCAN_PNO
1894 if (pHddCtx->config->configPNOScanSupport &&
1895 sme_is_feature_supported_by_fw(PNO)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001896 hdd_notice("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001897 fset |= WIFI_FEATURE_PNO;
1898 }
1899#endif
1900 fset |= WIFI_FEATURE_ADDITIONAL_STA;
1901#ifdef FEATURE_WLAN_TDLS
1902 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
1903 sme_is_feature_supported_by_fw(TDLS)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001904 hdd_notice("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001905 fset |= WIFI_FEATURE_TDLS;
1906 }
1907 if (sme_is_feature_supported_by_fw(TDLS) &&
1908 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
1909 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001910 hdd_notice("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001911 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
1912 }
1913#endif
1914#ifdef WLAN_AP_STA_CONCURRENCY
1915 fset |= WIFI_FEATURE_AP_STA;
1916#endif
1917 fset |= WIFI_FEATURE_RSSI_MONITOR;
Srinivas Girigowdaa2cad3e2016-10-25 14:14:23 -07001918 fset |= WIFI_FEATURE_TX_TRANSMIT_POWER;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001919
1920 if (hdd_link_layer_stats_supported())
1921 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
1922
1923 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
1924 NLMSG_HDRLEN);
1925 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07001926 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001927 return -EINVAL;
1928 }
Jeff Johnson020db452016-06-29 14:37:26 -07001929 hdd_notice("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001930 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001931 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001932 goto nla_put_failure;
1933 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301934 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301935 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001936nla_put_failure:
1937 kfree_skb(skb);
1938 return -EINVAL;
1939}
1940
1941/**
1942 * wlan_hdd_cfg80211_get_supported_features() - get supported features
1943 * @wiphy: pointer to wireless wiphy structure.
1944 * @wdev: pointer to wireless_dev structure.
1945 * @data: Pointer to the data to be passed via vendor interface
1946 * @data_len:Length of the data to be passed
1947 *
1948 * Return: Return the Success or Failure code.
1949 */
1950static int
1951wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1952 struct wireless_dev *wdev,
1953 const void *data, int data_len)
1954{
1955 int ret = 0;
1956
1957 cds_ssr_protect(__func__);
1958 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
1959 data, data_len);
1960 cds_ssr_unprotect(__func__);
1961
1962 return ret;
1963}
1964
1965/**
1966 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1967 * @wiphy: pointer to wireless wiphy structure.
1968 * @wdev: pointer to wireless_dev structure.
1969 * @data: Pointer to the data to be passed via vendor interface
1970 * @data_len:Length of the data to be passed
1971 *
1972 * Set the MAC address that is to be used for scanning.
1973 *
1974 * Return: Return the Success or Failure code.
1975 */
1976static int
1977__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
1978 struct wireless_dev *wdev,
1979 const void *data,
1980 int data_len)
1981{
1982 tpSirScanMacOui pReqMsg = NULL;
1983 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1984 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301985 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001986 int ret;
1987
Jeff Johnson1f61b612016-02-12 16:28:33 -08001988 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001989
Anurag Chouhan6d760662016-02-20 16:05:43 +05301990 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001991 hdd_err("Command not allowed in FTM mode");
1992 return -EPERM;
1993 }
1994
1995 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301996 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001997 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001998
1999 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07002000 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002001 return -ENOTSUPP;
2002 }
2003
2004 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
2005 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002006 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002007 return -EINVAL;
2008 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302009 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002010 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07002011 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002012 return -ENOMEM;
2013 }
2014 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002015 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002016 goto fail;
2017 }
2018 nla_memcpy(&pReqMsg->oui[0],
2019 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
2020 sizeof(pReqMsg->oui));
Jeff Johnson020db452016-06-29 14:37:26 -07002021 hdd_notice("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002022 pReqMsg->oui[1], pReqMsg->oui[2]);
2023 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302024 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002025 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002026 goto fail;
2027 }
2028 return 0;
2029fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302030 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002031 return -EINVAL;
2032}
2033
2034/**
2035 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2036 * @wiphy: pointer to wireless wiphy structure.
2037 * @wdev: pointer to wireless_dev structure.
2038 * @data: Pointer to the data to be passed via vendor interface
2039 * @data_len:Length of the data to be passed
2040 *
2041 * Set the MAC address that is to be used for scanning. This is an
2042 * SSR-protecting wrapper function.
2043 *
2044 * Return: Return the Success or Failure code.
2045 */
2046static int
2047wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2048 struct wireless_dev *wdev,
2049 const void *data,
2050 int data_len)
2051{
2052 int ret;
2053
2054 cds_ssr_protect(__func__);
2055 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2056 data, data_len);
2057 cds_ssr_unprotect(__func__);
2058
2059 return ret;
2060}
2061
2062/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302063 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2064 * @wiphy: pointer phy adapter
2065 * @wdev: pointer to wireless device structure
2066 * @data: pointer to data buffer
2067 * @data_len: length of data
2068 *
2069 * This routine will give concurrency matrix
2070 *
2071 * Return: int status code
2072 */
2073static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2074 struct wireless_dev *wdev,
2075 const void *data,
2076 int data_len)
2077{
2078 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2079 uint8_t i, feature_sets, max_feature_sets;
2080 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2081 struct sk_buff *reply_skb;
2082 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2083 int ret;
2084
2085 ENTER_DEV(wdev->netdev);
2086
2087 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2088 hdd_err("Command not allowed in FTM mode");
2089 return -EPERM;
2090 }
2091
2092 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302093 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302094 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302095
2096 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2097 data, data_len, NULL)) {
2098 hdd_err("Invalid ATTR");
2099 return -EINVAL;
2100 }
2101
2102 /* Parse and fetch max feature set */
2103 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2104 hdd_err("Attr max feature set size failed");
2105 return -EINVAL;
2106 }
2107 max_feature_sets = nla_get_u32(tb[
2108 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2109 hdd_info("Max feature set size: %d", max_feature_sets);
2110
2111 /* Fill feature combination matrix */
2112 feature_sets = 0;
2113 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002114 WIFI_FEATURE_P2P;
2115 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2116 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302117 /* Add more feature combinations here */
2118
2119 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002120 hdd_info("Number of feature sets: %d", feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302121 hdd_info("Feature set matrix");
2122 for (i = 0; i < feature_sets; i++)
2123 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2124
2125 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2126 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2127 if (!reply_skb) {
2128 hdd_err("Feature set matrix: buffer alloc fail");
2129 return -ENOMEM;
2130 }
2131
2132 if (nla_put_u32(reply_skb,
2133 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2134 feature_sets) ||
2135 nla_put(reply_skb,
2136 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2137 sizeof(u32) * feature_sets,
2138 feature_set_matrix)) {
2139 hdd_err("nla put fail");
2140 kfree_skb(reply_skb);
2141 return -EINVAL;
2142 }
2143 return cfg80211_vendor_cmd_reply(reply_skb);
2144}
2145
2146/**
2147 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2148 * @wiphy: pointer to wireless wiphy structure.
2149 * @wdev: pointer to wireless_dev structure.
2150 * @data: Pointer to the data to be passed via vendor interface
2151 * @data_len:Length of the data to be passed
2152 *
2153 * Retrieves the concurrency feature set matrix
2154 *
2155 * Return: 0 on success, negative errno on failure
2156 */
2157static int
2158wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2159 struct wireless_dev *wdev,
2160 const void *data,
2161 int data_len)
2162{
2163 int ret;
2164
2165 cds_ssr_protect(__func__);
2166 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2167 data, data_len);
2168 cds_ssr_unprotect(__func__);
2169
2170 return ret;
2171}
2172
2173/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002174 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2175 * @feature_flags: pointer to the byte array of features.
2176 * @feature: Feature to be turned ON in the byte array.
2177 *
2178 * Return: None
2179 *
2180 * This is called to turn ON or SET the feature flag for the requested feature.
2181 **/
2182#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002183static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2184 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002185{
2186 uint32_t index;
2187 uint8_t bit_mask;
2188
2189 index = feature / NUM_BITS_IN_BYTE;
2190 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2191 feature_flags[index] |= bit_mask;
2192}
2193
2194/**
2195 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2196 * @wiphy: pointer to wireless wiphy structure.
2197 * @wdev: pointer to wireless_dev structure.
2198 * @data: Pointer to the data to be passed via vendor interface
2199 * @data_len:Length of the data to be passed
2200 *
2201 * This is called when wlan driver needs to send supported feature set to
2202 * supplicant upon a request/query from the supplicant.
2203 *
2204 * Return: Return the Success or Failure code.
2205 **/
2206#define MAX_CONCURRENT_CHAN_ON_24G 2
2207#define MAX_CONCURRENT_CHAN_ON_5G 2
2208static int
2209__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2210 struct wireless_dev *wdev,
2211 const void *data, int data_len)
2212{
2213 struct sk_buff *skb = NULL;
2214 uint32_t dbs_capability = 0;
2215 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302216 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002217 int ret_val;
2218
2219 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2220 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2221
Jeff Johnson1f61b612016-02-12 16:28:33 -08002222 ENTER_DEV(wdev->netdev);
2223
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002224 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2225 if (ret_val)
2226 return ret_val;
2227
Anurag Chouhan6d760662016-02-20 16:05:43 +05302228 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002229 hdd_err("Command not allowed in FTM mode");
2230 return -EPERM;
2231 }
2232
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002233 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002234 hdd_notice("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002235 wlan_hdd_cfg80211_set_feature(feature_flags,
2236 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2237 }
2238
2239 wlan_hdd_cfg80211_set_feature(feature_flags,
2240 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2241 if (wma_is_scan_simultaneous_capable())
2242 wlan_hdd_cfg80211_set_feature(feature_flags,
2243 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002244
2245 if (wma_is_p2p_lo_capable())
2246 wlan_hdd_cfg80211_set_feature(feature_flags,
2247 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2248
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002249 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2250 NLMSG_HDRLEN);
2251
2252 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002253 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002254 return -ENOMEM;
2255 }
2256
2257 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2258 sizeof(feature_flags), feature_flags))
2259 goto nla_put_failure;
2260
2261 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302262 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002263 if (one_by_one_dbs)
2264 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2265
2266 if (two_by_two_dbs)
2267 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2268
2269 if (!one_by_one_dbs && !two_by_two_dbs)
2270 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2271 } else {
2272 hdd_err("wma_get_dbs_hw_mode failed");
2273 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2274 }
2275
2276 hdd_info("dbs_capability is %d", dbs_capability);
2277
2278 if (nla_put_u32(skb,
2279 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2280 MAX_CONCURRENT_CHAN_ON_24G))
2281 goto nla_put_failure;
2282
2283 if (nla_put_u32(skb,
2284 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2285 MAX_CONCURRENT_CHAN_ON_5G))
2286 goto nla_put_failure;
2287
2288 return cfg80211_vendor_cmd_reply(skb);
2289
2290nla_put_failure:
2291 kfree_skb(skb);
2292 return -EINVAL;
2293}
2294
2295/**
2296 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2297 * @wiphy: pointer to wireless wiphy structure.
2298 * @wdev: pointer to wireless_dev structure.
2299 * @data: Pointer to the data to be passed via vendor interface
2300 * @data_len:Length of the data to be passed
2301 *
2302 * This is called when wlan driver needs to send supported feature set to
2303 * supplicant upon a request/query from the supplicant.
2304 *
2305 * Return: Return the Success or Failure code.
2306 */
2307static int
2308wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2309 struct wireless_dev *wdev,
2310 const void *data, int data_len)
2311{
2312 int ret;
2313
2314 cds_ssr_protect(__func__);
2315 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2316 data, data_len);
2317 cds_ssr_unprotect(__func__);
2318
2319 return ret;
2320}
2321
2322
2323/**
2324 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2325 * @wiphy: The wiphy structure
2326 * @wdev: The wireless device
2327 * @data: Data passed by framework
2328 * @data_len: Parameters to be configured passed as data
2329 *
2330 * The roaming related parameters are configured by the framework
2331 * using this interface.
2332 *
2333 * Return: Return either success or failure code.
2334 */
2335static int
2336__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2337 struct wireless_dev *wdev, const void *data, int data_len)
2338{
2339 struct net_device *dev = wdev->netdev;
2340 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2341 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2342 uint8_t session_id;
2343 struct roam_ext_params roam_params;
2344 uint32_t cmd_type, req_id;
2345 struct nlattr *curr_attr;
2346 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2347 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2348 int rem, i;
2349 uint32_t buf_len = 0;
2350 int ret;
2351
Jeff Johnson1f61b612016-02-12 16:28:33 -08002352 ENTER_DEV(dev);
2353
Anurag Chouhan6d760662016-02-20 16:05:43 +05302354 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002355 hdd_err("Command not allowed in FTM mode");
2356 return -EPERM;
2357 }
2358
2359 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302360 if (ret)
2361 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002362
2363 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2364 data, data_len,
2365 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002366 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002367 return -EINVAL;
2368 }
2369 /* Parse and fetch Command Type*/
2370 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002371 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002372 goto fail;
2373 }
2374 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302375 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002376 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2377 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002378 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002379 goto fail;
2380 }
2381 req_id = nla_get_u32(
2382 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002383 hdd_debug("Req Id (%d)", req_id);
2384 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002385 switch (cmd_type) {
2386 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2387 i = 0;
2388 nla_for_each_nested(curr_attr,
2389 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2390 rem) {
2391 if (nla_parse(tb2,
2392 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2393 nla_data(curr_attr), nla_len(curr_attr),
2394 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002395 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002396 goto fail;
2397 }
2398 /* Parse and Fetch allowed SSID list*/
2399 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002400 hdd_err("attr allowed ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002401 goto fail;
2402 }
2403 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2404 /*
2405 * Upper Layers include a null termination character.
2406 * Check for the actual permissible length of SSID and
2407 * also ensure not to copy the NULL termination
2408 * character to the driver buffer.
2409 */
2410 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2411 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2412 nla_memcpy(
2413 roam_params.ssid_allowed_list[i].ssId,
2414 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2415 buf_len - 1);
2416 roam_params.ssid_allowed_list[i].length =
2417 buf_len - 1;
Jeff Johnson020db452016-06-29 14:37:26 -07002418 hdd_debug("SSID[%d]: %.*s,length = %d", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002419 roam_params.ssid_allowed_list[i].length,
2420 roam_params.ssid_allowed_list[i].ssId,
2421 roam_params.ssid_allowed_list[i].length);
2422 i++;
2423 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002424 hdd_err("Invalid buffer length");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002425 }
2426 }
2427 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002428 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002429 roam_params.num_ssid_allowed_list);
2430 sme_update_roam_params(pHddCtx->hHal, session_id,
2431 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2432 break;
2433 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2434 /* Parse and fetch 5G Boost Threshold */
2435 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002436 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002437 goto fail;
2438 }
2439 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2440 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002441 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002442 roam_params.raise_rssi_thresh_5g);
2443 /* Parse and fetch 5G Penalty Threshold */
2444 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002445 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002446 goto fail;
2447 }
2448 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2449 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002450 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002451 roam_params.drop_rssi_thresh_5g);
2452 /* Parse and fetch 5G Boost Factor */
2453 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002454 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002455 goto fail;
2456 }
2457 roam_params.raise_factor_5g = nla_get_u32(
2458 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002459 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002460 roam_params.raise_factor_5g);
2461 /* Parse and fetch 5G Penalty factor */
2462 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002463 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002464 goto fail;
2465 }
2466 roam_params.drop_factor_5g = nla_get_u32(
2467 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002468 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002469 roam_params.drop_factor_5g);
2470 /* Parse and fetch 5G Max Boost */
2471 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002472 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002473 goto fail;
2474 }
2475 roam_params.max_raise_rssi_5g = nla_get_u32(
2476 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002477 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002478 roam_params.max_raise_rssi_5g);
2479 /* Parse and fetch Rssi Diff */
2480 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002481 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002482 goto fail;
2483 }
2484 roam_params.rssi_diff = nla_get_s32(
2485 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002486 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002487 roam_params.rssi_diff);
2488 /* Parse and fetch Alert Rssi Threshold */
2489 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002490 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002491 goto fail;
2492 }
2493 roam_params.alert_rssi_threshold = nla_get_u32(
2494 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002495 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002496 roam_params.alert_rssi_threshold);
2497 sme_update_roam_params(pHddCtx->hHal, session_id,
2498 roam_params,
2499 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2500 break;
2501 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2502 /* Parse and fetch Activate Good Rssi Roam */
2503 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002504 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002505 goto fail;
2506 }
2507 roam_params.good_rssi_roam = nla_get_s32(
2508 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002509 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002510 roam_params.good_rssi_roam);
2511 sme_update_roam_params(pHddCtx->hHal, session_id,
2512 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2513 break;
2514 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2515 /* Parse and fetch number of preferred BSSID */
2516 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002517 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002518 goto fail;
2519 }
2520 roam_params.num_bssid_favored = nla_get_u32(
2521 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002522 hdd_debug("Num of Preferred BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002523 roam_params.num_bssid_favored);
2524 i = 0;
2525 nla_for_each_nested(curr_attr,
2526 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2527 rem) {
2528 if (nla_parse(tb2,
2529 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2530 nla_data(curr_attr), nla_len(curr_attr),
2531 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002532 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002533 goto fail;
2534 }
2535 /* Parse and fetch MAC address */
2536 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002537 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002538 goto fail;
2539 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002540 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002541 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302542 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002543 hdd_debug(MAC_ADDRESS_STR,
2544 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002545 /* Parse and fetch preference factor*/
2546 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002547 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002548 goto fail;
2549 }
2550 roam_params.bssid_favored_factor[i] = nla_get_u32(
2551 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002552 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002553 roam_params.bssid_favored_factor[i]);
2554 i++;
2555 }
2556 sme_update_roam_params(pHddCtx->hHal, session_id,
2557 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
2558 break;
2559 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
2560 /* Parse and fetch number of blacklist BSSID */
2561 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002562 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002563 goto fail;
2564 }
2565 roam_params.num_bssid_avoid_list = nla_get_u32(
2566 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002567 hdd_debug("Num of blacklist BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002568 roam_params.num_bssid_avoid_list);
2569 i = 0;
2570 nla_for_each_nested(curr_attr,
2571 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
2572 rem) {
2573 if (nla_parse(tb2,
2574 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2575 nla_data(curr_attr), nla_len(curr_attr),
2576 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002577 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002578 goto fail;
2579 }
2580 /* Parse and fetch MAC address */
2581 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002582 hdd_err("attr blacklist addr failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002583 goto fail;
2584 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002585 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002586 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302587 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002588 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002589 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002590 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002591 i++;
2592 }
2593 sme_update_roam_params(pHddCtx->hHal, session_id,
2594 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
2595 break;
2596 }
2597 return 0;
2598fail:
2599 return -EINVAL;
2600}
2601
2602/**
2603 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
2604 * @wiphy: pointer to wireless wiphy structure.
2605 * @wdev: pointer to wireless_dev structure.
2606 * @data: Pointer to the data to be passed via vendor interface
2607 * @data_len:Length of the data to be passed
2608 *
2609 * Return: Return the Success or Failure code.
2610 */
2611static int
2612wlan_hdd_cfg80211_set_ext_roam_params(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_set_ext_roam_params(wiphy, wdev,
2621 data, data_len);
2622 cds_ssr_unprotect(__func__);
2623
2624 return ret;
2625}
2626
2627static const struct nla_policy
2628wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
2629 +1] = {
2630 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
2631};
2632
2633/**
2634 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
2635 * @hdd_ctx: HDD context
2636 * @device_mode: device mode
2637 * Return: bool
2638 */
2639static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08002640 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002641{
2642 hdd_adapter_t *adapter;
2643 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
2644 hdd_ap_ctx_t *ap_ctx;
2645 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302646 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002647
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302648 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002649 &adapter_node);
2650
2651 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302652 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002653 adapter = adapter_node->pAdapter;
2654
2655 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002656 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002657 ap_ctx =
2658 WLAN_HDD_GET_AP_CTX_PTR(adapter);
2659
2660 /*
2661 * if there is SAP already running on DFS channel,
2662 * do not disable scan on dfs channels. Note that
2663 * with SAP on DFS, there cannot be conurrency on
2664 * single radio. But then we can have multiple
2665 * radios !!
2666 */
2667 if (CHANNEL_STATE_DFS ==
2668 cds_get_channel_state(
2669 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002670 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002671 return true;
2672 }
2673 }
2674
2675 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002676 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002677 sta_ctx =
2678 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2679
2680 /*
2681 * if STA is already connected on DFS channel,
2682 * do not disable scan on dfs channels
2683 */
2684 if (hdd_conn_is_connected(sta_ctx) &&
2685 (CHANNEL_STATE_DFS ==
2686 cds_get_channel_state(
2687 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002688 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002689 return true;
2690 }
2691 }
2692
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302693 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002694 adapter_node,
2695 &next);
2696 adapter_node = next;
2697 }
2698
2699 return false;
2700}
2701
2702/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002703 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
2704 * @hdd_ctx: HDD context within host driver
2705 * @adapter: Adapter pointer
2706 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
2707 *
2708 * Loops through devices to see who is operating on DFS channels
2709 * and then disables/enables DFS channels by calling SME API.
2710 * Fails the disable request if any device is active on a DFS channel.
2711 *
2712 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002713 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002714
2715int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
2716 hdd_adapter_t *adapter,
2717 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002718{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002719 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302720 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002721 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002722
2723 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
2724 if (no_dfs_flag) {
2725 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002726 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002727
2728 if (true == status)
2729 return -EOPNOTSUPP;
2730
2731 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002732 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002733
2734 if (true == status)
2735 return -EOPNOTSUPP;
2736 }
2737
2738 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
2739
2740 hdd_abort_mac_scan_all_adapters(hdd_ctx);
2741
2742 /*
2743 * call the SME API to tunnel down the new channel list
2744 * to the firmware
2745 */
2746 status = sme_handle_dfs_chan_scan(
2747 h_hal, hdd_ctx->config->enableDFSChnlScan);
2748
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302749 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002750 ret_val = 0;
2751
2752 /*
2753 * Clear the SME scan cache also. Note that the
2754 * clearing of scan results is independent of session;
2755 * so no need to iterate over
2756 * all sessions
2757 */
2758 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302759 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002760 ret_val = -EPERM;
2761 }
2762
2763 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002764 hdd_notice(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002765 ret_val = 0;
2766 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002767 return ret_val;
2768}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002769
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002770/**
2771 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
2772 * @wiphy: corestack handler
2773 * @wdev: wireless device
2774 * @data: data
2775 * @data_len: data length
2776 * Return: success(0) or reason code for failure
2777 */
2778static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2779 struct wireless_dev *wdev,
2780 const void *data,
2781 int data_len)
2782{
2783 struct net_device *dev = wdev->netdev;
2784 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2785 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2786 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
2787 int ret_val;
2788 uint32_t no_dfs_flag = 0;
2789
Jeff Johnson1f61b612016-02-12 16:28:33 -08002790 ENTER_DEV(dev);
2791
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002792 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302793 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002794 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002795
2796 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
2797 data, data_len,
2798 wlan_hdd_set_no_dfs_flag_config_policy)) {
2799 hdd_err("invalid attr");
2800 return -EINVAL;
2801 }
2802
2803 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
2804 hdd_err("attr dfs flag failed");
2805 return -EINVAL;
2806 }
2807
2808 no_dfs_flag = nla_get_u32(
2809 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
2810
Jeff Johnson020db452016-06-29 14:37:26 -07002811 hdd_notice(" DFS flag = %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002812
2813 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07002814 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002815 return -EINVAL;
2816 }
2817
2818 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
2819 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002820 return ret_val;
2821}
2822
2823/**
2824 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
2825 *
2826 * @wiphy: wiphy device pointer
2827 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07002828 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002829 * @data_len: Buffer length
2830 *
2831 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
2832 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
2833 *
2834 * Return: EOK or other error codes.
2835 */
2836
2837static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2838 struct wireless_dev *wdev,
2839 const void *data,
2840 int data_len)
2841{
2842 int ret;
2843
2844 cds_ssr_protect(__func__);
2845 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
2846 data, data_len);
2847 cds_ssr_unprotect(__func__);
2848
2849 return ret;
2850}
2851
Manikandan Mohan80dea792016-04-28 16:36:48 -07002852static const struct nla_policy
2853wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
2854 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
2855};
2856
2857/**
2858 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2859 * @wiphy: wiphy device pointer
2860 * @wdev: wireless device pointer
2861 * @data: Vendor command data buffer
2862 * @data_len: Buffer length
2863 *
2864 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2865 * setup WISA Mode features.
2866 *
2867 * Return: Success(0) or reason code for failure
2868 */
2869static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2870 struct wireless_dev *wdev, const void *data, int data_len)
2871{
2872 struct net_device *dev = wdev->netdev;
2873 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2874 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2875 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
2876 struct sir_wisa_params wisa;
2877 int ret_val;
2878 QDF_STATUS status;
2879 bool wisa_mode;
Leo Changfdb45c32016-10-28 11:09:23 -07002880 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
2881 void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002882
2883 ENTER_DEV(dev);
2884 ret_val = wlan_hdd_validate_context(hdd_ctx);
2885 if (ret_val)
2886 goto err;
2887
2888 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2889 hdd_err("Command not allowed in FTM mode");
2890 return -EPERM;
2891 }
2892
2893 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
2894 wlan_hdd_wisa_cmd_policy)) {
2895 hdd_err("Invalid WISA cmd attributes");
2896 ret_val = -EINVAL;
2897 goto err;
2898 }
2899 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
2900 hdd_err("Invalid WISA mode");
2901 ret_val = -EINVAL;
2902 goto err;
2903 }
2904
2905 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
2906 hdd_info("WISA Mode: %d", wisa_mode);
2907 wisa.mode = wisa_mode;
2908 wisa.vdev_id = adapter->sessionId;
2909 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002910 if (!QDF_IS_STATUS_SUCCESS(status)) {
2911 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002912 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002913 }
2914 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
Leo Changfdb45c32016-10-28 11:09:23 -07002915 cdp_set_wisa_mode(soc,
2916 cdp_get_vdev_from_vdev_id(soc, pdev,
2917 adapter->sessionId),
2918 wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002919err:
2920 EXIT();
2921 return ret_val;
2922}
2923
2924/**
2925 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2926 * @wiphy: corestack handler
2927 * @wdev: wireless device
2928 * @data: data
2929 * @data_len: data length
2930 *
2931 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2932 * setup WISA mode features.
2933 *
2934 * Return: Success(0) or reason code for failure
2935 */
2936static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2937 struct wireless_dev *wdev,
2938 const void *data,
2939 int data_len)
2940{
2941 int ret;
2942
2943 cds_ssr_protect(__func__);
2944 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
2945 cds_ssr_unprotect(__func__);
2946
2947 return ret;
2948}
2949
Anurag Chouhan96919482016-07-13 16:36:57 +05302950/*
2951 * define short names for the global vendor params
2952 * used by __wlan_hdd_cfg80211_get_station_cmd()
2953 */
2954#define STATION_INVALID \
2955 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
2956#define STATION_INFO \
2957 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
2958#define STATION_ASSOC_FAIL_REASON \
2959 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
2960#define STATION_MAX \
2961 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
2962
2963static const struct nla_policy
2964hdd_get_station_policy[STATION_MAX + 1] = {
2965 [STATION_INFO] = {.type = NLA_FLAG},
2966 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
2967};
2968
2969/**
2970 * hdd_get_station_assoc_fail() - Handle get station assoc fail
2971 * @hdd_ctx: HDD context within host driver
2972 * @wdev: wireless device
2973 *
2974 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
2975 * Validate cmd attributes and send the station info to upper layers.
2976 *
2977 * Return: Success(0) or reason code for failure
2978 */
2979static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
2980 hdd_adapter_t *adapter)
2981{
2982 struct sk_buff *skb = NULL;
2983 uint32_t nl_buf_len;
2984 hdd_station_ctx_t *hdd_sta_ctx;
2985
2986 nl_buf_len = NLMSG_HDRLEN;
2987 nl_buf_len += sizeof(uint32_t);
2988 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
2989
2990 if (!skb) {
2991 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
2992 return -ENOMEM;
2993 }
2994
2995 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2996
2997 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
2998 hdd_sta_ctx->conn_info.assoc_status_code)) {
2999 hdd_err("put fail");
3000 goto fail;
3001 }
3002 return cfg80211_vendor_cmd_reply(skb);
3003fail:
3004 if (skb)
3005 kfree_skb(skb);
3006 return -EINVAL;
3007}
3008
3009/**
3010 * hdd_map_auth_type() - transform auth type specific to
3011 * vendor command
3012 * @auth_type: csr auth type
3013 *
3014 * Return: Success(0) or reason code for failure
3015 */
3016static int hdd_convert_auth_type(uint32_t auth_type)
3017{
3018 uint32_t ret_val;
3019
3020 switch (auth_type) {
3021 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
3022 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
3023 break;
3024 case eCSR_AUTH_TYPE_SHARED_KEY:
3025 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
3026 break;
3027 case eCSR_AUTH_TYPE_WPA:
3028 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
3029 break;
3030 case eCSR_AUTH_TYPE_WPA_PSK:
3031 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
3032 break;
3033 case eCSR_AUTH_TYPE_AUTOSWITCH:
3034 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3035 break;
3036 case eCSR_AUTH_TYPE_WPA_NONE:
3037 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3038 break;
3039 case eCSR_AUTH_TYPE_RSN:
3040 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3041 break;
3042 case eCSR_AUTH_TYPE_RSN_PSK:
3043 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3044 break;
3045 case eCSR_AUTH_TYPE_FT_RSN:
3046 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3047 break;
3048 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3049 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3050 break;
3051 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3052 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3053 break;
3054 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3055 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3056 break;
3057 case eCSR_AUTH_TYPE_CCKM_WPA:
3058 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3059 break;
3060 case eCSR_AUTH_TYPE_CCKM_RSN:
3061 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3062 break;
3063 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3064 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3065 break;
3066 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3067 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3068 break;
3069 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3070 case eCSR_AUTH_TYPE_FAILED:
3071 case eCSR_AUTH_TYPE_NONE:
3072 default:
3073 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3074 break;
3075 }
3076 return ret_val;
3077}
3078
3079/**
3080 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3081 * vendor command
3082 * @dot11mode: dot11mode
3083 *
3084 * Return: Success(0) or reason code for failure
3085 */
3086static int hdd_convert_dot11mode(uint32_t dot11mode)
3087{
3088 uint32_t ret_val;
3089
3090 switch (dot11mode) {
3091 case eCSR_CFG_DOT11_MODE_11A:
3092 ret_val = QCA_WLAN_802_11_MODE_11A;
3093 break;
3094 case eCSR_CFG_DOT11_MODE_11B:
3095 ret_val = QCA_WLAN_802_11_MODE_11B;
3096 break;
3097 case eCSR_CFG_DOT11_MODE_11G:
3098 ret_val = QCA_WLAN_802_11_MODE_11G;
3099 break;
3100 case eCSR_CFG_DOT11_MODE_11N:
3101 ret_val = QCA_WLAN_802_11_MODE_11N;
3102 break;
3103 case eCSR_CFG_DOT11_MODE_11AC:
3104 ret_val = QCA_WLAN_802_11_MODE_11AC;
3105 break;
3106 case eCSR_CFG_DOT11_MODE_AUTO:
3107 case eCSR_CFG_DOT11_MODE_ABG:
3108 default:
3109 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3110 }
3111 return ret_val;
3112}
3113
3114/**
3115 * hdd_add_tx_bitrate() - add tx bitrate attribute
3116 * @skb: pointer to sk buff
3117 * @hdd_sta_ctx: pointer to hdd station context
3118 * @idx: attribute index
3119 *
3120 * Return: Success(0) or reason code for failure
3121 */
3122static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3123 hdd_station_ctx_t *hdd_sta_ctx,
3124 int idx)
3125{
3126 struct nlattr *nla_attr;
3127 uint32_t bitrate, bitrate_compat;
3128
3129 nla_attr = nla_nest_start(skb, idx);
3130 if (!nla_attr)
3131 goto fail;
3132 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3133 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3134
3135 /* report 16-bit bitrate only if we can */
3136 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3137 if (bitrate > 0 &&
3138 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3139 hdd_err("put fail");
3140 goto fail;
3141 }
3142 if (bitrate_compat > 0 &&
3143 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3144 hdd_err("put fail");
3145 goto fail;
3146 }
3147 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3148 hdd_sta_ctx->conn_info.txrate.nss)) {
3149 hdd_err("put fail");
3150 goto fail;
3151 }
3152 nla_nest_end(skb, nla_attr);
3153 return 0;
3154fail:
3155 return -EINVAL;
3156}
3157
3158/**
3159 * hdd_add_sta_info() - add station info attribute
3160 * @skb: pointer to sk buff
3161 * @hdd_sta_ctx: pointer to hdd station context
3162 * @idx: attribute index
3163 *
3164 * Return: Success(0) or reason code for failure
3165 */
3166static int32_t hdd_add_sta_info(struct sk_buff *skb,
3167 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3168{
3169 struct nlattr *nla_attr;
3170
3171 nla_attr = nla_nest_start(skb, idx);
3172 if (!nla_attr)
3173 goto fail;
3174 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3175 (hdd_sta_ctx->conn_info.signal + 100))) {
3176 hdd_err("put fail");
3177 goto fail;
3178 }
3179 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3180 goto fail;
3181 nla_nest_end(skb, nla_attr);
3182 return 0;
3183fail:
3184 return -EINVAL;
3185}
3186
3187/**
3188 * hdd_add_survey_info() - add survey info attribute
3189 * @skb: pointer to sk buff
3190 * @hdd_sta_ctx: pointer to hdd station context
3191 * @idx: attribute index
3192 *
3193 * Return: Success(0) or reason code for failure
3194 */
3195static int32_t hdd_add_survey_info(struct sk_buff *skb,
3196 hdd_station_ctx_t *hdd_sta_ctx,
3197 int idx)
3198{
3199 struct nlattr *nla_attr;
3200
3201 nla_attr = nla_nest_start(skb, idx);
3202 if (!nla_attr)
3203 goto fail;
3204 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3205 hdd_sta_ctx->conn_info.freq) ||
3206 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3207 (hdd_sta_ctx->conn_info.noise + 100))) {
3208 hdd_err("put fail");
3209 goto fail;
3210 }
3211 nla_nest_end(skb, nla_attr);
3212 return 0;
3213fail:
3214 return -EINVAL;
3215}
3216
3217/**
3218 * hdd_add_link_standard_info() - add link info attribute
3219 * @skb: pointer to sk buff
3220 * @hdd_sta_ctx: pointer to hdd station context
3221 * @idx: attribute index
3222 *
3223 * Return: Success(0) or reason code for failure
3224 */
3225static int32_t
3226hdd_add_link_standard_info(struct sk_buff *skb,
3227 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3228{
3229 struct nlattr *nla_attr;
3230
3231 nla_attr = nla_nest_start(skb, idx);
3232 if (!nla_attr)
3233 goto fail;
3234 if (nla_put(skb,
3235 NL80211_ATTR_SSID,
3236 hdd_sta_ctx->conn_info.SSID.SSID.length,
3237 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3238 hdd_err("put fail");
3239 goto fail;
3240 }
3241 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3242 goto fail;
3243 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3244 goto fail;
3245 nla_nest_end(skb, nla_attr);
3246 return 0;
3247fail:
3248 return -EINVAL;
3249}
3250
3251/**
3252 * hdd_add_ap_standard_info() - add ap info attribute
3253 * @skb: pointer to sk buff
3254 * @hdd_sta_ctx: pointer to hdd station context
3255 * @idx: attribute index
3256 *
3257 * Return: Success(0) or reason code for failure
3258 */
3259static int32_t
3260hdd_add_ap_standard_info(struct sk_buff *skb,
3261 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3262{
3263 struct nlattr *nla_attr;
3264
3265 nla_attr = nla_nest_start(skb, idx);
3266 if (!nla_attr)
3267 goto fail;
3268 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3269 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3270 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3271 &hdd_sta_ctx->conn_info.vht_caps)) {
3272 hdd_err("put fail");
3273 goto fail;
3274 }
3275 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3276 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3277 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3278 &hdd_sta_ctx->conn_info.ht_caps)) {
3279 hdd_err("put fail");
3280 goto fail;
3281 }
3282 nla_nest_end(skb, nla_attr);
3283 return 0;
3284fail:
3285 return -EINVAL;
3286}
3287
3288/**
3289 * hdd_get_station_info() - send BSS information to supplicant
3290 * @hdd_ctx: pointer to hdd context
3291 * @adapter: pointer to adapter
3292 *
3293 * Return: 0 if success else error status
3294 */
3295static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3296 hdd_adapter_t *adapter)
3297{
3298 struct sk_buff *skb = NULL;
3299 uint8_t *tmp_hs20 = NULL;
3300 uint32_t nl_buf_len;
3301 hdd_station_ctx_t *hdd_sta_ctx;
3302
3303 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3304
3305 nl_buf_len = NLMSG_HDRLEN;
3306 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3307 sizeof(hdd_sta_ctx->conn_info.freq) +
3308 sizeof(hdd_sta_ctx->conn_info.noise) +
3309 sizeof(hdd_sta_ctx->conn_info.signal) +
3310 (sizeof(uint32_t) * 2) +
3311 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3312 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3313 sizeof(hdd_sta_ctx->conn_info.authType) +
3314 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3315 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3316 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3317 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3318 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3319 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3320 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3321 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3322 1);
3323 }
3324 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3325 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3326 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3327 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3328
3329
3330 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3331 if (!skb) {
3332 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3333 return -ENOMEM;
3334 }
3335
3336 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3337 LINK_INFO_STANDARD_NL80211_ATTR)) {
3338 hdd_err("put fail");
3339 goto fail;
3340 }
3341 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3342 AP_INFO_STANDARD_NL80211_ATTR)) {
3343 hdd_err("put fail");
3344 goto fail;
3345 }
3346 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3347 hdd_sta_ctx->conn_info.roam_count) ||
3348 nla_put_u32(skb, INFO_AKM,
3349 hdd_convert_auth_type(
3350 hdd_sta_ctx->conn_info.authType)) ||
3351 nla_put_u32(skb, WLAN802_11_MODE,
3352 hdd_convert_dot11mode(
3353 hdd_sta_ctx->conn_info.dot11Mode))) {
3354 hdd_err("put fail");
3355 goto fail;
3356 }
3357 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3358 if (nla_put(skb, HT_OPERATION,
3359 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3360 &hdd_sta_ctx->conn_info.ht_operation)) {
3361 hdd_err("put fail");
3362 goto fail;
3363 }
3364 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3365 if (nla_put(skb, VHT_OPERATION,
3366 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3367 &hdd_sta_ctx->conn_info.vht_operation)) {
3368 hdd_err("put fail");
3369 goto fail;
3370 }
3371 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3372 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3373 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3374 tmp_hs20 + 1)) {
3375 hdd_err("put fail");
3376 goto fail;
3377 }
3378
3379 return cfg80211_vendor_cmd_reply(skb);
3380fail:
3381 if (skb)
3382 kfree_skb(skb);
3383 return -EINVAL;
3384}
3385
3386/**
3387 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3388 * @wiphy: corestack handler
3389 * @wdev: wireless device
3390 * @data: data
3391 * @data_len: data length
3392 *
3393 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3394 * Validate cmd attributes and send the station info to upper layers.
3395 *
3396 * Return: Success(0) or reason code for failure
3397 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303398static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303399__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3400 struct wireless_dev *wdev,
3401 const void *data,
3402 int data_len)
3403{
3404 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3405 struct net_device *dev = wdev->netdev;
3406 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3407 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3408 int32_t status;
3409
3410 ENTER_DEV(dev);
3411 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3412 hdd_err("Command not allowed in FTM mode");
3413 status = -EPERM;
3414 goto out;
3415 }
3416
3417 status = wlan_hdd_validate_context(hdd_ctx);
3418 if (0 != status)
3419 goto out;
3420
3421
3422 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3423 data, data_len, NULL);
3424 if (status) {
3425 hdd_err("Invalid ATTR");
3426 goto out;
3427 }
3428
3429 /* Parse and fetch Command Type*/
3430 if (tb[STATION_INFO]) {
3431 status = hdd_get_station_info(hdd_ctx, adapter);
3432 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3433 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3434 } else {
3435 hdd_err("get station info cmd type failed");
3436 status = -EINVAL;
3437 goto out;
3438 }
3439 EXIT();
3440out:
3441 return status;
3442}
3443
3444/**
3445 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3446 * @wiphy: corestack handler
3447 * @wdev: wireless device
3448 * @data: data
3449 * @data_len: data length
3450 *
3451 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3452 * Validate cmd attributes and send the station info to upper layers.
3453 *
3454 * Return: Success(0) or reason code for failure
3455 */
3456static int32_t
3457hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3458 struct wireless_dev *wdev,
3459 const void *data,
3460 int data_len)
3461{
3462 int ret;
3463
3464 cds_ssr_protect(__func__);
3465 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3466 cds_ssr_unprotect(__func__);
3467
3468 return ret;
3469}
3470
3471/*
3472 * undef short names defined for get station command
3473 * used by __wlan_hdd_cfg80211_get_station_cmd()
3474 */
3475#undef STATION_INVALID
3476#undef STATION_INFO
3477#undef STATION_ASSOC_FAIL_REASON
3478#undef STATION_MAX
3479
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003480#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3481/**
3482 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3483 * @wiphy: pointer to wireless wiphy structure.
3484 * @wdev: pointer to wireless_dev structure.
3485 * @data: Pointer to the Key data
3486 * @data_len:Length of the data passed
3487 *
3488 * This is called when wlan driver needs to save the keys received via
3489 * vendor specific command.
3490 *
3491 * Return: Return the Success or Failure code.
3492 */
3493static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3494 struct wireless_dev *wdev,
3495 const void *data, int data_len)
3496{
3497 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
3498 struct net_device *dev = wdev->netdev;
3499 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
3500 hdd_context_t *hdd_ctx_ptr;
3501 int status;
3502
Jeff Johnson1f61b612016-02-12 16:28:33 -08003503 ENTER_DEV(dev);
3504
Anurag Chouhan6d760662016-02-20 16:05:43 +05303505 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003506 hdd_err("Command not allowed in FTM mode");
3507 return -EPERM;
3508 }
3509
3510 if ((data == NULL) || (data_len == 0) ||
3511 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003512 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003513 return -EINVAL;
3514 }
3515
3516 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
3517 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07003518 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003519 return -EINVAL;
3520 }
3521
3522 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303523 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003524 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003525 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
3526 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07003527 true,
3528 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303529 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
3530 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003531 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
3532 hdd_adapter_ptr->sessionId, local_pmk, data_len);
3533 return 0;
3534}
3535
3536/**
3537 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3538 * @wiphy: pointer to wireless wiphy structure.
3539 * @wdev: pointer to wireless_dev structure.
3540 * @data: Pointer to the Key data
3541 * @data_len:Length of the data passed
3542 *
3543 * This is called when wlan driver needs to save the keys received via
3544 * vendor specific command.
3545 *
3546 * Return: Return the Success or Failure code.
3547 */
3548static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3549 struct wireless_dev *wdev,
3550 const void *data, int data_len)
3551{
3552 int ret;
3553
3554 cds_ssr_protect(__func__);
3555 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
3556 cds_ssr_unprotect(__func__);
3557
3558 return ret;
3559}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003560#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003561
3562static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
3563 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
3564 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
3565 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07003566 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003567};
3568
3569/**
3570 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3571 * @wiphy: pointer to wireless wiphy structure.
3572 * @wdev: pointer to wireless_dev structure.
3573 * @data: Pointer to the data to be passed via vendor interface
3574 * @data_len:Length of the data to be passed
3575 *
3576 * This is called when wlan driver needs to send wifi driver related info
3577 * (driver/fw version) to the user space application upon request.
3578 *
3579 * Return: Return the Success or Failure code.
3580 */
3581static int
3582__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3583 struct wireless_dev *wdev,
3584 const void *data, int data_len)
3585{
3586 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3587 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07003588 tSirVersionString driver_version;
3589 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003590 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003591 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07003592 struct sk_buff *reply_skb;
3593 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003594
Jeff Johnson1f61b612016-02-12 16:28:33 -08003595 ENTER_DEV(wdev->netdev);
3596
Anurag Chouhan6d760662016-02-20 16:05:43 +05303597 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003598 hdd_err("Command not allowed in FTM mode");
3599 return -EPERM;
3600 }
3601
3602 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303603 if (status)
3604 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003605
3606 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
3607 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003608 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003609 return -EINVAL;
3610 }
3611
3612 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003613 hdd_err("Rcvd req for Driver version");
3614 strlcpy(driver_version, QWLAN_VERSIONSTR,
3615 sizeof(driver_version));
3616 skb_len += strlen(driver_version) + 1;
3617 count++;
3618 }
3619
3620 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
3621 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003622 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
3623 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003624 snprintf(firmware_version, sizeof(firmware_version),
3625 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
3626 skb_len += strlen(firmware_version) + 1;
3627 count++;
3628 }
3629
3630 if (count == 0) {
3631 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003632 return -EINVAL;
3633 }
3634
Ryan Hsu7ac88852016-04-28 10:20:34 -07003635 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
3636 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
3637
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003638 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003639 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003640 return -ENOMEM;
3641 }
3642
Ryan Hsu7ac88852016-04-28 10:20:34 -07003643 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3644 if (nla_put_string(reply_skb,
3645 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
3646 driver_version))
3647 goto error_nla_fail;
3648 }
3649
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05303650 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003651 if (nla_put_string(reply_skb,
3652 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
3653 firmware_version))
3654 goto error_nla_fail;
3655 }
3656
3657 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
3658 if (nla_put_u32(reply_skb,
3659 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
3660 hdd_ctx->radio_index))
3661 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003662 }
3663
3664 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003665
3666error_nla_fail:
3667 hdd_err("nla put fail");
3668 kfree_skb(reply_skb);
3669 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003670}
3671
3672/**
3673 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3674 * @wiphy: pointer to wireless wiphy structure.
3675 * @wdev: pointer to wireless_dev structure.
3676 * @data: Pointer to the data to be passed via vendor interface
3677 * @data_len:Length of the data to be passed
3678 *
3679 * This is called when wlan driver needs to send wifi driver related info
3680 * (driver/fw version) to the user space application upon request.
3681 *
3682 * Return: Return the Success or Failure code.
3683 */
3684static int
3685wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3686 struct wireless_dev *wdev,
3687 const void *data, int data_len)
3688{
3689 int ret;
3690
3691 cds_ssr_protect(__func__);
3692 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
3693 cds_ssr_unprotect(__func__);
3694
3695 return ret;
3696}
3697
3698/**
3699 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3700 * @wiphy: pointer to wireless wiphy structure.
3701 * @wdev: pointer to wireless_dev structure.
3702 * @data: Pointer to the data to be passed via vendor interface
3703 * @data_len:Length of the data to be passed
3704 *
3705 * This is called by userspace to know the supported logger features
3706 *
3707 * Return: Return the Success or Failure code.
3708 */
3709static int
3710__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3711 struct wireless_dev *wdev,
3712 const void *data, int data_len)
3713{
3714 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3715 int status;
3716 uint32_t features;
3717 struct sk_buff *reply_skb = NULL;
3718
Jeff Johnson1f61b612016-02-12 16:28:33 -08003719 ENTER_DEV(wdev->netdev);
3720
Anurag Chouhan6d760662016-02-20 16:05:43 +05303721 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003722 hdd_err("Command not allowed in FTM mode");
3723 return -EPERM;
3724 }
3725
3726 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303727 if (status)
3728 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003729
3730 features = 0;
3731
3732 if (hdd_is_memdump_supported())
3733 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
3734 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
3735 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
3736 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
3737
3738 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
3739 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
3740 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003741 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003742 return -ENOMEM;
3743 }
3744
Jeff Johnson020db452016-06-29 14:37:26 -07003745 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003746 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
3747 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003748 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003749 kfree_skb(reply_skb);
3750 return -EINVAL;
3751 }
3752
3753 return cfg80211_vendor_cmd_reply(reply_skb);
3754}
3755
3756/**
3757 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3758 * @wiphy: pointer to wireless wiphy structure.
3759 * @wdev: pointer to wireless_dev structure.
3760 * @data: Pointer to the data to be passed via vendor interface
3761 * @data_len:Length of the data to be passed
3762 *
3763 * This is called by userspace to know the supported logger features
3764 *
3765 * Return: Return the Success or Failure code.
3766 */
3767static int
3768wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3769 struct wireless_dev *wdev,
3770 const void *data, int data_len)
3771{
3772 int ret;
3773
3774 cds_ssr_protect(__func__);
3775 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
3776 data, data_len);
3777 cds_ssr_unprotect(__func__);
3778
3779 return ret;
3780}
3781
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003782#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003783/**
3784 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
3785 * @hdd_ctx_ptr: pointer to HDD Context.
3786 * @bssid: pointer to bssid of roamed AP.
3787 * @req_rsn_ie: Pointer to request RSN IE
3788 * @req_rsn_len: Length of the request RSN IE
3789 * @rsp_rsn_ie: Pointer to response RSN IE
3790 * @rsp_rsn_len: Length of the response RSN IE
3791 * @roam_info_ptr: Pointer to the roaming related information
3792 *
3793 * This is called when wlan driver needs to send the roaming and
3794 * authorization information after roaming.
3795 *
3796 * The information that would be sent is the request RSN IE, response
3797 * RSN IE and BSSID of the newly roamed AP.
3798 *
3799 * If the Authorized status is authenticated, then additional parameters
3800 * like PTK's KCK and KEK and Replay Counter would also be passed to the
3801 * supplicant.
3802 *
3803 * The supplicant upon receiving this event would ignore the legacy
3804 * cfg80211_roamed call and use the entire information from this event.
3805 * The cfg80211_roamed should still co-exist since the kernel will
3806 * make use of the parameters even if the supplicant ignores it.
3807 *
3808 * Return: Return the Success or Failure code.
3809 */
3810int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid,
3811 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
3812 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
3813{
3814 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003815 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003816 ENTER();
3817
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303818 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003819 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003820
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07003821 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08003822 !roam_info_ptr->roamSynchInProgress)
3823 return 0;
3824
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003825 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
3826 NULL,
3827 ETH_ALEN + req_rsn_len + rsp_rsn_len +
3828 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
3829 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003830 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003831 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
3832 GFP_KERNEL);
3833
3834 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003835 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003836 return -EINVAL;
3837 }
3838
3839 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
3840 ETH_ALEN, bssid) ||
3841 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
3842 req_rsn_len, req_rsn_ie) ||
3843 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
3844 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003845 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003846 goto nla_put_failure;
3847 }
Jeff Johnson020db452016-06-29 14:37:26 -07003848 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003849 if (roam_info_ptr->synchAuthStatus ==
3850 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07003851 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08003852 if (nla_put_u8(skb,
3853 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
3854 hdd_err("nla put fail");
3855 goto nla_put_failure;
3856 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003857 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
3858 /* if FT or CCKM connection: dont send replay counter */
3859 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
3860 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
3861 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
3862 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
3863 nla_put(skb,
3864 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
3865 SIR_REPLAY_CTR_LEN,
3866 roam_info_ptr->replay_ctr)) {
3867 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08003868 hdd_err("failed to send replay counter.");
3869 goto nla_put_failure;
3870 }
3871 if (nla_put(skb,
3872 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
3873 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
3874 nla_put(skb,
3875 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
3876 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
3877 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003878 goto nla_put_failure;
3879 }
3880 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07003881 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003882 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
3883 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003884 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003885 goto nla_put_failure;
3886 }
3887 }
3888
Jeff Johnson020db452016-06-29 14:37:26 -07003889 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003890 roam_info_ptr->subnet_change_status);
3891
3892 /*
3893 * Add subnet change status if subnet has changed
3894 * 0 = unchanged
3895 * 1 = changed
3896 * 2 = unknown
3897 */
3898 if (roam_info_ptr->subnet_change_status) {
3899 if (nla_put_u8(skb,
3900 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
3901 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003902 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003903 goto nla_put_failure;
3904 }
3905 }
3906
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003907 cfg80211_vendor_event(skb, GFP_KERNEL);
3908 return 0;
3909
3910nla_put_failure:
3911 kfree_skb(skb);
3912 return -EINVAL;
3913}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003914#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003915
3916static const struct nla_policy
3917wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
3918
3919 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
3920 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
3921 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303922 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303923 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
3924 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08003925 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
3926 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
3927 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
3928 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
3929 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05303930 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003931};
3932
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003933/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303934 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
3935 *
3936 * @adapter: Pointer to HDD adapter
3937 * @ie_data: Pointer to Scan IEs buffer
3938 * @ie_len: Length of Scan IEs
3939 *
3940 * Return: 0 on success; error number otherwise
3941 */
3942static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
3943 uint8_t *ie_data, uint8_t ie_len)
3944{
3945 hdd_scaninfo_t *scan_info = NULL;
3946 scan_info = &adapter->scan_info;
3947
3948 if (scan_info->default_scan_ies) {
3949 qdf_mem_free(scan_info->default_scan_ies);
3950 scan_info->default_scan_ies = NULL;
3951 }
3952
3953 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
3954 if (!scan_info->default_scan_ies)
3955 return -ENOMEM;
3956
3957 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
3958 scan_info->default_scan_ies_len = ie_len;
3959 return 0;
3960}
3961
3962/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003963 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3964 * vendor command
3965 *
3966 * @wiphy: wiphy device pointer
3967 * @wdev: wireless device pointer
3968 * @data: Vendor command data buffer
3969 * @data_len: Buffer length
3970 *
3971 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3972 *
3973 * Return: Error code.
3974 */
3975static int
3976__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3977 struct wireless_dev *wdev,
3978 const void *data,
3979 int data_len)
3980{
3981 struct net_device *dev = wdev->netdev;
3982 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3983 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3984 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
3985 int ret_val = 0;
3986 u32 modulated_dtim;
3987 u16 stats_avg_factor;
3988 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303989 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07003990 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07003991 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303992 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05303993 int attr_len;
3994 int access_policy = 0;
3995 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
3996 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05303997 uint16_t scan_ie_len = 0;
3998 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303999 struct sir_set_tx_rx_aggregation_size request;
4000 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004001 uint8_t retry, delay;
4002 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304003 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304004
Jeff Johnson1f61b612016-02-12 16:28:33 -08004005 ENTER_DEV(dev);
4006
Anurag Chouhan6d760662016-02-20 16:05:43 +05304007 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004008 hdd_err("Command not allowed in FTM mode");
4009 return -EPERM;
4010 }
4011
4012 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304013 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004014 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004015
4016 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4017 data, data_len,
4018 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004019 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004020 return -EINVAL;
4021 }
4022
Krunal Sonie3531942016-04-12 17:43:53 -07004023 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4024 ftm_capab = nla_get_u32(tb[
4025 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4026 hdd_ctx->config->fine_time_meas_cap =
4027 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4028 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304029 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004030 hdd_ctx->config->fine_time_meas_cap);
4031 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
4032 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4033 hdd_ctx->config->fine_time_meas_cap);
4034 }
4035
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004036 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4037 modulated_dtim = nla_get_u32(
4038 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4039
4040 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4041 adapter->sessionId,
4042 modulated_dtim);
4043
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304044 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004045 ret_val = -EPERM;
4046 }
4047
Kapil Gupta6213c012016-09-02 19:39:09 +05304048 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4049 qpower = nla_get_u8(
4050 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4051 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4052 ret_val = -EINVAL;
4053 }
4054
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004055 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4056 stats_avg_factor = nla_get_u16(
4057 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4058 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4059 adapter->sessionId,
4060 stats_avg_factor);
4061
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304062 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004063 ret_val = -EPERM;
4064 }
4065
4066
4067 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4068 guard_time = nla_get_u32(
4069 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4070 status = sme_configure_guard_time(hdd_ctx->hHal,
4071 adapter->sessionId,
4072 guard_time);
4073
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304074 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004075 ret_val = -EPERM;
4076 }
4077
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304078 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4079 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4080 attr_len = nla_len(
4081 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4082 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4083 hdd_info("Invalid value. attr_len %d",
4084 attr_len);
4085 return -EINVAL;
4086 }
4087
4088 nla_memcpy(&vendor_ie,
4089 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4090 attr_len);
4091 vendor_ie_present = true;
4092 hdd_info("Access policy vendor ie present.attr_len %d",
4093 attr_len);
4094 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4095 &vendor_ie[0], attr_len);
4096 }
4097
4098 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4099 access_policy = (int) nla_get_u32(
4100 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4101 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4102 (access_policy >
4103 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4104 hdd_info("Invalid value. access_policy %d",
4105 access_policy);
4106 return -EINVAL;
4107 }
4108 access_policy_present = true;
4109 hdd_info("Access policy present. access_policy %d",
4110 access_policy);
4111 }
4112
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004113 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4114 retry = nla_get_u8(tb[
4115 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4116 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4117 CFG_NON_AGG_RETRY_MAX : retry;
4118 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4119 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4120 retry, PDEV_CMD);
4121 }
4122
4123 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4124 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4125 retry = retry > CFG_AGG_RETRY_MAX ?
4126 CFG_AGG_RETRY_MAX : retry;
4127
4128 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4129 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4130 CFG_AGG_RETRY_MIN : retry;
4131 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4132 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4133 retry, PDEV_CMD);
4134 }
4135
4136 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4137 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4138 retry = retry > CFG_MGMT_RETRY_MAX ?
4139 CFG_MGMT_RETRY_MAX : retry;
4140 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4141 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4142 retry, PDEV_CMD);
4143 }
4144
4145 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4146 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4147 retry = retry > CFG_CTRL_RETRY_MAX ?
4148 CFG_CTRL_RETRY_MAX : retry;
4149 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4150 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4151 retry, PDEV_CMD);
4152 }
4153
4154 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4155 delay = nla_get_u8(tb[
4156 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4157 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4158 CFG_PROPAGATION_DELAY_MAX : delay;
4159 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4160 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4161 delay, PDEV_CMD);
4162 }
4163
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304164 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4165 tx_fail_count = nla_get_u32(
4166 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4167 if (tx_fail_count) {
4168 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4169 adapter->sessionId, tx_fail_count);
4170 if (QDF_STATUS_SUCCESS != status) {
4171 hdd_info("sme_update_tx_fail_cnt_threshold (err=%d)",
4172 status);
4173 return -EINVAL;
4174 }
4175 }
4176 }
4177
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304178 if (vendor_ie_present && access_policy_present) {
4179 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4180 access_policy =
4181 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304182 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304183 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304184 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304185
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304186 hdd_info("calling sme_update_access_policy_vendor_ie");
4187 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4188 adapter->sessionId, &vendor_ie[0],
4189 access_policy);
4190 if (QDF_STATUS_SUCCESS != status) {
4191 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304192 return -EINVAL;
4193 }
4194 }
4195
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304196 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4197 set_value = nla_get_u8(
4198 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4199 hdd_info("set_value: %d", set_value);
4200 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4201 }
4202
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304203 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4204 scan_ie_len = nla_len(
4205 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4206 hdd_info("Received default scan IE of len %d session %d device mode %d",
4207 scan_ie_len, adapter->sessionId,
4208 adapter->device_mode);
4209 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4210 scan_ie = (uint8_t *) nla_data(tb
4211 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304212
4213 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4214 scan_ie_len))
4215 hdd_err("Failed to save default scan IEs");
4216
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304217 if (adapter->device_mode == QDF_STA_MODE) {
4218 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4219 adapter->sessionId, scan_ie,
4220 scan_ie_len);
4221 if (QDF_STATUS_SUCCESS != status)
4222 ret_val = -EPERM;
4223 }
4224 } else
4225 ret_val = -EPERM;
4226 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304227
4228 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4229 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4230 /* if one is specified, both must be specified */
4231 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4232 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4233 hdd_err("Both TX and RX MPDU Aggregation required");
4234 return -EINVAL;
4235 }
4236
4237 request.tx_aggregation_size = nla_get_u8(
4238 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4239 request.rx_aggregation_size = nla_get_u8(
4240 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4241 request.vdev_id = adapter->sessionId;
4242
4243 if (request.tx_aggregation_size >=
4244 CFG_TX_AGGREGATION_SIZE_MIN &&
4245 request.tx_aggregation_size <=
4246 CFG_TX_AGGREGATION_SIZE_MAX &&
4247 request.rx_aggregation_size >=
4248 CFG_RX_AGGREGATION_SIZE_MIN &&
4249 request.rx_aggregation_size <=
4250 CFG_RX_AGGREGATION_SIZE_MAX) {
4251 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4252 if (qdf_status != QDF_STATUS_SUCCESS) {
4253 hdd_err("failed to set aggr sizes err %d",
4254 qdf_status);
4255 ret_val = -EPERM;
4256 }
4257 } else {
4258 hdd_err("TX %d RX %d MPDU aggr size not in range",
4259 request.tx_aggregation_size,
4260 request.rx_aggregation_size);
4261 ret_val = -EINVAL;
4262 }
4263 }
4264
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304265 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4266 uint8_t ignore_assoc_disallowed;
4267
4268 ignore_assoc_disallowed
4269 = nla_get_u8(tb[
4270 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4271 hdd_info("Set ignore_assoc_disallowed value - %d",
4272 ignore_assoc_disallowed);
4273 if ((ignore_assoc_disallowed <
4274 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4275 (ignore_assoc_disallowed >
4276 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4277 return -EPERM;
4278
4279 sme_update_session_param(hdd_ctx->hHal,
4280 adapter->sessionId,
4281 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4282 ignore_assoc_disallowed);
4283 }
4284
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004285 return ret_val;
4286}
4287
4288/**
4289 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4290 * vendor command
4291 *
4292 * @wiphy: wiphy device pointer
4293 * @wdev: wireless device pointer
4294 * @data: Vendor command data buffer
4295 * @data_len: Buffer length
4296 *
4297 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4298 *
4299 * Return: EOK or other error codes.
4300 */
4301static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4302 struct wireless_dev *wdev,
4303 const void *data,
4304 int data_len)
4305{
4306 int ret;
4307
4308 cds_ssr_protect(__func__);
4309 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4310 data, data_len);
4311 cds_ssr_unprotect(__func__);
4312
4313 return ret;
4314}
4315
4316static const struct
4317nla_policy
4318qca_wlan_vendor_wifi_logger_start_policy
4319[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4320 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4321 = {.type = NLA_U32 },
4322 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4323 = {.type = NLA_U32 },
4324 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4325 = {.type = NLA_U32 },
4326};
4327
4328/**
4329 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4330 * or disable the collection of packet statistics from the firmware
4331 * @wiphy: WIPHY structure pointer
4332 * @wdev: Wireless device structure pointer
4333 * @data: Pointer to the data received
4334 * @data_len: Length of the data received
4335 *
4336 * This function enables or disables the collection of packet statistics from
4337 * the firmware
4338 *
4339 * Return: 0 on success and errno on failure
4340 */
4341static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4342 struct wireless_dev *wdev,
4343 const void *data,
4344 int data_len)
4345{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304346 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004347 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4348 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4349 struct sir_wifi_start_log start_log;
4350
Jeff Johnson1f61b612016-02-12 16:28:33 -08004351 ENTER_DEV(wdev->netdev);
4352
Anurag Chouhan6d760662016-02-20 16:05:43 +05304353 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004354 hdd_err("Command not allowed in FTM mode");
4355 return -EPERM;
4356 }
4357
4358 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304359 if (status)
4360 return status;
4361
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004362
4363 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4364 data, data_len,
4365 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004366 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004367 return -EINVAL;
4368 }
4369
4370 /* Parse and fetch ring id */
4371 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004372 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004373 return -EINVAL;
4374 }
4375 start_log.ring_id = nla_get_u32(
4376 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004377 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004378
4379 /* Parse and fetch verbose level */
4380 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004381 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004382 return -EINVAL;
4383 }
4384 start_log.verbose_level = nla_get_u32(
4385 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004386 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004387
4388 /* Parse and fetch flag */
4389 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004390 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004391 return -EINVAL;
4392 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304393 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004394 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304395 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004396
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304397 /* size is buff size which can be set using iwpriv command*/
4398 start_log.size = 0;
4399
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004400 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4401
4402 if (start_log.ring_id == RING_ID_WAKELOCK) {
4403 /* Start/stop wakelock events */
4404 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4405 cds_set_wakelock_logging(true);
4406 else
4407 cds_set_wakelock_logging(false);
4408 return 0;
4409 }
4410
4411 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304412 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004413 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004414 status);
4415 return -EINVAL;
4416 }
4417 return 0;
4418}
4419
4420/**
4421 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4422 * or disable the collection of packet statistics from the firmware
4423 * @wiphy: WIPHY structure pointer
4424 * @wdev: Wireless device structure pointer
4425 * @data: Pointer to the data received
4426 * @data_len: Length of the data received
4427 *
4428 * This function is used to enable or disable the collection of packet
4429 * statistics from the firmware
4430 *
4431 * Return: 0 on success and errno on failure
4432 */
4433static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4434 struct wireless_dev *wdev,
4435 const void *data,
4436 int data_len)
4437{
4438 int ret = 0;
4439
4440 cds_ssr_protect(__func__);
4441 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4442 wdev, data, data_len);
4443 cds_ssr_unprotect(__func__);
4444
4445 return ret;
4446}
4447
4448static const struct
4449nla_policy
4450qca_wlan_vendor_wifi_logger_get_ring_data_policy
4451[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4452 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4453 = {.type = NLA_U32 },
4454};
4455
4456/**
4457 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4458 * @wiphy: WIPHY structure pointer
4459 * @wdev: Wireless device structure pointer
4460 * @data: Pointer to the data received
4461 * @data_len: Length of the data received
4462 *
4463 * This function is used to flush or retrieve the per packet statistics from
4464 * the driver
4465 *
4466 * Return: 0 on success and errno on failure
4467 */
4468static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4469 struct wireless_dev *wdev,
4470 const void *data,
4471 int data_len)
4472{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304473 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004474 uint32_t ring_id;
4475 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4476 struct nlattr *tb
4477 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4478
Jeff Johnson1f61b612016-02-12 16:28:33 -08004479 ENTER_DEV(wdev->netdev);
4480
Anurag Chouhan6d760662016-02-20 16:05:43 +05304481 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004482 hdd_err("Command not allowed in FTM mode");
4483 return -EPERM;
4484 }
4485
4486 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304487 if (status)
4488 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004489
4490 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
4491 data, data_len,
4492 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004493 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004494 return -EINVAL;
4495 }
4496
4497 /* Parse and fetch ring id */
4498 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004499 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004500 return -EINVAL;
4501 }
4502
4503 ring_id = nla_get_u32(
4504 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
4505
4506 if (ring_id == RING_ID_PER_PACKET_STATS) {
4507 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07004508 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05304509 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
4510 /*
4511 * As part of DRIVER ring ID, flush both driver and fw logs.
4512 * For other Ring ID's driver doesn't have any rings to flush
4513 */
4514 hdd_notice("Bug report triggered by framework");
4515
4516 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
4517 WLAN_LOG_INDICATOR_FRAMEWORK,
4518 WLAN_LOG_REASON_CODE_UNUSED,
4519 true, false);
4520 if (QDF_STATUS_SUCCESS != status) {
4521 hdd_err("Failed to trigger bug report");
4522 return -EINVAL;
4523 }
4524 } else {
4525 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
4526 WLAN_LOG_INDICATOR_FRAMEWORK,
4527 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004528 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004529 return 0;
4530}
4531
4532/**
4533 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
4534 * @wiphy: WIPHY structure pointer
4535 * @wdev: Wireless device structure pointer
4536 * @data: Pointer to the data received
4537 * @data_len: Length of the data received
4538 *
4539 * This function is used to flush or retrieve the per packet statistics from
4540 * the driver
4541 *
4542 * Return: 0 on success and errno on failure
4543 */
4544static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4545 struct wireless_dev *wdev,
4546 const void *data,
4547 int data_len)
4548{
4549 int ret = 0;
4550
4551 cds_ssr_protect(__func__);
4552 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
4553 wdev, data, data_len);
4554 cds_ssr_unprotect(__func__);
4555
4556 return ret;
4557}
4558
4559#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4560/**
4561 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
4562 * @hdd_ctx: HDD context
4563 * @request_id: [input] request id
4564 * @pattern_id: [output] pattern id
4565 *
4566 * This function loops through request id to pattern id array
4567 * if the slot is available, store the request id and return pattern id
4568 * if entry exists, return the pattern id
4569 *
4570 * Return: 0 on success and errno on failure
4571 */
4572static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4573 uint32_t request_id,
4574 uint8_t *pattern_id)
4575{
4576 uint32_t i;
4577
4578 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4579 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4580 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
4581 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
4582 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4583 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4584 return 0;
4585 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
4586 request_id) {
4587 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4588 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4589 return 0;
4590 }
4591 }
4592 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4593 return -EINVAL;
4594}
4595
4596/**
4597 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
4598 * @hdd_ctx: HDD context
4599 * @request_id: [input] request id
4600 * @pattern_id: [output] pattern id
4601 *
4602 * This function loops through request id to pattern id array
4603 * reset request id to 0 (slot available again) and
4604 * return pattern id
4605 *
4606 * Return: 0 on success and errno on failure
4607 */
4608static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4609 uint32_t request_id,
4610 uint8_t *pattern_id)
4611{
4612 uint32_t i;
4613
4614 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4615 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4616 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
4617 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4618 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4619 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4620 return 0;
4621 }
4622 }
4623 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4624 return -EINVAL;
4625}
4626
4627
4628/*
4629 * define short names for the global vendor params
4630 * used by __wlan_hdd_cfg80211_offloaded_packets()
4631 */
4632#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
4633#define PARAM_REQUEST_ID \
4634 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
4635#define PARAM_CONTROL \
4636 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
4637#define PARAM_IP_PACKET \
4638 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
4639#define PARAM_SRC_MAC_ADDR \
4640 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
4641#define PARAM_DST_MAC_ADDR \
4642 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
4643#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
4644
4645/**
4646 * wlan_hdd_add_tx_ptrn() - add tx pattern
4647 * @adapter: adapter pointer
4648 * @hdd_ctx: hdd context
4649 * @tb: nl attributes
4650 *
4651 * This function reads the NL attributes and forms a AddTxPtrn message
4652 * posts it to SME.
4653 *
4654 */
4655static int
4656wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4657 struct nlattr **tb)
4658{
4659 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304660 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004661 uint32_t request_id, ret, len;
4662 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304663 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004664 uint16_t eth_type = htons(ETH_P_IP);
4665
4666 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004667 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004668 return -ENOTSUPP;
4669 }
4670
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304671 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004672 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004673 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004674 return -ENOMEM;
4675 }
4676
4677 /* Parse and fetch request Id */
4678 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004679 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004680 goto fail;
4681 }
4682
4683 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4684 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004685 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004686 return -EINVAL;
4687 }
Jeff Johnson77848112016-06-29 14:52:06 -07004688 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004689
4690 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004691 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004692 goto fail;
4693 }
4694 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07004695 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004696 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07004697 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004698 goto fail;
4699 }
4700
4701 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004702 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004703 goto fail;
4704 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08004705 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05304706 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004707 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004708 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004709
Anurag Chouhanc5548422016-02-24 18:33:27 +05304710 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004711 &adapter->macAddressCurrent)) {
4712 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004713 goto fail;
4714 }
4715
4716 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004717 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004718 goto fail;
4719 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05304720 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004721 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004722 MAC_ADDR_ARRAY(dst_addr.bytes));
4723
4724 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004725 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004726 goto fail;
4727 }
4728 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07004729 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004730
4731 if (add_req->ucPtrnSize < 0 ||
4732 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
4733 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004734 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004735 add_req->ucPtrnSize);
4736 goto fail;
4737 }
4738
4739 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304740 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05304741 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304742 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304743 QDF_MAC_ADDR_SIZE);
4744 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304745 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004746 len += 2;
4747
4748 /*
4749 * This is the IP packet, add 14 bytes Ethernet (802.3) header
4750 * ------------------------------------------------------------
4751 * | 14 bytes Ethernet (802.3) header | IP header and payload |
4752 * ------------------------------------------------------------
4753 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304754 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004755 nla_data(tb[PARAM_IP_PACKET]),
4756 add_req->ucPtrnSize);
4757 add_req->ucPtrnSize += len;
4758
4759 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4760 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004761 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004762 goto fail;
4763 }
4764 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004765 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004766
4767 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304768 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004769 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004770 goto fail;
4771 }
4772
4773 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304774 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004775 return 0;
4776
4777fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304778 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004779 return -EINVAL;
4780}
4781
4782/**
4783 * wlan_hdd_del_tx_ptrn() - delete tx pattern
4784 * @adapter: adapter pointer
4785 * @hdd_ctx: hdd context
4786 * @tb: nl attributes
4787 *
4788 * This function reads the NL attributes and forms a DelTxPtrn message
4789 * posts it to SME.
4790 *
4791 */
4792static int
4793wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4794 struct nlattr **tb)
4795{
4796 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304797 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004798 uint32_t request_id, ret;
4799 uint8_t pattern_id = 0;
4800
4801 /* Parse and fetch request Id */
4802 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004803 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004804 return -EINVAL;
4805 }
4806 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4807 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004808 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004809 return -EINVAL;
4810 }
4811
4812 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4813 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004814 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004815 return -EINVAL;
4816 }
4817
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304818 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004819 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004820 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004821 return -ENOMEM;
4822 }
4823
Anurag Chouhanc5548422016-02-24 18:33:27 +05304824 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004825 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004826 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004827 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004828 request_id, del_req->ucPtrnId);
4829
4830 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304831 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004832 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004833 goto fail;
4834 }
4835
4836 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304837 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004838 return 0;
4839
4840fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304841 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004842 return -EINVAL;
4843}
4844
4845
4846/**
4847 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
4848 * @wiphy: Pointer to wireless phy
4849 * @wdev: Pointer to wireless device
4850 * @data: Pointer to data
4851 * @data_len: Data length
4852 *
4853 * Return: 0 on success, negative errno on failure
4854 */
4855static int
4856__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4857 struct wireless_dev *wdev,
4858 const void *data,
4859 int data_len)
4860{
4861 struct net_device *dev = wdev->netdev;
4862 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4863 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4864 struct nlattr *tb[PARAM_MAX + 1];
4865 uint8_t control;
4866 int ret;
4867 static const struct nla_policy policy[PARAM_MAX + 1] = {
4868 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4869 [PARAM_CONTROL] = { .type = NLA_U32 },
4870 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304871 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004872 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304873 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004874 [PARAM_PERIOD] = { .type = NLA_U32 },
4875 };
4876
Jeff Johnson1f61b612016-02-12 16:28:33 -08004877 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004878
Anurag Chouhan6d760662016-02-20 16:05:43 +05304879 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004880 hdd_err("Command not allowed in FTM mode");
4881 return -EPERM;
4882 }
4883
4884 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304885 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004886 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004887
4888 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004889 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004890 return -ENOTSUPP;
4891 }
4892
4893 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004894 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004895 return -EINVAL;
4896 }
4897
4898 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004899 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004900 return -EINVAL;
4901 }
4902 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07004903 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004904
4905 if (control == WLAN_START_OFFLOADED_PACKETS)
4906 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
4907 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
4908 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
4909 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004910 hdd_err("Invalid control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004911 return -EINVAL;
4912 }
4913}
4914
4915/*
4916 * done with short names for the global vendor params
4917 * used by __wlan_hdd_cfg80211_offloaded_packets()
4918 */
4919#undef PARAM_MAX
4920#undef PARAM_REQUEST_ID
4921#undef PARAM_CONTROL
4922#undef PARAM_IP_PACKET
4923#undef PARAM_SRC_MAC_ADDR
4924#undef PARAM_DST_MAC_ADDR
4925#undef PARAM_PERIOD
4926
4927/**
4928 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
4929 * @wiphy: wiphy structure pointer
4930 * @wdev: Wireless device structure pointer
4931 * @data: Pointer to the data received
4932 * @data_len: Length of @data
4933 *
4934 * Return: 0 on success; errno on failure
4935 */
4936static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4937 struct wireless_dev *wdev,
4938 const void *data,
4939 int data_len)
4940{
4941 int ret = 0;
4942
4943 cds_ssr_protect(__func__);
4944 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
4945 wdev, data, data_len);
4946 cds_ssr_unprotect(__func__);
4947
4948 return ret;
4949}
4950#endif
4951
4952/*
4953 * define short names for the global vendor params
4954 * used by __wlan_hdd_cfg80211_monitor_rssi()
4955 */
4956#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
4957#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
4958#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
4959#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
4960#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
4961
4962/**
4963 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
4964 * @wiphy: Pointer to wireless phy
4965 * @wdev: Pointer to wireless device
4966 * @data: Pointer to data
4967 * @data_len: Data length
4968 *
4969 * Return: 0 on success, negative errno on failure
4970 */
4971static int
4972__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
4973 struct wireless_dev *wdev,
4974 const void *data,
4975 int data_len)
4976{
4977 struct net_device *dev = wdev->netdev;
4978 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4979 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4980 struct nlattr *tb[PARAM_MAX + 1];
4981 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304982 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004983 int ret;
4984 uint32_t control;
4985 static const struct nla_policy policy[PARAM_MAX + 1] = {
4986 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4987 [PARAM_CONTROL] = { .type = NLA_U32 },
4988 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
4989 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
4990 };
4991
Jeff Johnson1f61b612016-02-12 16:28:33 -08004992 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004993
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05304994 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
4995 hdd_err("invalid session id: %d", adapter->sessionId);
4996 return -EINVAL;
4997 }
4998
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004999 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305000 if (ret)
5001 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005002
5003 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005004 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005005 return -ENOTSUPP;
5006 }
5007
5008 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005009 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005010 return -EINVAL;
5011 }
5012
5013 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005014 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005015 return -EINVAL;
5016 }
5017
5018 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005019 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005020 return -EINVAL;
5021 }
5022
5023 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5024 req.session_id = adapter->sessionId;
5025 control = nla_get_u32(tb[PARAM_CONTROL]);
5026
5027 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5028 req.control = true;
5029 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005030 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005031 return -EINVAL;
5032 }
5033
5034 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005035 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005036 return -EINVAL;
5037 }
5038
5039 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5040 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5041
5042 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005043 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005044 req.min_rssi, req.max_rssi);
5045 return -EINVAL;
5046 }
Jeff Johnson77848112016-06-29 14:52:06 -07005047 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005048 req.min_rssi, req.max_rssi);
5049
5050 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5051 req.control = false;
5052 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005053 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005054 return -EINVAL;
5055 }
Jeff Johnson77848112016-06-29 14:52:06 -07005056 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005057 req.request_id, req.session_id, req.control);
5058
5059 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305060 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005061 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005062 return -EINVAL;
5063 }
5064
5065 return 0;
5066}
5067
5068/*
5069 * done with short names for the global vendor params
5070 * used by __wlan_hdd_cfg80211_monitor_rssi()
5071 */
5072#undef PARAM_MAX
5073#undef PARAM_CONTROL
5074#undef PARAM_REQUEST_ID
5075#undef PARAM_MAX_RSSI
5076#undef PARAM_MIN_RSSI
5077
5078/**
5079 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5080 * @wiphy: wiphy structure pointer
5081 * @wdev: Wireless device structure pointer
5082 * @data: Pointer to the data received
5083 * @data_len: Length of @data
5084 *
5085 * Return: 0 on success; errno on failure
5086 */
5087static int
5088wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5089 const void *data, int data_len)
5090{
5091 int ret;
5092
5093 cds_ssr_protect(__func__);
5094 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5095 cds_ssr_unprotect(__func__);
5096
5097 return ret;
5098}
5099
5100/**
5101 * hdd_rssi_threshold_breached() - rssi breached NL event
5102 * @hddctx: HDD context
5103 * @data: rssi breached event data
5104 *
5105 * This function reads the rssi breached event %data and fill in the skb with
5106 * NL attributes and send up the NL event.
5107 *
5108 * Return: none
5109 */
5110void hdd_rssi_threshold_breached(void *hddctx,
5111 struct rssi_breach_event *data)
5112{
5113 hdd_context_t *hdd_ctx = hddctx;
5114 struct sk_buff *skb;
5115
5116 ENTER();
5117
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305118 if (wlan_hdd_validate_context(hdd_ctx))
5119 return;
5120 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005121 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005122 return;
5123 }
5124
5125 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5126 NULL,
5127 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5128 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5129 GFP_KERNEL);
5130
5131 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005132 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005133 return;
5134 }
5135
Jeff Johnson77848112016-06-29 14:52:06 -07005136 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005137 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005138 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005139 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5140
5141 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5142 data->request_id) ||
5143 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5144 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5145 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5146 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005147 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005148 goto fail;
5149 }
5150
5151 cfg80211_vendor_event(skb, GFP_KERNEL);
5152 return;
5153
5154fail:
5155 kfree_skb(skb);
5156 return;
5157}
5158
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305159static const struct nla_policy
5160ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5161 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5162};
5163
5164/**
5165 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5166 * @wiphy: Pointer to wireless phy
5167 * @wdev: Pointer to wireless device
5168 * @data: Pointer to data
5169 * @data_len: Length of @data
5170 *
5171 * Return: 0 on success, negative errno on failure
5172 */
5173static int
5174__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5175 struct wireless_dev *wdev,
5176 const void *data, int data_len)
5177{
5178 int status;
5179 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5180 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005181 struct net_device *dev = wdev->netdev;
5182 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305183
5184 ENTER_DEV(wdev->netdev);
5185
5186 status = wlan_hdd_validate_context(pHddCtx);
5187 if (0 != status)
5188 return status;
5189 if (!pHddCtx->config->fhostNSOffload) {
5190 hdd_err("ND Offload not supported");
5191 return -EINVAL;
5192 }
5193
5194 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5195 (struct nlattr *)data,
5196 data_len, ns_offload_set_policy)) {
5197 hdd_err("nla_parse failed");
5198 return -EINVAL;
5199 }
5200
5201 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5202 hdd_err("ND Offload flag attribute not present");
5203 return -EINVAL;
5204 }
5205
5206 pHddCtx->ns_offload_enable =
5207 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5208
Dustin Brownd8279d22016-09-07 14:52:57 -07005209 /* update ns offload in case it is already enabled/disabled */
5210 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
5211
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305212 return 0;
5213}
5214
5215/**
5216 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5217 * @wiphy: pointer to wireless wiphy structure.
5218 * @wdev: pointer to wireless_dev structure.
5219 * @data: Pointer to the data to be passed via vendor interface
5220 * @data_len:Length of the data to be passed
5221 *
5222 * Return: Return the Success or Failure code.
5223 */
5224static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5225 struct wireless_dev *wdev,
5226 const void *data, int data_len)
5227{
5228 int ret;
5229
5230 cds_ssr_protect(__func__);
5231 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5232 cds_ssr_unprotect(__func__);
5233
5234 return ret;
5235}
5236
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005237/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5238 * @wiphy: Pointer to wireless phy
5239 * @wdev: Pointer to wireless device
5240 * @data: Pointer to data
5241 * @data_len: Data length
5242 *
5243 * This function return the preferred frequency list generated by the policy
5244 * manager.
5245 *
5246 * Return: success or failure code
5247 */
5248static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5249 struct wireless_dev
5250 *wdev, const void *data,
5251 int data_len)
5252{
5253 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5254 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305255 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305256 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005257 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305258 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005259 enum cds_con_mode intf_mode;
5260 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5261 struct sk_buff *reply_skb;
5262
Jeff Johnson1f61b612016-02-12 16:28:33 -08005263 ENTER_DEV(wdev->netdev);
5264
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005265 ret = wlan_hdd_validate_context(hdd_ctx);
5266 if (ret)
5267 return -EINVAL;
5268
5269 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5270 data, data_len, NULL)) {
5271 hdd_err("Invalid ATTR");
5272 return -EINVAL;
5273 }
5274
5275 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5276 hdd_err("attr interface type failed");
5277 return -EINVAL;
5278 }
5279
5280 intf_mode = nla_get_u32(tb
5281 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5282
5283 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5284 hdd_err("Invalid interface type");
5285 return -EINVAL;
5286 }
5287
5288 hdd_debug("Userspace requested pref freq list");
5289
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305290 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5291 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305292 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005293 hdd_err("Get pcl failed");
5294 return -EINVAL;
5295 }
5296
5297 /* convert channel number to frequency */
5298 for (i = 0; i < pcl_len; i++) {
5299 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5300 freq_list[i] =
5301 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005302 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005303 else
5304 freq_list[i] =
5305 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005306 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005307 }
5308
5309 /* send the freq_list back to supplicant */
5310 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5311 sizeof(u32) *
5312 pcl_len +
5313 NLMSG_HDRLEN);
5314
5315 if (!reply_skb) {
5316 hdd_err("Allocate reply_skb failed");
5317 return -EINVAL;
5318 }
5319
5320 if (nla_put_u32(reply_skb,
5321 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5322 intf_mode) ||
5323 nla_put(reply_skb,
5324 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5325 sizeof(uint32_t) * pcl_len,
5326 freq_list)) {
5327 hdd_err("nla put fail");
5328 kfree_skb(reply_skb);
5329 return -EINVAL;
5330 }
5331
5332 return cfg80211_vendor_cmd_reply(reply_skb);
5333}
5334
5335/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5336 * @wiphy: Pointer to wireless phy
5337 * @wdev: Pointer to wireless device
5338 * @data: Pointer to data
5339 * @data_len: Data length
5340 *
5341 * This function return the preferred frequency list generated by the policy
5342 * manager.
5343 *
5344 * Return: success or failure code
5345 */
5346static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5347 struct wireless_dev
5348 *wdev, const void *data,
5349 int data_len)
5350{
5351 int ret = 0;
5352
5353 cds_ssr_protect(__func__);
5354 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5355 data, data_len);
5356 cds_ssr_unprotect(__func__);
5357
5358 return ret;
5359}
5360
5361/**
5362 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5363 * @wiphy: Pointer to wireless phy
5364 * @wdev: Pointer to wireless device
5365 * @data: Pointer to data
5366 * @data_len: Data length
5367 *
5368 * Return: 0 on success, negative errno on failure
5369 */
5370static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5371 struct wireless_dev *wdev,
5372 const void *data,
5373 int data_len)
5374{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305375 struct net_device *ndev = wdev->netdev;
5376 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005377 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5378 int ret = 0;
5379 enum cds_con_mode intf_mode;
5380 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5381 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005382
Jeff Johnson1f61b612016-02-12 16:28:33 -08005383 ENTER_DEV(ndev);
5384
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005385 ret = wlan_hdd_validate_context(hdd_ctx);
5386 if (ret)
5387 return ret;
5388
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005389 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5390 data, data_len, NULL)) {
5391 hdd_err("Invalid ATTR");
5392 return -EINVAL;
5393 }
5394
5395 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5396 hdd_err("attr interface type failed");
5397 return -EINVAL;
5398 }
5399
5400 intf_mode = nla_get_u32(tb
5401 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5402
5403 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5404 hdd_err("Invalid interface type");
5405 return -EINVAL;
5406 }
5407
5408 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5409 hdd_err("attr probable freq failed");
5410 return -EINVAL;
5411 }
5412
5413 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5414 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5415
5416 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005417 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005418 channel_hint, HW_MODE_20_MHZ)) {
5419 hdd_err("Set channel hint failed due to concurrency check");
5420 return -EINVAL;
5421 }
5422
Krunal Soni09e55032016-06-07 10:06:55 -07005423 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5424 hdd_warn("Remain On Channel Pending");
5425
Krunal Soni3091bcc2016-06-23 12:28:21 -07005426 ret = qdf_reset_connection_update();
5427 if (!QDF_IS_STATUS_SUCCESS(ret))
5428 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005429
Krunal Soni3091bcc2016-06-23 12:28:21 -07005430 ret = cds_current_connections_update(adapter->sessionId,
5431 channel_hint,
5432 SIR_UPDATE_REASON_SET_OPER_CHAN);
5433 if (QDF_STATUS_E_FAILURE == ret) {
5434 /* return in the failure case */
5435 hdd_err("ERROR: connections update failed!!");
5436 return -EINVAL;
5437 }
5438
5439 if (QDF_STATUS_SUCCESS == ret) {
5440 /*
5441 * Success is the only case for which we expect hw mode
5442 * change to take place, hence we need to wait.
5443 * For any other return value it should be a pass
5444 * through
5445 */
5446 ret = qdf_wait_for_connection_update();
5447 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5448 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005449 return -EINVAL;
5450 }
5451
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005452 }
5453
5454 return 0;
5455}
5456
5457/**
5458 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5459 * @wiphy: Pointer to wireless phy
5460 * @wdev: Pointer to wireless device
5461 * @data: Pointer to data
5462 * @data_len: Data length
5463 *
5464 * Return: 0 on success, negative errno on failure
5465 */
5466static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5467 struct wireless_dev *wdev,
5468 const void *data,
5469 int data_len)
5470{
5471 int ret = 0;
5472
5473 cds_ssr_protect(__func__);
5474 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5475 data, data_len);
5476 cds_ssr_unprotect(__func__);
5477
5478 return ret;
5479}
5480
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305481static const struct
5482nla_policy
5483qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5484 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5485};
5486
5487/**
5488 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
5489 * @wiphy: WIPHY structure pointer
5490 * @wdev: Wireless device structure pointer
5491 * @data: Pointer to the data received
5492 * @data_len: Length of the data received
5493 *
5494 * This function is used to get link properties like nss, rate flags and
5495 * operating frequency for the active connection with the given peer.
5496 *
5497 * Return: 0 on success and errno on failure
5498 */
5499static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5500 struct wireless_dev *wdev,
5501 const void *data,
5502 int data_len)
5503{
5504 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5505 struct net_device *dev = wdev->netdev;
5506 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5507 hdd_station_ctx_t *hdd_sta_ctx;
5508 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05305509 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305510 uint32_t sta_id;
5511 struct sk_buff *reply_skb;
5512 uint32_t rate_flags = 0;
5513 uint8_t nss;
5514 uint8_t final_rate_flags = 0;
5515 uint32_t freq;
5516
Jeff Johnson1f61b612016-02-12 16:28:33 -08005517 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305518
Anurag Chouhan6d760662016-02-20 16:05:43 +05305519 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305520 hdd_err("Command not allowed in FTM mode");
5521 return -EPERM;
5522 }
5523
5524 if (0 != wlan_hdd_validate_context(hdd_ctx))
5525 return -EINVAL;
5526
5527 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
5528 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005529 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305530 return -EINVAL;
5531 }
5532
5533 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005534 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305535 adapter->device_mode);
5536 return -EINVAL;
5537 }
5538
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305539 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05305540 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005541 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305542 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
5543
Krunal Sonib4326f22016-03-10 13:05:51 -08005544 if (adapter->device_mode == QDF_STA_MODE ||
5545 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305546 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
5547 if ((hdd_sta_ctx->conn_info.connState !=
5548 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305549 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305550 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005551 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305552 MAC_ADDR_ARRAY(peer_mac));
5553 return -EINVAL;
5554 }
5555
5556 nss = hdd_sta_ctx->conn_info.nss;
5557 freq = cds_chan_to_freq(
5558 hdd_sta_ctx->conn_info.operationChannel);
5559 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08005560 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
5561 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305562
5563 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
5564 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05305565 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305566 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305567 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305568 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305569 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305570 break;
5571 }
5572
5573 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07005574 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305575 MAC_ADDR_ARRAY(peer_mac));
5576 return -EINVAL;
5577 }
5578
5579 nss = adapter->aStaInfo[sta_id].nss;
5580 freq = cds_chan_to_freq(
5581 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
5582 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
5583 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07005584 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305585 MAC_ADDR_ARRAY(peer_mac));
5586 return -EINVAL;
5587 }
5588
5589 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
5590 if (rate_flags & eHAL_TX_RATE_VHT80) {
5591 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005592#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305593 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005594#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305595 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
5596 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005597#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305598 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005599#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305600 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
5601 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
5602 } else if (rate_flags &
5603 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
5604 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005605#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305606 if (rate_flags & eHAL_TX_RATE_HT40)
5607 final_rate_flags |=
5608 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005609#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305610 }
5611
5612 if (rate_flags & eHAL_TX_RATE_SGI) {
5613 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
5614 final_rate_flags |= RATE_INFO_FLAGS_MCS;
5615 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
5616 }
5617 }
5618
5619 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5620 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
5621
5622 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005623 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305624 return -EINVAL;
5625 }
5626
5627 if (nla_put_u8(reply_skb,
5628 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
5629 nss) ||
5630 nla_put_u8(reply_skb,
5631 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
5632 final_rate_flags) ||
5633 nla_put_u32(reply_skb,
5634 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
5635 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005636 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305637 kfree_skb(reply_skb);
5638 return -EINVAL;
5639 }
5640
5641 return cfg80211_vendor_cmd_reply(reply_skb);
5642}
5643
5644/**
5645 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
5646 * properties.
5647 * @wiphy: WIPHY structure pointer
5648 * @wdev: Wireless device structure pointer
5649 * @data: Pointer to the data received
5650 * @data_len: Length of the data received
5651 *
5652 * This function is used to get link properties like nss, rate flags and
5653 * operating frequency for the active connection with the given peer.
5654 *
5655 * Return: 0 on success and errno on failure
5656 */
5657static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5658 struct wireless_dev *wdev,
5659 const void *data,
5660 int data_len)
5661{
5662 int ret = 0;
5663
5664 cds_ssr_protect(__func__);
5665 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
5666 wdev, data, data_len);
5667 cds_ssr_unprotect(__func__);
5668
5669 return ret;
5670}
5671
Peng Xu278d0122015-09-24 16:34:17 -07005672static const struct
5673nla_policy
5674qca_wlan_vendor_ota_test_policy
5675[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
5676 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
5677};
5678
5679/**
5680 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
5681 * @wiphy: Pointer to wireless phy
5682 * @wdev: Pointer to wireless device
5683 * @data: Pointer to data
5684 * @data_len: Data length
5685 *
5686 * Return: 0 on success, negative errno on failure
5687 */
5688static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5689 struct wireless_dev *wdev,
5690 const void *data,
5691 int data_len)
5692{
5693 struct net_device *dev = wdev->netdev;
5694 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5695 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
5696 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5697 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
5698 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305699 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07005700 uint32_t current_roam_state;
5701
Jeff Johnson1f61b612016-02-12 16:28:33 -08005702 ENTER_DEV(dev);
5703
Anurag Chouhan6d760662016-02-20 16:05:43 +05305704 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07005705 hdd_err("Command not allowed in FTM mode");
5706 return -EPERM;
5707 }
5708
5709 if (0 != wlan_hdd_validate_context(hdd_ctx))
5710 return -EINVAL;
5711
5712 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
5713 data, data_len,
5714 qca_wlan_vendor_ota_test_policy)) {
5715 hdd_err("invalid attr");
5716 return -EINVAL;
5717 }
5718
5719 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
5720 hdd_err("attr ota test failed");
5721 return -EINVAL;
5722 }
5723
5724 ota_enable = nla_get_u8(
5725 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
5726
5727 hdd_info(" OTA test enable = %d", ota_enable);
5728 if (ota_enable != 1) {
5729 hdd_err("Invalid value, only enable test mode is supported!");
5730 return -EINVAL;
5731 }
5732
5733 current_roam_state =
5734 sme_get_current_roam_state(hal, adapter->sessionId);
5735 status = sme_stop_roaming(hal, adapter->sessionId,
5736 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305737 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005738 hdd_err("Enable/Disable roaming failed");
5739 return -EINVAL;
5740 }
5741
5742 status = sme_ps_enable_disable(hal, adapter->sessionId,
5743 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305744 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005745 hdd_err("Enable/Disable power save failed");
5746 /* restore previous roaming setting */
5747 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
5748 current_roam_state == eCSR_ROAMING_STATE_JOINED)
5749 status = sme_start_roaming(hal, adapter->sessionId,
5750 eCsrHddIssued);
5751 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
5752 current_roam_state == eCSR_ROAMING_STATE_IDLE)
5753 status = sme_stop_roaming(hal, adapter->sessionId,
5754 eCsrHddIssued);
5755
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305756 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07005757 hdd_err("Restoring roaming state failed");
5758
5759 return -EINVAL;
5760 }
5761
5762
5763 return 0;
5764}
5765
5766/**
5767 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
5768 * @wiphy: Pointer to wireless phy
5769 * @wdev: Pointer to wireless device
5770 * @data: Pointer to data
5771 * @data_len: Data length
5772 *
5773 * Return: 0 on success, negative errno on failure
5774 */
5775static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5776 struct wireless_dev *wdev,
5777 const void *data,
5778 int data_len)
5779{
5780 int ret = 0;
5781
5782 cds_ssr_protect(__func__);
5783 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
5784 cds_ssr_unprotect(__func__);
5785
5786 return ret;
5787}
5788
Peng Xu4d67c8f2015-10-16 16:02:26 -07005789/**
5790 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5791 * @wiphy: Pointer to wireless phy
5792 * @wdev: Pointer to wireless device
5793 * @data: Pointer to data
5794 * @data_len: Data length
5795 *
5796 * Return: 0 on success, negative errno on failure
5797 */
5798static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5799 struct wireless_dev *wdev,
5800 const void *data,
5801 int data_len)
5802{
5803 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5804 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005805 hdd_adapter_t *adapter;
5806 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005807 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
5808 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005809 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005810
Jeff Johnson1f61b612016-02-12 16:28:33 -08005811 ENTER_DEV(dev);
5812
Peng Xu4d67c8f2015-10-16 16:02:26 -07005813 ret = wlan_hdd_validate_context(hdd_ctx);
5814 if (ret)
5815 return ret;
5816
5817 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5818
5819 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
5820 data, data_len, NULL)) {
5821 hdd_err("Invalid ATTR");
5822 return -EINVAL;
5823 }
5824
5825 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
5826 hdd_err("attr tx power scale failed");
5827 return -EINVAL;
5828 }
5829
5830 scale_value = nla_get_u8(tb
5831 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
5832
5833 if (scale_value > MAX_TXPOWER_SCALE) {
5834 hdd_err("Invalid tx power scale level");
5835 return -EINVAL;
5836 }
5837
Peng Xu62c8c432016-05-09 15:23:02 -07005838 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005839
Peng Xu62c8c432016-05-09 15:23:02 -07005840 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005841 hdd_err("Set tx power scale failed");
5842 return -EINVAL;
5843 }
5844
5845 return 0;
5846}
5847
5848/**
5849 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5850 * @wiphy: Pointer to wireless phy
5851 * @wdev: Pointer to wireless device
5852 * @data: Pointer to data
5853 * @data_len: Data length
5854 *
5855 * Return: 0 on success, negative errno on failure
5856 */
5857static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5858 struct wireless_dev *wdev,
5859 const void *data,
5860 int data_len)
5861{
Peng Xu62c8c432016-05-09 15:23:02 -07005862 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005863
5864 cds_ssr_protect(__func__);
5865 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
5866 data, data_len);
5867 cds_ssr_unprotect(__func__);
5868
5869 return ret;
5870}
5871
5872/**
5873 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5874 * @wiphy: Pointer to wireless phy
5875 * @wdev: Pointer to wireless device
5876 * @data: Pointer to data
5877 * @data_len: Data length
5878 *
5879 * Return: 0 on success, negative errno on failure
5880 */
5881static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5882 struct wireless_dev *wdev,
5883 const void *data,
5884 int data_len)
5885{
5886 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5887 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005888 hdd_adapter_t *adapter;
5889 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005890 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
5891 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005892 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005893
Jeff Johnson1f61b612016-02-12 16:28:33 -08005894 ENTER_DEV(dev);
5895
Peng Xu4d67c8f2015-10-16 16:02:26 -07005896 ret = wlan_hdd_validate_context(hdd_ctx);
5897 if (ret)
5898 return ret;
5899
5900 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5901
5902 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
5903 data, data_len, NULL)) {
5904 hdd_err("Invalid ATTR");
5905 return -EINVAL;
5906 }
5907
5908 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
5909 hdd_err("attr tx power decrease db value failed");
5910 return -EINVAL;
5911 }
5912
5913 scale_value = nla_get_u8(tb
5914 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
5915
Peng Xu62c8c432016-05-09 15:23:02 -07005916 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
5917 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005918
Peng Xu62c8c432016-05-09 15:23:02 -07005919 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005920 hdd_err("Set tx power decrease db failed");
5921 return -EINVAL;
5922 }
5923
5924 return 0;
5925}
5926
5927/**
5928 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5929 * @wiphy: Pointer to wireless phy
5930 * @wdev: Pointer to wireless device
5931 * @data: Pointer to data
5932 * @data_len: Data length
5933 *
5934 * Return: 0 on success, negative errno on failure
5935 */
5936static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5937 struct wireless_dev *wdev,
5938 const void *data,
5939 int data_len)
5940{
Peng Xu62c8c432016-05-09 15:23:02 -07005941 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005942
5943 cds_ssr_protect(__func__);
5944 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
5945 data, data_len);
5946 cds_ssr_unprotect(__func__);
5947
5948 return ret;
5949}
Peng Xu8fdaa492016-06-22 10:20:47 -07005950
5951/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05305952 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
5953 * @wiphy: Pointer to wireless phy
5954 * @wdev: Pointer to wireless device
5955 * @data: Pointer to data
5956 * @data_len: Data length
5957 *
5958 * Processes the conditional channel switch request and invokes the helper
5959 * APIs to process the channel switch request.
5960 *
5961 * Return: 0 on success, negative errno on failure
5962 */
5963static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
5964 struct wireless_dev *wdev,
5965 const void *data,
5966 int data_len)
5967{
5968 int ret;
5969 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5970 struct net_device *dev = wdev->netdev;
5971 hdd_adapter_t *adapter;
5972 struct nlattr
5973 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
5974 uint32_t freq_len, i;
5975 uint32_t *freq;
5976 uint8_t chans[QDF_MAX_NUM_CHAN];
5977
5978 ENTER_DEV(dev);
5979
5980 ret = wlan_hdd_validate_context(hdd_ctx);
5981 if (ret)
5982 return ret;
5983
5984 if (!hdd_ctx->config->enableDFSMasterCap) {
5985 hdd_err("DFS master capability is not present in the driver");
5986 return -EINVAL;
5987 }
5988
5989 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5990 hdd_err("Command not allowed in FTM mode");
5991 return -EPERM;
5992 }
5993
5994 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5995 if (adapter->device_mode != QDF_SAP_MODE) {
5996 hdd_err("Invalid device mode %d", adapter->device_mode);
5997 return -EINVAL;
5998 }
5999
6000 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6001 data, data_len, NULL)) {
6002 hdd_err("Invalid ATTR");
6003 return -EINVAL;
6004 }
6005
6006 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6007 hdd_err("Frequency list is missing");
6008 return -EINVAL;
6009 }
6010
6011 freq_len = nla_len(
6012 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6013 sizeof(uint32_t);
6014
6015 if (freq_len > QDF_MAX_NUM_CHAN) {
6016 hdd_err("insufficient space to hold channels");
6017 return -ENOMEM;
6018 }
6019
6020 hdd_debug("freq_len=%d", freq_len);
6021
6022 freq = nla_data(
6023 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6024
6025
6026 for (i = 0; i < freq_len; i++) {
6027 if (freq[i] == 0)
6028 chans[i] = 0;
6029 else
6030 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6031
6032 hdd_debug("freq[%d]=%d", i, freq[i]);
6033 }
6034
6035 /*
6036 * The input frequency list from user space is designed to be a
6037 * priority based frequency list. This is only to accommodate any
6038 * future request. But, current requirement is only to perform CAC
6039 * on a single channel. So, the first entry from the list is picked.
6040 *
6041 * If channel is zero, any channel in the available outdoor regulatory
6042 * domain will be selected.
6043 */
6044 ret = wlan_hdd_request_pre_cac(chans[0]);
6045 if (ret) {
6046 hdd_err("pre cac request failed with reason:%d", ret);
6047 return ret;
6048 }
6049
6050 return 0;
6051}
6052
6053/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006054 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6055 * @wiphy: Pointer to wireless phy
6056 * @wdev: Pointer to wireless device
6057 * @data: Pointer to data
6058 * @data_len: Data length
6059 *
6060 * This function is to process the p2p listen offload start vendor
6061 * command. It parses the input parameters and invoke WMA API to
6062 * send the command to firmware.
6063 *
6064 * Return: 0 on success, negative errno on failure
6065 */
6066static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6067 struct wireless_dev *wdev,
6068 const void *data,
6069 int data_len)
6070{
6071 int ret;
6072 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6073 struct net_device *dev = wdev->netdev;
6074 hdd_adapter_t *adapter;
6075 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6076 struct sir_p2p_lo_start params;
6077 QDF_STATUS status;
6078
6079 ENTER_DEV(dev);
6080
6081 ret = wlan_hdd_validate_context(hdd_ctx);
6082 if (ret)
6083 return ret;
6084
6085 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6086 hdd_err("Command not allowed in FTM mode");
6087 return -EPERM;
6088 }
6089
6090 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6091 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6092 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6093 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6094 hdd_err("Invalid device mode %d", adapter->device_mode);
6095 return -EINVAL;
6096 }
6097
6098 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6099 data, data_len, NULL)) {
6100 hdd_err("Invalid ATTR");
6101 return -EINVAL;
6102 }
6103
6104 memset(&params, 0, sizeof(params));
6105
6106 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6107 params.ctl_flags = 1; /* set to default value */
6108 else
6109 params.ctl_flags = nla_get_u32(tb
6110 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6111
6112 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6113 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6114 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6115 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6116 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6117 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6118 hdd_err("Attribute parsing failed");
6119 return -EINVAL;
6120 }
6121
6122 params.vdev_id = adapter->sessionId;
6123 params.freq = nla_get_u32(tb
6124 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6125 if ((params.freq != 2412) && (params.freq != 2437) &&
6126 (params.freq != 2462)) {
6127 hdd_err("Invalid listening channel: %d", params.freq);
6128 return -EINVAL;
6129 }
6130
6131 params.period = nla_get_u32(tb
6132 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6133 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6134 hdd_err("Invalid period: %d", params.period);
6135 return -EINVAL;
6136 }
6137
6138 params.interval = nla_get_u32(tb
6139 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6140 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6141 hdd_err("Invalid interval: %d", params.interval);
6142 return -EINVAL;
6143 }
6144
6145 params.count = nla_get_u32(tb
6146 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
6147 if (!((params.count > 0) && (params.count < UINT_MAX))) {
6148 hdd_err("Invalid count: %d", params.count);
6149 return -EINVAL;
6150 }
6151
6152 params.device_types = nla_data(tb
6153 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6154 if (params.device_types == NULL) {
6155 hdd_err("Invalid device types");
6156 return -EINVAL;
6157 }
6158
6159 params.dev_types_len = nla_len(tb
6160 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6161 if (params.dev_types_len < 8) {
6162 hdd_err("Invalid device type length: %d", params.dev_types_len);
6163 return -EINVAL;
6164 }
6165
6166 params.probe_resp_tmplt = nla_data(tb
6167 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6168 if (params.probe_resp_tmplt == NULL) {
6169 hdd_err("Invalid probe response template");
6170 return -EINVAL;
6171 }
6172
6173 params.probe_resp_len = nla_len(tb
6174 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6175 if (params.probe_resp_len == 0) {
6176 hdd_err("Invalid probe resp template length: %d",
6177 params.probe_resp_len);
6178 return -EINVAL;
6179 }
6180
6181 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6182 params.freq, params.period, params.interval, params.count);
6183
6184 status = wma_p2p_lo_start(&params);
6185
6186 if (!QDF_IS_STATUS_SUCCESS(status)) {
6187 hdd_err("P2P LO start failed");
6188 return -EINVAL;
6189 }
6190
6191 return 0;
6192}
6193
6194
6195/**
6196 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6197 * @wiphy: Pointer to wireless phy
6198 * @wdev: Pointer to wireless device
6199 * @data: Pointer to data
6200 * @data_len: Data length
6201 *
6202 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6203 * to process p2p listen offload start vendor command.
6204 *
6205 * Return: 0 on success, negative errno on failure
6206 */
6207static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6208 struct wireless_dev *wdev,
6209 const void *data,
6210 int data_len)
6211{
6212 int ret = 0;
6213
6214 cds_ssr_protect(__func__);
6215 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6216 data, data_len);
6217 cds_ssr_unprotect(__func__);
6218
6219 return ret;
6220}
6221
6222/**
6223 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6224 * @wiphy: Pointer to wireless phy
6225 * @wdev: Pointer to wireless device
6226 * @data: Pointer to data
6227 * @data_len: Data length
6228 *
6229 * This function is to process the p2p listen offload stop vendor
6230 * command. It invokes WMA API to send command to firmware.
6231 *
6232 * Return: 0 on success, negative errno on failure
6233 */
6234static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6235 struct wireless_dev *wdev,
6236 const void *data,
6237 int data_len)
6238{
6239 QDF_STATUS status;
6240 hdd_adapter_t *adapter;
6241 struct net_device *dev = wdev->netdev;
6242
6243 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6244 hdd_err("Command not allowed in FTM mode");
6245 return -EPERM;
6246 }
6247
6248 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6249 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6250 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6251 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6252 hdd_err("Invalid device mode");
6253 return -EINVAL;
6254 }
6255
6256 status = wma_p2p_lo_stop(adapter->sessionId);
6257
6258 if (!QDF_IS_STATUS_SUCCESS(status)) {
6259 hdd_err("P2P LO stop failed");
6260 return -EINVAL;
6261 }
6262
6263 return 0;
6264}
6265
6266/**
6267 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6268 * @wiphy: Pointer to wireless phy
6269 * @wdev: Pointer to wireless device
6270 * @data: Pointer to data
6271 * @data_len: Data length
6272 *
6273 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6274 * to process p2p listen offload stop vendor command.
6275 *
6276 * Return: 0 on success, negative errno on failure
6277 */
6278static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6279 struct wireless_dev *wdev,
6280 const void *data,
6281 int data_len)
6282{
6283 int ret = 0;
6284
6285 cds_ssr_protect(__func__);
6286 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6287 data, data_len);
6288 cds_ssr_unprotect(__func__);
6289
6290 return ret;
6291}
6292
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306293/**
6294 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6295 * @wiphy: Pointer to wireless phy
6296 * @wdev: Pointer to wireless device
6297 * @data: Pointer to data
6298 * @data_len: Data length
6299 *
6300 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6301 * to process the conditional channel switch request.
6302 *
6303 * Return: 0 on success, negative errno on failure
6304 */
6305static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6306 struct wireless_dev *wdev,
6307 const void *data,
6308 int data_len)
6309{
6310 int ret;
6311
6312 cds_ssr_protect(__func__);
6313 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6314 data, data_len);
6315 cds_ssr_unprotect(__func__);
6316
6317 return ret;
6318}
6319
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306320/*
6321 * define short names for the global vendor params
6322 * used by __wlan_hdd_cfg80211_bpf_offload()
6323 */
6324#define BPF_INVALID \
6325 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6326#define BPF_SET_RESET \
6327 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6328#define BPF_VERSION \
6329 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6330#define BPF_FILTER_ID \
6331 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6332#define BPF_PACKET_SIZE \
6333 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6334#define BPF_CURRENT_OFFSET \
6335 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6336#define BPF_PROGRAM \
6337 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6338#define BPF_MAX \
6339 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006340
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306341static const struct nla_policy
6342wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6343 [BPF_SET_RESET] = {.type = NLA_U32},
6344 [BPF_VERSION] = {.type = NLA_U32},
6345 [BPF_FILTER_ID] = {.type = NLA_U32},
6346 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6347 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6348 [BPF_PROGRAM] = {.type = NLA_U8},
6349};
6350
6351/**
6352 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
6353 * @hdd_context: hdd_context
6354 * @bpf_get_offload: struct for get offload
6355 *
6356 * This function receives the response/data from the lower layer and
6357 * checks to see if the thread is still waiting then post the results to
6358 * upper layer, if the request has timed out then ignore.
6359 *
6360 * Return: None
6361 */
6362void hdd_get_bpf_offload_cb(void *hdd_context,
6363 struct sir_bpf_get_offload *data)
6364{
6365 hdd_context_t *hdd_ctx = hdd_context;
6366 struct hdd_bpf_context *context;
6367
6368 ENTER();
6369
6370 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006371 hdd_err("HDD context is invalid or data(%p) is null",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306372 data);
6373 return;
6374 }
6375
6376 spin_lock(&hdd_context_lock);
6377
6378 context = &bpf_context;
6379 /* The caller presumably timed out so there is nothing we can do */
6380 if (context->magic != BPF_CONTEXT_MAGIC) {
6381 spin_unlock(&hdd_context_lock);
6382 return;
6383 }
6384
6385 /* context is valid so caller is still waiting */
6386 /* paranoia: invalidate the magic */
6387 context->magic = 0;
6388
6389 context->capability_response = *data;
6390 complete(&context->completion);
6391
6392 spin_unlock(&hdd_context_lock);
6393
6394 return;
6395}
6396
6397/**
6398 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6399 * @hdd_context: hdd_context
6400 * @bpf_get_offload: struct for get offload
6401 *
6402 * Return: 0 on success, error number otherwise.
6403 */
6404static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6405 struct sir_bpf_get_offload *bpf_get_offload)
6406{
6407 struct sk_buff *skb;
6408 uint32_t nl_buf_len;
6409
6410 ENTER();
6411
6412 nl_buf_len = NLMSG_HDRLEN;
6413 nl_buf_len +=
6414 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6415 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6416
6417 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6418 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006419 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306420 return -ENOMEM;
6421 }
6422
Jeff Johnson77848112016-06-29 14:52:06 -07006423 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306424 bpf_get_offload->bpf_version,
6425 bpf_get_offload->max_bytes_for_bpf_inst);
6426
6427 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6428 bpf_get_offload->max_bytes_for_bpf_inst) ||
6429 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006430 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306431 goto nla_put_failure;
6432 }
6433
6434 cfg80211_vendor_cmd_reply(skb);
6435 EXIT();
6436 return 0;
6437
6438nla_put_failure:
6439 kfree_skb(skb);
6440 return -EINVAL;
6441}
6442
6443/**
6444 * hdd_get_bpf_offload - Get BPF offload Capabilities
6445 * @hdd_ctx: Hdd context
6446 *
6447 * Return: 0 on success, errno on failure
6448 */
6449static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6450{
6451 unsigned long rc;
Houston Hoffman59c097f2016-11-09 15:50:25 -08006452 static struct hdd_bpf_context *context;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306453 QDF_STATUS status;
6454 int ret;
6455
6456 ENTER();
6457
6458 spin_lock(&hdd_context_lock);
6459 context = &bpf_context;
6460 context->magic = BPF_CONTEXT_MAGIC;
6461 INIT_COMPLETION(context->completion);
6462 spin_unlock(&hdd_context_lock);
6463
6464 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal);
6465 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006466 hdd_err("Unable to retrieve BPF caps");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306467 return -EINVAL;
6468 }
6469 /* request was sent -- wait for the response */
6470 rc = wait_for_completion_timeout(&context->completion,
6471 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
6472 if (!rc) {
Jeff Johnson77848112016-06-29 14:52:06 -07006473 hdd_err("Target response timed out");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306474 spin_lock(&hdd_context_lock);
6475 context->magic = 0;
6476 spin_unlock(&hdd_context_lock);
6477
6478 return -ETIMEDOUT;
6479 }
6480 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
6481 &bpf_context.capability_response);
6482 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006483 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306484
6485 EXIT();
6486 return ret;
6487}
6488
6489/**
6490 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
6491 * @hdd_ctx: Hdd context
6492 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306493 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306494 *
6495 * Return: 0 on success; errno on failure
6496 */
6497static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
6498 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306499 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306500{
6501 struct sir_bpf_set_offload *bpf_set_offload;
6502 QDF_STATUS status;
6503 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05306504 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306505
6506 ENTER();
6507
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306508 if (adapter->device_mode == QDF_STA_MODE ||
6509 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
6510 if (!hdd_conn_is_connected(
6511 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
6512 hdd_err("Not in Connected state!");
6513 return -ENOTSUPP;
6514 }
6515 }
6516
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306517 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
6518 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07006519 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306520 return -ENOMEM;
6521 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306522
6523 /* Parse and fetch bpf packet size */
6524 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006525 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306526 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306527 goto fail;
6528 }
6529 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
6530
6531 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07006532 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306533 goto post_sme;
6534 }
6535
6536 /* Parse and fetch bpf program */
6537 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006538 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306539 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306540 goto fail;
6541 }
6542
6543 prog_len = nla_len(tb[BPF_PROGRAM]);
6544 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05306545
6546 if (bpf_set_offload->program == NULL) {
6547 hdd_err("qdf_mem_malloc failed for bpf offload program");
6548 ret = -ENOMEM;
6549 goto fail;
6550 }
6551
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306552 bpf_set_offload->current_length = prog_len;
6553 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306554 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306555
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05306556 hdd_info("BPF set instructions");
6557 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
6558 bpf_set_offload->program, prog_len);
6559
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306560 /* Parse and fetch filter Id */
6561 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006562 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306563 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306564 goto fail;
6565 }
6566 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
6567
6568 /* Parse and fetch current offset */
6569 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006570 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306571 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306572 goto fail;
6573 }
6574 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
6575
6576post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07006577 hdd_notice("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 +05306578 bpf_set_offload->session_id,
6579 bpf_set_offload->version,
6580 bpf_set_offload->filter_id,
6581 bpf_set_offload->total_length,
6582 bpf_set_offload->current_length,
6583 bpf_set_offload->current_offset);
6584
6585 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
6586 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006587 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05306588 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306589 goto fail;
6590 }
6591 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306592
6593fail:
6594 if (bpf_set_offload->current_length)
6595 qdf_mem_free(bpf_set_offload->program);
6596 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05306597 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306598}
6599
6600/**
6601 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
6602 * @wiphy: wiphy structure pointer
6603 * @wdev: Wireless device structure pointer
6604 * @data: Pointer to the data received
6605 * @data_len: Length of @data
6606 *
6607 * Return: 0 on success; errno on failure
6608 */
6609static int
6610__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6611 struct wireless_dev *wdev,
6612 const void *data, int data_len)
6613{
6614 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6615 struct net_device *dev = wdev->netdev;
6616 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6617 struct nlattr *tb[BPF_MAX + 1];
6618 int ret_val, packet_filter_subcmd;
6619
6620 ENTER();
6621
6622 ret_val = wlan_hdd_validate_context(hdd_ctx);
6623 if (ret_val)
6624 return ret_val;
6625
6626 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07006627 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306628 return -EINVAL;
6629 }
6630
6631 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07006632 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306633 return -ENOTSUPP;
6634 }
6635
6636 if (nla_parse(tb, BPF_MAX, data, data_len,
6637 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006638 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306639 return -EINVAL;
6640 }
6641
6642 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006643 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306644 return -EINVAL;
6645 }
6646
6647 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
6648
6649 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
6650 return hdd_get_bpf_offload(hdd_ctx);
6651 else
6652 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306653 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306654}
6655
6656/**
6657 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
6658 * @wiphy: wiphy structure pointer
6659 * @wdev: Wireless device structure pointer
6660 * @data: Pointer to the data received
6661 * @data_len: Length of @data
6662 *
6663 * Return: 0 on success; errno on failure
6664 */
6665
6666static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6667 struct wireless_dev *wdev,
6668 const void *data, int data_len)
6669{
6670 int ret;
6671
6672 cds_ssr_protect(__func__);
6673 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
6674 cds_ssr_unprotect(__func__);
6675
6676 return ret;
6677}
6678
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306679/**
6680 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
6681 * @pre_cac_adapter: AP adapter used for pre cac
6682 * @status: Status (true or false)
6683 * @handle: Global handle
6684 *
6685 * Sets the status of pre cac i.e., whether the pre cac is active or not
6686 *
6687 * Return: Zero on success, non-zero on failure
6688 */
6689static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
6690 bool status, tHalHandle handle)
6691{
6692 QDF_STATUS ret;
6693
6694 ret = wlan_sap_set_pre_cac_status(
6695 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
6696 if (QDF_IS_STATUS_ERROR(ret))
6697 return -EINVAL;
6698
6699 return 0;
6700}
6701
6702/**
6703 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
6704 * @ap_adapter: AP adapter
6705 * @chan_before_pre_cac: Channel
6706 *
6707 * Saves the channel which the AP was beaconing on before moving to the pre
6708 * cac channel. If radar is detected on the pre cac channel, this saved
6709 * channel will be used for AP operations.
6710 *
6711 * Return: Zero on success, non-zero on failure
6712 */
6713static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
6714 uint8_t chan_before_pre_cac)
6715{
6716 QDF_STATUS ret;
6717
6718 ret = wlan_sap_set_chan_before_pre_cac(
6719 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
6720 if (QDF_IS_STATUS_ERROR(ret))
6721 return -EINVAL;
6722
6723 return 0;
6724}
6725
6726/**
6727 * wlan_hdd_sap_get_nol() - Get SAPs NOL
6728 * @ap_adapter: AP adapter
6729 * @nol: Non-occupancy list
6730 * @nol_len: Length of NOL
6731 *
6732 * Get the NOL for SAP
6733 *
6734 * Return: Zero on success, non-zero on failure
6735 */
6736static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
6737 uint32_t *nol_len)
6738{
6739 QDF_STATUS ret;
6740
6741 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
6742 nol, nol_len);
6743 if (QDF_IS_STATUS_ERROR(ret))
6744 return -EINVAL;
6745
6746 return 0;
6747}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306748
6749/**
6750 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
6751 * @hdd_ctx: HDD context
6752 * @ap_adapter: AP adapter
6753 * @channel: Channel requested by userspace
6754 * @pre_cac_chan: Pointer to the pre CAC channel
6755 *
6756 * Validates the channel provided by userspace. If user provided channel 0,
6757 * a valid outdoor channel must be selected from the regulatory channel.
6758 *
6759 * Return: Zero on success and non zero value on error
6760 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07006761static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
6762 hdd_adapter_t *ap_adapter,
6763 uint8_t channel,
6764 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306765{
6766 uint32_t i, j;
6767 QDF_STATUS status;
6768 int ret;
6769 uint8_t nol[QDF_MAX_NUM_CHAN];
6770 uint32_t nol_len = 0, weight_len = 0;
6771 bool found;
6772 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6773 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
6774 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
6775
6776 if (0 == channel) {
6777 /* Channel is not obtained from PCL because PCL may not have
6778 * the entire channel list. For example: if SAP is up on
6779 * channel 6 and PCL is queried for the next SAP interface,
6780 * if SCC is preferred, the PCL will contain only the channel
6781 * 6. But, we are in need of a DFS channel. So, going with the
6782 * first channel from the valid channel list.
6783 */
6784 status = cds_get_valid_chans(channel_list, &len);
6785 if (QDF_IS_STATUS_ERROR(status)) {
6786 hdd_err("Failed to get channel list");
6787 return -EINVAL;
6788 }
6789 cds_update_with_safe_channel_list(channel_list, &len,
6790 pcl_weights, weight_len);
6791 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
6792 for (i = 0; i < len; i++) {
6793 found = false;
6794 for (j = 0; j < nol_len; j++) {
6795 if (channel_list[i] == nol[j]) {
6796 found = true;
6797 break;
6798 }
6799 }
6800 if (found)
6801 continue;
6802 if (CDS_IS_DFS_CH(channel_list[i])) {
6803 *pre_cac_chan = channel_list[i];
6804 break;
6805 }
6806 }
6807 if (*pre_cac_chan == 0) {
6808 hdd_err("unable to find outdoor channel");
6809 return -EINVAL;
6810 }
6811 } else {
6812 /* Only when driver selects a channel, check is done for
6813 * unnsafe and NOL channels. When user provides a fixed channel
6814 * the user is expected to take care of this.
6815 */
6816 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
6817 !CDS_IS_DFS_CH(channel)) {
6818 hdd_err("Invalid channel for pre cac:%d", channel);
6819 return -EINVAL;
6820 } else {
6821 *pre_cac_chan = channel;
6822 }
6823 }
6824 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
6825 return 0;
6826}
6827
6828/**
6829 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
6830 * @channel: Channel option provided by userspace
6831 *
6832 * Sets the driver to the required hardware mode and start an adapater for
6833 * pre CAC which will mimic an AP.
6834 *
6835 * Return: Zero on success, non-zero value on error
6836 */
6837int wlan_hdd_request_pre_cac(uint8_t channel)
6838{
Krunal Sonib37bb352016-12-20 14:12:21 -08006839 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306840 hdd_context_t *hdd_ctx;
6841 int ret;
6842 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
6843 hdd_ap_ctx_t *hdd_ap_ctx;
6844 QDF_STATUS status;
6845 struct wiphy *wiphy;
6846 struct net_device *dev;
6847 struct cfg80211_chan_def chandef;
6848 enum nl80211_channel_type channel_type;
6849 uint32_t freq;
6850 struct ieee80211_channel *chan;
6851 tHalHandle handle;
6852 bool val;
6853
6854 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
6855 if (0 != wlan_hdd_validate_context(hdd_ctx))
6856 return -EINVAL;
6857
6858 if (cds_get_connection_count() > 1) {
6859 hdd_err("pre cac not allowed in concurrency");
6860 return -EINVAL;
6861 }
6862
6863 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
6864 if (!ap_adapter) {
6865 hdd_err("unable to get SAP adapter");
6866 return -EINVAL;
6867 }
6868
6869 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
6870 if (!handle) {
6871 hdd_err("Invalid handle");
6872 return -EINVAL;
6873 }
6874
6875 val = wlan_sap_is_pre_cac_active(handle);
6876 if (val) {
6877 hdd_err("pre cac is already in progress");
6878 return -EINVAL;
6879 }
6880
6881 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6882 if (!hdd_ap_ctx) {
6883 hdd_err("SAP context is NULL");
6884 return -EINVAL;
6885 }
6886
6887 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
6888 hdd_err("SAP is already on DFS channel:%d",
6889 hdd_ap_ctx->operatingChannel);
6890 return -EINVAL;
6891 }
6892
6893 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
6894 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
6895 hdd_ap_ctx->operatingChannel);
6896 return -EINVAL;
6897 }
6898
Krunal Sonib37bb352016-12-20 14:12:21 -08006899 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
6900 if (!mac_addr) {
6901 hdd_err("can't add virtual intf: Not getting valid mac addr");
6902 return -EINVAL;
6903 }
6904
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306905 hdd_info("channel:%d", channel);
6906
6907 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
6908 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08006909 if (ret != 0) {
6910 hdd_err("can't validate pre-cac channel");
6911 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306912 }
6913
6914 hdd_debug("starting pre cac SAP adapter");
6915
6916 /* Starting a SAP adapter:
6917 * Instead of opening an adapter, we could just do a SME open session
6918 * for AP type. But, start BSS would still need an adapter.
6919 * So, this option is not taken.
6920 *
6921 * hdd open adapter is going to register this precac interface with
6922 * user space. This interface though exposed to user space will be in
6923 * DOWN state. Consideration was done to avoid this registration to the
6924 * user space. But, as part of SAP operations multiple events are sent
6925 * to user space. Some of these events received from unregistered
6926 * interface was causing crashes. So, retaining the registration.
6927 *
6928 * So, this interface would remain registered and will remain in DOWN
6929 * state for the CAC duration. We will add notes in the feature
6930 * announcement to not use this temporary interface for any activity
6931 * from user space.
6932 */
6933 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08006934 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306935 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306936 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08006937 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306938 }
6939
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306940 /*
6941 * This interface is internally created by the driver. So, no interface
6942 * up comes for this interface from user space and hence starting
6943 * the adapter internally.
6944 */
6945 if (hdd_start_adapter(pre_cac_adapter)) {
6946 hdd_err("error starting the pre cac adapter");
6947 goto close_pre_cac_adapter;
6948 }
6949
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306950 hdd_debug("preparing for start ap/bss on the pre cac adapter");
6951
6952 wiphy = hdd_ctx->wiphy;
6953 dev = pre_cac_adapter->dev;
6954
6955 /* Since this is only a dummy interface lets us use the IEs from the
6956 * other active SAP interface. In regular scenarios, these IEs would
6957 * come from the user space entity
6958 */
6959 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
6960 sizeof(*ap_adapter->sessionCtx.ap.beacon));
6961 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
6962 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306963 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306964 }
6965 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
6966 ap_adapter->sessionCtx.ap.beacon,
6967 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
6968 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
6969 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
6970 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
6971 ap_adapter->sessionCtx.ap.sapConfig.authType;
6972
6973 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
6974 * to operate on the same bandwidth as that of the 2.4GHz operations.
6975 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
6976 */
6977 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
6978 case CH_WIDTH_20MHZ:
6979 channel_type = NL80211_CHAN_HT20;
6980 break;
6981 case CH_WIDTH_40MHZ:
6982 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
6983 ap_adapter->sessionCtx.ap.sapConfig.channel)
6984 channel_type = NL80211_CHAN_HT40PLUS;
6985 else
6986 channel_type = NL80211_CHAN_HT40MINUS;
6987 break;
6988 default:
6989 channel_type = NL80211_CHAN_NO_HT;
6990 break;
6991 }
6992
6993 freq = cds_chan_to_freq(pre_cac_chan);
6994 chan = __ieee80211_get_channel(wiphy, freq);
6995 if (!chan) {
6996 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306997 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306998 }
6999
7000 cfg80211_chandef_create(&chandef, chan, channel_type);
7001
7002 hdd_debug("orig width:%d channel_type:%d freq:%d",
7003 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7004 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007005 /*
7006 * Doing update after opening and starting pre-cac adapter will make
7007 * sure that driver won't do hardware mode change if there are any
7008 * initial hick-ups or issues in pre-cac adapter's configuration.
7009 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7010 * connection update should result in DBS mode
7011 */
7012 status = cds_update_and_wait_for_connection_update(
7013 ap_adapter->sessionId,
7014 pre_cac_chan,
7015 SIR_UPDATE_REASON_PRE_CAC);
7016 if (QDF_IS_STATUS_ERROR(status)) {
7017 hdd_err("error in moving to DBS mode");
7018 goto stop_close_pre_cac_adapter;
7019 }
7020
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307021
7022 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7023 if (0 != ret) {
7024 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307025 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307026 }
7027
7028 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7029 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007030 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307031 if (QDF_IS_STATUS_ERROR(status)) {
7032 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307033 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307034 }
7035
7036 /*
7037 * The pre cac status is set here. But, it would not be reset explicitly
7038 * anywhere, since after the pre cac success/failure, the pre cac
7039 * adapter itself would be removed.
7040 */
7041 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7042 if (0 != ret) {
7043 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307044 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307045 }
7046
7047 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7048 hdd_ap_ctx->operatingChannel);
7049 if (0 != ret) {
7050 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307051 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307052 }
7053
7054 ap_adapter->pre_cac_chan = pre_cac_chan;
7055
7056 return 0;
7057
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307058stop_close_pre_cac_adapter:
7059 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307060 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7061 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307062close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307063 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007064release_intf_addr_and_return_failure:
7065 /*
7066 * Release the interface address as the adapter
7067 * failed to start, if you don't release then next
7068 * adapter which is trying to come wouldn't get valid
7069 * mac address. Remember we have limited pool of mac addresses
7070 */
7071 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307072 return -EINVAL;
7073}
7074
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307075/**
7076 * hdd_init_bpf_completion() - Initialize the completion event for bpf
7077 *
7078 * Return: None
7079 */
7080void hdd_init_bpf_completion(void)
7081{
7082 init_completion(&bpf_context.completion);
7083}
7084
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307085static const struct nla_policy
7086wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7087 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7088};
7089
Agrawal Ashish65634612016-08-18 13:24:32 +05307090static const struct nla_policy
7091wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7092 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7093 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7094};
7095
7096/**
7097 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7098 * @wiphy: Pointer to wireless phy
7099 * @wdev: Pointer to wireless device
7100 * @data: Pointer to data
7101 * @data_len: Length of @data
7102 *
7103 * This function parses the incoming NL vendor command data attributes and
7104 * updates the SAP context about channel_hint and DFS mode.
7105 * If channel_hint is set, SAP will choose that channel
7106 * as operating channel.
7107 *
7108 * If DFS mode is enabled, driver will include DFS channels
7109 * in ACS else driver will skip DFS channels.
7110 *
7111 * Return: 0 on success, negative errno on failure
7112 */
7113static int
7114__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7115 struct wireless_dev *wdev,
7116 const void *data, int data_len)
7117{
7118 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7119 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7120 int ret;
7121 struct acs_dfs_policy *acs_policy;
7122 int mode = DFS_MODE_NONE;
7123 int channel_hint = 0;
7124
7125 ENTER_DEV(wdev->netdev);
7126
7127 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7128 hdd_err("Command not allowed in FTM mode");
7129 return -EINVAL;
7130 }
7131
7132 ret = wlan_hdd_validate_context(hdd_ctx);
7133 if (0 != ret)
7134 return ret;
7135
7136 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7137 data, data_len,
7138 wlan_hdd_set_acs_dfs_config_policy)) {
7139 hdd_err("invalid attr");
7140 return -EINVAL;
7141 }
7142
7143 acs_policy = &hdd_ctx->acs_policy;
7144 /*
7145 * SCM sends this attribute to restrict SAP from choosing
7146 * DFS channels from ACS.
7147 */
7148 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7149 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7150
7151 if (!IS_DFS_MODE_VALID(mode)) {
7152 hdd_err("attr acs dfs mode is not valid");
7153 return -EINVAL;
7154 }
7155 acs_policy->acs_dfs_mode = mode;
7156
7157 /*
7158 * SCM sends this attribute to provide an active channel,
7159 * to skip redundant ACS between drivers, and save driver start up time
7160 */
7161 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7162 channel_hint = nla_get_u8(
7163 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7164
7165 if (!IS_CHANNEL_VALID(channel_hint)) {
7166 hdd_err("acs channel is not valid");
7167 return -EINVAL;
7168 }
7169 acs_policy->acs_channel = channel_hint;
7170
7171 return 0;
7172}
7173
7174/**
7175 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7176 * @wiphy: wiphy structure pointer
7177 * @wdev: Wireless device structure pointer
7178 * @data: Pointer to the data received
7179 * @data_len: Length of @data
7180 *
7181 * This function parses the incoming NL vendor command data attributes and
7182 * updates the SAP context about channel_hint and DFS mode.
7183 *
7184 * Return: 0 on success; errno on failure
7185 */
7186static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7187 struct wireless_dev *wdev,
7188 const void *data, int data_len)
7189{
7190 int ret;
7191
7192 cds_ssr_protect(__func__);
7193 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7194 cds_ssr_unprotect(__func__);
7195
7196 return ret;
7197}
7198
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307199/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307200 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7201 * @mode : cfg80211 dfs mode
7202 *
7203 * Return: return csr sta roam dfs mode else return NONE
7204 */
7205static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7206 enum dfs_mode mode)
7207{
7208 switch (mode) {
7209 case DFS_MODE_ENABLE:
7210 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7211 break;
7212 case DFS_MODE_DISABLE:
7213 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7214 break;
7215 case DFS_MODE_DEPRIORITIZE:
7216 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7217 break;
7218 default:
7219 hdd_err("STA Roam policy dfs mode is NONE");
7220 return CSR_STA_ROAM_POLICY_NONE;
7221 }
7222}
7223
7224static const struct nla_policy
7225wlan_hdd_set_sta_roam_config_policy[
7226QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7227 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7228 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7229};
7230
7231/**
7232 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7233 * for station connection or roaming.
7234 * @wiphy: Pointer to wireless phy
7235 * @wdev: Pointer to wireless device
7236 * @data: Pointer to data
7237 * @data_len: Length of @data
7238 *
7239 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7240 * channels needs to be skipped in scanning or not.
7241 * If dfs_mode is disabled, driver will not scan DFS channels.
7242 * If skip_unsafe_channels is set, driver will skip unsafe channels
7243 * in Scanning.
7244 *
7245 * Return: 0 on success, negative errno on failure
7246 */
7247static int
7248__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7249 struct wireless_dev *wdev,
7250 const void *data, int data_len)
7251{
7252 struct net_device *dev = wdev->netdev;
7253 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7254 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7255 struct nlattr *tb[
7256 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7257 int ret;
7258 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7259 enum dfs_mode mode = DFS_MODE_NONE;
7260 bool skip_unsafe_channels = false;
7261 QDF_STATUS status;
7262
7263 ENTER_DEV(dev);
7264
7265 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7266 hdd_err("Command not allowed in FTM mode");
7267 return -EINVAL;
7268 }
7269
7270 ret = wlan_hdd_validate_context(hdd_ctx);
7271 if (0 != ret)
7272 return ret;
7273 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7274 data, data_len,
7275 wlan_hdd_set_sta_roam_config_policy)) {
7276 hdd_err("invalid attr");
7277 return -EINVAL;
7278 }
7279 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7280 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7281 if (!IS_DFS_MODE_VALID(mode)) {
7282 hdd_err("attr sta roam dfs mode policy is not valid");
7283 return -EINVAL;
7284 }
7285
7286 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7287
7288 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7289 skip_unsafe_channels = nla_get_u8(
7290 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
7291
7292 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
7293 skip_unsafe_channels, adapter->sessionId);
7294
7295 if (!QDF_IS_STATUS_SUCCESS(status)) {
7296 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7297 return -EINVAL;
7298 }
7299 return 0;
7300}
7301
7302/**
7303 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7304 * connection and roaming for station.
7305 * @wiphy: wiphy structure pointer
7306 * @wdev: Wireless device structure pointer
7307 * @data: Pointer to the data received
7308 * @data_len: Length of @data
7309 *
7310 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7311 * channels needs to be skipped in scanning or not.
7312 * If dfs_mode is disabled, driver will not scan DFS channels.
7313 * If skip_unsafe_channels is set, driver will skip unsafe channels
7314 * in Scanning.
7315 * Return: 0 on success; errno on failure
7316 */
7317static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7318 struct wireless_dev *wdev,
7319 const void *data, int data_len)
7320{
7321 int ret;
7322
7323 cds_ssr_protect(__func__);
7324 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7325 cds_ssr_unprotect(__func__);
7326
7327 return ret;
7328}
7329
Agrawal Ashish467dde42016-09-08 18:44:22 +05307330#ifdef FEATURE_WLAN_CH_AVOID
7331/**
7332 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7333 * is on unsafe channel.
7334 * @wiphy: wiphy structure pointer
7335 * @wdev: Wireless device structure pointer
7336 * @data: Pointer to the data received
7337 * @data_len: Length of @data
7338 *
7339 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7340 * on any of unsafe channels.
7341 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7342 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7343 *
7344 * Return: 0 on success; errno on failure
7345 */
7346static int
7347__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7348 struct wireless_dev *wdev,
7349 const void *data, int data_len)
7350{
7351 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7352 int ret;
7353 uint16_t unsafe_channel_count;
7354 int unsafe_channel_index;
7355 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7356
7357 ENTER_DEV(wdev->netdev);
7358
7359 if (!qdf_ctx) {
7360 cds_err("qdf_ctx is NULL");
7361 return -EINVAL;
7362 }
7363
7364 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7365 hdd_err("Command not allowed in FTM mode");
7366 return -EINVAL;
7367 }
7368
7369 ret = wlan_hdd_validate_context(hdd_ctx);
7370 if (0 != ret)
7371 return ret;
7372 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7373 &(hdd_ctx->unsafe_channel_count),
7374 sizeof(hdd_ctx->unsafe_channel_list));
7375
7376 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7377 (uint16_t)NUM_CHANNELS);
7378 for (unsafe_channel_index = 0;
7379 unsafe_channel_index < unsafe_channel_count;
7380 unsafe_channel_index++) {
7381 hdd_info("Channel %d is not safe",
7382 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7383 }
7384 hdd_unsafe_channel_restart_sap(hdd_ctx);
7385 return 0;
7386}
7387
7388/**
7389 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7390 * is on unsafe channel.
7391 * @wiphy: wiphy structure pointer
7392 * @wdev: Wireless device structure pointer
7393 * @data: Pointer to the data received
7394 * @data_len: Length of @data
7395 *
7396 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7397 * on any of unsafe channels.
7398 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7399 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7400 *
7401 * Return: 0 on success; errno on failure
7402 */
7403static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7404 struct wireless_dev *wdev,
7405 const void *data, int data_len)
7406{
7407 int ret;
7408
7409 cds_ssr_protect(__func__);
7410 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
7411 cds_ssr_unprotect(__func__);
7412
7413 return ret;
7414}
7415
7416#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307417/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307418 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
7419 * SAP is on unsafe channel.
7420 * @wiphy: wiphy structure pointer
7421 * @wdev: Wireless device structure pointer
7422 * @data: Pointer to the data received
7423 * @data_len: Length of @data
7424 *
7425 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7426 * driver.
7427 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7428 * will initiate restart of sap.
7429 *
7430 * Return: 0 on success; errno on failure
7431 */
7432static int
7433__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7434 struct wireless_dev *wdev,
7435 const void *data, int data_len)
7436{
7437 struct net_device *ndev = wdev->netdev;
7438 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7439 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7440 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
7441 uint8_t config_channel = 0;
7442 hdd_ap_ctx_t *ap_ctx;
7443 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307444 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307445
7446 ENTER();
7447
7448 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007449 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307450 return -EINVAL;
7451 }
7452
7453 ret = wlan_hdd_validate_context(hdd_ctx);
7454 if (0 != ret)
7455 return -EINVAL;
7456
7457 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
7458 data, data_len,
7459 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007460 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307461 return -EINVAL;
7462 }
7463
7464 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
7465 if (!test_bit(SOFTAP_BSS_STARTED,
7466 &hostapd_adapter->event_flags)) {
7467 hdd_err("SAP is not started yet. Restart sap will be invalid");
7468 return -EINVAL;
7469 }
7470
7471 config_channel =
7472 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
7473
7474 if (!((IS_24G_CH(config_channel)) ||
7475 (IS_5G_CH(config_channel)))) {
7476 hdd_err("Channel %d is not valid to restart SAP",
7477 config_channel);
7478 return -ENOTSUPP;
7479 }
7480
7481 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
7482 ap_ctx->sapConfig.channel = config_channel;
7483 ap_ctx->sapConfig.ch_params.ch_width =
7484 ap_ctx->sapConfig.ch_width_orig;
7485
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07007486 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307487 ap_ctx->sapConfig.sec_ch,
7488 &ap_ctx->sapConfig.ch_params);
7489
7490 cds_restart_sap(hostapd_adapter);
7491 }
7492
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307493 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
7494 uint32_t freq_len, i;
7495 uint32_t *freq;
7496 uint8_t chans[QDF_MAX_NUM_CHAN];
7497
7498 hdd_debug("setting mandatory freq/chan list");
7499
7500 freq_len = nla_len(
7501 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
7502 sizeof(uint32_t);
7503
7504 if (freq_len > QDF_MAX_NUM_CHAN) {
7505 hdd_err("insufficient space to hold channels");
7506 return -ENOMEM;
7507 }
7508
7509 freq = nla_data(
7510 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
7511
7512 hdd_debug("freq_len=%d", freq_len);
7513
7514 for (i = 0; i < freq_len; i++) {
7515 chans[i] = ieee80211_frequency_to_channel(freq[i]);
7516 hdd_debug("freq[%d]=%d", i, freq[i]);
7517 }
7518
7519 status = cds_set_sap_mandatory_channels(chans, freq_len);
7520 if (QDF_IS_STATUS_ERROR(status))
7521 return -EINVAL;
7522 }
7523
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307524 return 0;
7525}
7526
7527/**
7528 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
7529 * @wiphy: wiphy structure pointer
7530 * @wdev: Wireless device structure pointer
7531 * @data: Pointer to the data received
7532 * @data_len: Length of @data
7533 *
7534 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7535 * driver.
7536 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7537 * will initiate restart of sap.
7538 *
7539 * Return: 0 on success; errno on failure
7540 */
7541static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7542 struct wireless_dev *wdev,
7543 const void *data, int data_len)
7544{
7545 int ret;
7546
7547 cds_ssr_protect(__func__);
7548 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
7549 wdev, data, data_len);
7550 cds_ssr_unprotect(__func__);
7551
7552 return ret;
7553}
7554
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307555#undef BPF_INVALID
7556#undef BPF_SET_RESET
7557#undef BPF_VERSION
7558#undef BPF_ID
7559#undef BPF_PACKET_SIZE
7560#undef BPF_CURRENT_OFFSET
7561#undef BPF_PROGRAM
7562#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307563
7564/**
7565 * define short names for the global vendor params
7566 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
7567 */
7568#define PARAM_TOTAL_CMD_EVENT_WAKE \
7569 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
7570#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
7571 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
7572#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
7573 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
7574#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
7575 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
7576#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
7577 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
7578#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
7579 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
7580#define PARAM_TOTAL_RX_DATA_WAKE \
7581 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
7582#define PARAM_RX_UNICAST_CNT \
7583 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
7584#define PARAM_RX_MULTICAST_CNT \
7585 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
7586#define PARAM_RX_BROADCAST_CNT \
7587 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
7588#define PARAM_ICMP_PKT \
7589 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
7590#define PARAM_ICMP6_PKT \
7591 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
7592#define PARAM_ICMP6_RA \
7593 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
7594#define PARAM_ICMP6_NA \
7595 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
7596#define PARAM_ICMP6_NS \
7597 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
7598#define PARAM_ICMP4_RX_MULTICAST_CNT \
7599 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
7600#define PARAM_ICMP6_RX_MULTICAST_CNT \
7601 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
7602#define PARAM_OTHER_RX_MULTICAST_CNT \
7603 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05307604#define PARAM_RSSI_BREACH_CNT \
7605 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
7606#define PARAM_LOW_RSSI_CNT \
7607 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
7608#define PARAM_GSCAN_CNT \
7609 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
7610#define PARAM_PNO_COMPLETE_CNT \
7611 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
7612#define PARAM_PNO_MATCH_CNT \
7613 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
7614
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307615
7616
7617/**
7618 * hdd_send_wakelock_stats() - API to send wakelock stats
7619 * @ctx: context to be passed to callback
7620 * @data: data passed to callback
7621 *
7622 * This function is used to send wake lock stats to HAL layer
7623 *
7624 * Return: 0 on success, error number otherwise.
7625 */
7626static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
7627 const struct sir_wake_lock_stats *data)
7628{
7629 struct sk_buff *skb;
7630 uint32_t nl_buf_len;
7631 uint32_t total_rx_data_wake, rx_multicast_cnt;
7632 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307633 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307634
7635 ENTER();
7636
7637 nl_buf_len = NLMSG_HDRLEN;
7638 nl_buf_len +=
7639 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
7640 (NLMSG_HDRLEN + sizeof(uint32_t));
7641
7642 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7643
7644 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007645 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307646 return -ENOMEM;
7647 }
7648
Jeff Johnson64943bd2016-08-23 13:14:06 -07007649 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307650 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007651 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307652 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007653 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307654 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007655 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307656 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007657 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307658 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007659 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307660 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007661 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307662 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007663 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
7664 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307665 data->wow_icmpv6_count);
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05307666 hdd_info("wow_rssi_breach_wake_up_count %d",
7667 data->wow_rssi_breach_wake_up_count);
7668 hdd_info("wow_low_rssi_wake_up_count %d",
7669 data->wow_low_rssi_wake_up_count);
7670 hdd_info("wow_gscan_wake_up_count %d",
7671 data->wow_gscan_wake_up_count);
7672 hdd_info("wow_pno_complete_wake_up_count %d",
7673 data->wow_pno_complete_wake_up_count);
7674 hdd_info("wow_pno_match_wake_up_count %d",
7675 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307676
7677 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307678 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307679
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307680 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307681 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307682
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307683 rx_multicast_cnt =
7684 data->wow_ipv4_mcast_wake_up_count +
7685 ipv6_rx_multicast_addr_cnt;
7686
7687 total_rx_data_wake =
7688 data->wow_ucast_wake_up_count +
7689 data->wow_bcast_wake_up_count +
7690 rx_multicast_cnt;
7691
7692 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
7693 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
7694 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
7695 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
7696 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
7697 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
7698 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
7699 total_rx_data_wake) ||
7700 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
7701 data->wow_ucast_wake_up_count) ||
7702 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
7703 rx_multicast_cnt) ||
7704 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
7705 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307706 nla_put_u32(skb, PARAM_ICMP_PKT,
7707 data->wow_icmpv4_count) ||
7708 nla_put_u32(skb, PARAM_ICMP6_PKT,
7709 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307710 nla_put_u32(skb, PARAM_ICMP6_RA,
7711 data->wow_ipv6_mcast_ra_stats) ||
7712 nla_put_u32(skb, PARAM_ICMP6_NA,
7713 data->wow_ipv6_mcast_na_stats) ||
7714 nla_put_u32(skb, PARAM_ICMP6_NS,
7715 data->wow_ipv6_mcast_ns_stats) ||
7716 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
7717 data->wow_ipv4_mcast_wake_up_count) ||
7718 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
7719 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05307720 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
7721 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
7722 data->wow_rssi_breach_wake_up_count) ||
7723 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
7724 data->wow_low_rssi_wake_up_count) ||
7725 nla_put_u32(skb, PARAM_GSCAN_CNT,
7726 data->wow_gscan_wake_up_count) ||
7727 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
7728 data->wow_pno_complete_wake_up_count) ||
7729 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
7730 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007731 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307732 goto nla_put_failure;
7733 }
7734
7735 cfg80211_vendor_cmd_reply(skb);
7736
7737 EXIT();
7738 return 0;
7739
7740nla_put_failure:
7741 kfree_skb(skb);
7742 return -EINVAL;
7743}
7744
7745/**
7746 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7747 * @wiphy: wiphy pointer
7748 * @wdev: pointer to struct wireless_dev
7749 * @data: pointer to incoming NL vendor data
7750 * @data_len: length of @data
7751 *
7752 * This function parses the incoming NL vendor command data attributes and
7753 * invokes the SME Api and blocks on a completion variable.
7754 * WMA copies required data and invokes callback
7755 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7756 *
7757 * Return: 0 on success; error number otherwise.
7758 */
7759static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7760 struct wireless_dev *wdev,
7761 const void *data,
7762 int data_len)
7763{
7764 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7765 int status, ret;
7766 struct sir_wake_lock_stats wake_lock_stats;
7767 QDF_STATUS qdf_status;
7768
7769 ENTER();
7770
7771 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007772 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307773 return -EINVAL;
7774 }
7775
7776 status = wlan_hdd_validate_context(hdd_ctx);
7777 if (0 != status)
7778 return -EINVAL;
7779
7780 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
7781 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007782 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307783 return -EINVAL;
7784 }
7785
7786 ret = hdd_send_wakelock_stats(hdd_ctx,
7787 &wake_lock_stats);
7788 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07007789 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307790
7791 EXIT();
7792 return ret;
7793}
7794
7795/**
7796 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7797 * @wiphy: wiphy pointer
7798 * @wdev: pointer to struct wireless_dev
7799 * @data: pointer to incoming NL vendor data
7800 * @data_len: length of @data
7801 *
7802 * This function parses the incoming NL vendor command data attributes and
7803 * invokes the SME Api and blocks on a completion variable.
7804 * WMA copies required data and invokes callback
7805 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7806 *
7807 * Return: 0 on success; error number otherwise.
7808 */
7809static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7810 struct wireless_dev *wdev,
7811 const void *data, int data_len)
7812{
7813 int ret;
7814
7815 cds_ssr_protect(__func__);
7816 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
7817 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07007818 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307819
7820 return ret;
7821}
7822
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307823/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05307824 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
7825 * @wiphy: wiphy structure pointer
7826 * @wdev: Wireless device structure pointer
7827 * @data: Pointer to the data received
7828 * @data_len: Length of @data
7829 *
7830 * This function reads wmi max bus size and fill in the skb with
7831 * NL attributes and send up the NL event.
7832 * Return: 0 on success; errno on failure
7833 */
7834static int
7835__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7836 struct wireless_dev *wdev,
7837 const void *data, int data_len)
7838{
7839 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7840 int ret_val;
7841 struct sk_buff *skb;
7842 uint32_t nl_buf_len;
7843
7844 ENTER();
7845
7846 ret_val = wlan_hdd_validate_context(hdd_ctx);
7847 if (ret_val)
7848 return ret_val;
7849
7850 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7851 hdd_err("Command not allowed in FTM mode");
7852 return -EINVAL;
7853 }
7854
7855 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
7856
7857 nl_buf_len = NLMSG_HDRLEN;
7858 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
7859
7860 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7861 if (!skb) {
7862 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
7863 return -ENOMEM;
7864 }
7865
7866 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
7867 hdd_ctx->wmi_max_len)) {
7868 hdd_err("nla put failure");
7869 goto nla_put_failure;
7870 }
7871
7872 cfg80211_vendor_cmd_reply(skb);
7873
7874 EXIT();
7875
7876 return 0;
7877
7878nla_put_failure:
7879 kfree_skb(skb);
7880 return -EINVAL;
7881}
7882
7883/**
7884 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
7885 * @wiphy: wiphy structure pointer
7886 * @wdev: Wireless device structure pointer
7887 * @data: Pointer to the data received
7888 * @data_len: Length of @data
7889 *
7890 * Return: 0 on success; errno on failure
7891 */
7892static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7893 struct wireless_dev *wdev,
7894 const void *data, int data_len)
7895{
7896 int ret;
7897
7898 cds_ssr_protect(__func__);
7899 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
7900 cds_ssr_unprotect(__func__);
7901
7902 return ret;
7903}
7904
7905/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307906 *__wlan_hdd_cfg80211_setband() - set band
7907 * @wiphy: Pointer to wireless phy
7908 * @wdev: Pointer to wireless device
7909 * @data: Pointer to data
7910 * @data_len: Length of @data
7911 *
7912 * Return: 0 on success, negative errno on failure
7913 */
7914static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7915 struct wireless_dev *wdev,
7916 const void *data, int data_len)
7917{
7918 struct net_device *dev = wdev->netdev;
7919 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7920 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7921 int ret;
7922 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
7923 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
7924
7925 ENTER();
7926
7927 ret = wlan_hdd_validate_context(hdd_ctx);
7928 if (ret)
7929 return ret;
7930
7931 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
7932 hdd_err(FL("Invalid ATTR"));
7933 return -EINVAL;
7934 }
7935
7936 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
7937 hdd_err(FL("attr SETBAND_VALUE failed"));
7938 return -EINVAL;
7939 }
7940
7941 ret = hdd_set_band(dev,
7942 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
7943
7944 EXIT();
7945 return ret;
7946}
7947
7948/**
7949 * wlan_hdd_cfg80211_setband() - Wrapper to setband
7950 * @wiphy: wiphy structure pointer
7951 * @wdev: Wireless device structure pointer
7952 * @data: Pointer to the data received
7953 * @data_len: Length of @data
7954 *
7955 * Return: 0 on success; errno on failure
7956 */
7957static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7958 struct wireless_dev *wdev,
7959 const void *data, int data_len)
7960{
7961 int ret;
7962
7963 cds_ssr_protect(__func__);
7964 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
7965 cds_ssr_unprotect(__func__);
7966
7967 return ret;
7968}
7969
Mukul Sharma69c44cd2016-09-12 18:33:57 +05307970static const struct
7971nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
7972 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
7973 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
7974 .len = QDF_MAC_ADDR_SIZE},
7975};
7976
7977/**
7978 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7979 * @wiphy: Pointer to wireless phy
7980 * @wdev: Pointer to wireless device
7981 * @data: Pointer to data
7982 * @data_len: Length of @data
7983 *
7984 * This function is used to enable/disable roaming using vendor commands
7985 *
7986 * Return: 0 on success, negative errno on failure
7987 */
7988static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7989 struct wireless_dev *wdev,
7990 const void *data, int data_len)
7991{
7992 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7993 struct net_device *dev = wdev->netdev;
7994 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7995 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7996 uint32_t is_fast_roam_enabled;
7997 int ret;
7998
7999 ENTER_DEV(dev);
8000
8001 ret = wlan_hdd_validate_context(hdd_ctx);
8002 if (0 != ret)
8003 return ret;
8004
8005 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8006 hdd_err("Command not allowed in FTM mode");
8007 return -EINVAL;
8008 }
8009
8010 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
8011 qca_wlan_vendor_attr);
8012 if (ret) {
8013 hdd_err("Invalid ATTR");
8014 return -EINVAL;
8015 }
8016
8017 /* Parse and fetch Enable flag */
8018 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
8019 hdd_err("attr enable failed");
8020 return -EINVAL;
8021 }
8022
8023 is_fast_roam_enabled = nla_get_u32(
8024 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
8025 hdd_notice("isFastRoamEnabled %d", is_fast_roam_enabled);
8026
8027 /* Update roaming */
8028 ret = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
8029 is_fast_roam_enabled);
8030 if (ret)
8031 hdd_err("sme_config_fast_roaming failed");
8032 EXIT();
8033 return ret;
8034}
8035
8036/**
8037 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
8038 * @wiphy: Pointer to wireless phy
8039 * @wdev: Pointer to wireless device
8040 * @data: Pointer to data
8041 * @data_len: Length of @data
8042 *
8043 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
8044 *
8045 * Return: 0 on success, negative errno on failure
8046 */
8047static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
8048 struct wireless_dev *wdev,
8049 const void *data, int data_len)
8050{
8051 int ret;
8052
8053 cds_ssr_protect(__func__);
8054 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
8055 cds_ssr_unprotect(__func__);
8056
8057 return ret;
8058}
8059
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008060const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
8061 {
8062 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8063 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
8064 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05308065 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008066 .doit = is_driver_dfs_capable
8067 },
8068
8069#ifdef WLAN_FEATURE_NAN
8070 {
8071 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8072 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
8073 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8074 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8075 .doit = wlan_hdd_cfg80211_nan_request
8076 },
8077#endif
8078
8079#ifdef WLAN_FEATURE_STATS_EXT
8080 {
8081 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8082 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
8083 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8084 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8085 .doit = wlan_hdd_cfg80211_stats_ext_request
8086 },
8087#endif
8088#ifdef FEATURE_WLAN_EXTSCAN
8089 {
8090 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8091 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
8092 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8093 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8094 .doit = wlan_hdd_cfg80211_extscan_start
8095 },
8096 {
8097 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8098 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
8099 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8100 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8101 .doit = wlan_hdd_cfg80211_extscan_stop
8102 },
8103 {
8104 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8105 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
8106 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8107 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
8108 },
8109 {
8110 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8111 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
8112 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8113 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8114 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
8115 },
8116 {
8117 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8118 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
8119 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8120 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8121 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
8122 },
8123 {
8124 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8125 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
8126 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8127 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8128 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
8129 },
8130 {
8131 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8132 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
8133 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8134 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8135 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
8136 },
8137 {
8138 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8139 .info.subcmd =
8140 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
8141 .flags =
8142 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8143 WIPHY_VENDOR_CMD_NEED_RUNNING,
8144 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
8145 },
8146 {
8147 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8148 .info.subcmd =
8149 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
8150 .flags =
8151 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8152 WIPHY_VENDOR_CMD_NEED_RUNNING,
8153 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
8154 },
8155 {
8156 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8157 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
8158 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8159 WIPHY_VENDOR_CMD_NEED_NETDEV |
8160 WIPHY_VENDOR_CMD_NEED_RUNNING,
8161 .doit = wlan_hdd_cfg80211_set_epno_list
8162 },
8163#endif /* FEATURE_WLAN_EXTSCAN */
8164
8165#ifdef WLAN_FEATURE_LINK_LAYER_STATS
8166 {
8167 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8168 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
8169 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8170 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8171 .doit = wlan_hdd_cfg80211_ll_stats_clear
8172 },
8173
8174 {
8175 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8176 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
8177 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8178 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8179 .doit = wlan_hdd_cfg80211_ll_stats_set
8180 },
8181
8182 {
8183 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8184 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
8185 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8186 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8187 .doit = wlan_hdd_cfg80211_ll_stats_get
8188 },
8189#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
8190#ifdef FEATURE_WLAN_TDLS
8191 {
8192 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8193 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
8194 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8195 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8196 .doit = wlan_hdd_cfg80211_exttdls_enable
8197 },
8198 {
8199 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8200 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
8201 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8202 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8203 .doit = wlan_hdd_cfg80211_exttdls_disable
8204 },
8205 {
8206 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8207 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
8208 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8209 .doit = wlan_hdd_cfg80211_exttdls_get_status
8210 },
8211#endif
8212 {
8213 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8214 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
8215 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8216 .doit = wlan_hdd_cfg80211_get_supported_features
8217 },
8218 {
8219 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8220 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
8221 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8222 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
8223 },
8224 {
8225 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8226 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
8227 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05308228 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008229 },
8230 {
8231 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8232 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
8233 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8234 WIPHY_VENDOR_CMD_NEED_NETDEV,
8235 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
8236 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07008237 {
8238 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8239 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
8240 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8241 WIPHY_VENDOR_CMD_NEED_NETDEV,
8242 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
8243 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008244 {
8245 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05308246 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
8247 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8248 WIPHY_VENDOR_CMD_NEED_NETDEV |
8249 WIPHY_VENDOR_CMD_NEED_RUNNING,
8250 .doit = hdd_cfg80211_get_station_cmd
8251 },
8252 {
8253 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008254 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
8255 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8256 WIPHY_VENDOR_CMD_NEED_NETDEV |
8257 WIPHY_VENDOR_CMD_NEED_RUNNING,
8258 .doit = wlan_hdd_cfg80211_do_acs
8259 },
8260
8261 {
8262 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8263 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
8264 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8265 WIPHY_VENDOR_CMD_NEED_NETDEV,
8266 .doit = wlan_hdd_cfg80211_get_features
8267 },
8268#ifdef WLAN_FEATURE_ROAM_OFFLOAD
8269 {
8270 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8271 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
8272 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8273 WIPHY_VENDOR_CMD_NEED_NETDEV |
8274 WIPHY_VENDOR_CMD_NEED_RUNNING,
8275 .doit = wlan_hdd_cfg80211_keymgmt_set_key
8276 },
8277#endif
8278#ifdef FEATURE_WLAN_EXTSCAN
8279 {
8280 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8281 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
8282 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8283 WIPHY_VENDOR_CMD_NEED_NETDEV |
8284 WIPHY_VENDOR_CMD_NEED_RUNNING,
8285 .doit = wlan_hdd_cfg80211_set_passpoint_list
8286 },
8287 {
8288 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8289 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
8290 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8291 WIPHY_VENDOR_CMD_NEED_NETDEV |
8292 WIPHY_VENDOR_CMD_NEED_RUNNING,
8293 .doit = wlan_hdd_cfg80211_reset_passpoint_list
8294 },
8295 {
8296 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8297 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
8298 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8299 WIPHY_VENDOR_CMD_NEED_NETDEV |
8300 WIPHY_VENDOR_CMD_NEED_RUNNING,
8301 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
8302 },
8303 {
8304 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8305 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
8306 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8307 WIPHY_VENDOR_CMD_NEED_NETDEV |
8308 WIPHY_VENDOR_CMD_NEED_RUNNING,
8309 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
8310 },
8311#endif /* FEATURE_WLAN_EXTSCAN */
8312 {
8313 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8314 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
8315 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8316 WIPHY_VENDOR_CMD_NEED_NETDEV,
8317 .doit = wlan_hdd_cfg80211_get_wifi_info
8318 },
Paul Zhang3a210c52016-12-08 10:18:12 +08008319#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008320 {
8321 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8322 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
8323 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8324 WIPHY_VENDOR_CMD_NEED_NETDEV |
8325 WIPHY_VENDOR_CMD_NEED_RUNNING,
8326 .doit = wlan_hdd_cfg80211_wifi_configuration_set
8327 },
Paul Zhang3a210c52016-12-08 10:18:12 +08008328#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008329 {
8330 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8331 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
8332 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8333 WIPHY_VENDOR_CMD_NEED_NETDEV,
8334 .doit = wlan_hdd_cfg80211_set_ext_roam_params
8335 },
8336 {
8337 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8338 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
8339 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8340 WIPHY_VENDOR_CMD_NEED_NETDEV,
8341 .doit = wlan_hdd_cfg80211_wifi_logger_start
8342 },
8343 {
8344 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8345 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
8346 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8347 WIPHY_VENDOR_CMD_NEED_NETDEV,
8348 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
8349 },
8350 {
8351 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8352 .info.subcmd =
8353 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
8354 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8355 WIPHY_VENDOR_CMD_NEED_NETDEV |
8356 WIPHY_VENDOR_CMD_NEED_RUNNING,
8357 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
8358 },
8359 {
8360 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8361 .info.subcmd =
8362 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
8363 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8364 WIPHY_VENDOR_CMD_NEED_NETDEV |
8365 WIPHY_VENDOR_CMD_NEED_RUNNING,
8366 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
8367 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07008368#ifdef WLAN_FEATURE_TSF
8369 {
8370 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8371 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
8372 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8373 WIPHY_VENDOR_CMD_NEED_NETDEV |
8374 WIPHY_VENDOR_CMD_NEED_RUNNING,
8375 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
8376 },
8377#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008378#ifdef FEATURE_WLAN_TDLS
8379 {
8380 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8381 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
8382 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8383 WIPHY_VENDOR_CMD_NEED_NETDEV |
8384 WIPHY_VENDOR_CMD_NEED_RUNNING,
8385 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
8386 },
8387#endif
8388#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
8389 {
8390 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8391 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
8392 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8393 WIPHY_VENDOR_CMD_NEED_NETDEV |
8394 WIPHY_VENDOR_CMD_NEED_RUNNING,
8395 .doit = wlan_hdd_cfg80211_offloaded_packets
8396 },
8397#endif
8398 {
8399 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8400 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
8401 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8402 WIPHY_VENDOR_CMD_NEED_NETDEV |
8403 WIPHY_VENDOR_CMD_NEED_RUNNING,
8404 .doit = wlan_hdd_cfg80211_monitor_rssi
8405 },
8406 {
8407 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308408 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
8409 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8410 WIPHY_VENDOR_CMD_NEED_NETDEV |
8411 WIPHY_VENDOR_CMD_NEED_RUNNING,
8412 .doit = wlan_hdd_cfg80211_set_ns_offload
8413 },
8414 {
8415 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008416 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
8417 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8418 WIPHY_VENDOR_CMD_NEED_NETDEV |
8419 WIPHY_VENDOR_CMD_NEED_RUNNING,
8420 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
8421 },
8422#ifdef WLAN_FEATURE_MEMDUMP
8423 {
8424 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8425 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
8426 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8427 WIPHY_VENDOR_CMD_NEED_NETDEV |
8428 WIPHY_VENDOR_CMD_NEED_RUNNING,
8429 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
8430 },
8431#endif /* WLAN_FEATURE_MEMDUMP */
8432 {
8433 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8434 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
8435 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8436 WIPHY_VENDOR_CMD_NEED_NETDEV |
8437 WIPHY_VENDOR_CMD_NEED_RUNNING,
8438 .doit = wlan_hdd_cfg80211_vendor_scan
8439 },
8440
8441 /* OCB commands */
8442 {
8443 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8444 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
8445 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8446 WIPHY_VENDOR_CMD_NEED_NETDEV |
8447 WIPHY_VENDOR_CMD_NEED_RUNNING,
8448 .doit = wlan_hdd_cfg80211_ocb_set_config
8449 },
8450 {
8451 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8452 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
8453 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8454 WIPHY_VENDOR_CMD_NEED_NETDEV |
8455 WIPHY_VENDOR_CMD_NEED_RUNNING,
8456 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
8457 },
8458 {
8459 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8460 .info.subcmd =
8461 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
8462 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8463 WIPHY_VENDOR_CMD_NEED_NETDEV |
8464 WIPHY_VENDOR_CMD_NEED_RUNNING,
8465 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
8466 },
8467 {
8468 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8469 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
8470 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8471 WIPHY_VENDOR_CMD_NEED_NETDEV |
8472 WIPHY_VENDOR_CMD_NEED_RUNNING,
8473 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
8474 },
8475 {
8476 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8477 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
8478 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8479 WIPHY_VENDOR_CMD_NEED_NETDEV |
8480 WIPHY_VENDOR_CMD_NEED_RUNNING,
8481 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
8482 },
8483 {
8484 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8485 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
8486 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8487 WIPHY_VENDOR_CMD_NEED_NETDEV |
8488 WIPHY_VENDOR_CMD_NEED_RUNNING,
8489 .doit = wlan_hdd_cfg80211_dcc_get_stats
8490 },
8491 {
8492 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8493 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
8494 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8495 WIPHY_VENDOR_CMD_NEED_NETDEV |
8496 WIPHY_VENDOR_CMD_NEED_RUNNING,
8497 .doit = wlan_hdd_cfg80211_dcc_clear_stats
8498 },
8499 {
8500 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8501 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
8502 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8503 WIPHY_VENDOR_CMD_NEED_NETDEV |
8504 WIPHY_VENDOR_CMD_NEED_RUNNING,
8505 .doit = wlan_hdd_cfg80211_dcc_update_ndl
8506 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308507 {
8508 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8509 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
8510 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8511 WIPHY_VENDOR_CMD_NEED_NETDEV |
8512 WIPHY_VENDOR_CMD_NEED_RUNNING,
8513 .doit = wlan_hdd_cfg80211_get_link_properties
8514 },
Peng Xu278d0122015-09-24 16:34:17 -07008515 {
Peng Xud2220962016-07-11 17:59:17 -07008516 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07008517 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
8518 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8519 WIPHY_VENDOR_CMD_NEED_NETDEV |
8520 WIPHY_VENDOR_CMD_NEED_RUNNING,
8521 .doit = wlan_hdd_cfg80211_set_ota_test
8522 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08008523#ifdef FEATURE_LFR_SUBNET_DETECTION
8524 {
8525 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8526 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
8527 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8528 WIPHY_VENDOR_CMD_NEED_NETDEV |
8529 WIPHY_VENDOR_CMD_NEED_RUNNING,
8530 .doit = wlan_hdd_cfg80211_set_gateway_params
8531 },
8532#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07008533 {
Peng Xud2220962016-07-11 17:59:17 -07008534 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07008535 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
8536 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8537 WIPHY_VENDOR_CMD_NEED_NETDEV |
8538 WIPHY_VENDOR_CMD_NEED_RUNNING,
8539 .doit = wlan_hdd_cfg80211_txpower_scale
8540 },
8541 {
8542 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8543 .info.subcmd =
8544 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
8545 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8546 WIPHY_VENDOR_CMD_NEED_NETDEV |
8547 WIPHY_VENDOR_CMD_NEED_RUNNING,
8548 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
8549 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308550 {
8551 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8552 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
8553 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8554 WIPHY_VENDOR_CMD_NEED_NETDEV |
8555 WIPHY_VENDOR_CMD_NEED_RUNNING,
8556 .doit = wlan_hdd_cfg80211_bpf_offload
8557 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308558 {
8559 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05308560 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
8561 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8562 WIPHY_VENDOR_CMD_NEED_NETDEV |
8563 WIPHY_VENDOR_CMD_NEED_RUNNING,
8564 .doit = wlan_hdd_cfg80211_acs_dfs_mode
8565 },
8566 {
8567 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308568 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
8569 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8570 WIPHY_VENDOR_CMD_NEED_NETDEV |
8571 WIPHY_VENDOR_CMD_NEED_RUNNING,
8572 .doit = wlan_hdd_cfg80211_sta_roam_policy
8573 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05308574#ifdef FEATURE_WLAN_CH_AVOID
8575 {
8576 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8577 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
8578 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8579 WIPHY_VENDOR_CMD_NEED_NETDEV |
8580 WIPHY_VENDOR_CMD_NEED_RUNNING,
8581 .doit = wlan_hdd_cfg80211_avoid_freq
8582 },
8583#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308584 {
8585 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308586 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
8587 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8588 WIPHY_VENDOR_CMD_NEED_NETDEV |
8589 WIPHY_VENDOR_CMD_NEED_RUNNING,
8590 .doit = wlan_hdd_cfg80211_sap_configuration_set
8591 },
Peng Xu8fdaa492016-06-22 10:20:47 -07008592 {
Peng Xu4225c152016-07-14 21:18:14 -07008593 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07008594 .info.subcmd =
8595 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
8596 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8597 WIPHY_VENDOR_CMD_NEED_NETDEV |
8598 WIPHY_VENDOR_CMD_NEED_RUNNING,
8599 .doit = wlan_hdd_cfg80211_p2p_lo_start
8600 },
8601 {
8602 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8603 .info.subcmd =
8604 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
8605 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8606 WIPHY_VENDOR_CMD_NEED_NETDEV |
8607 WIPHY_VENDOR_CMD_NEED_RUNNING,
8608 .doit = wlan_hdd_cfg80211_p2p_lo_stop
8609 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308610 {
8611 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8612 .info.subcmd =
8613 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
8614 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8615 WIPHY_VENDOR_CMD_NEED_NETDEV |
8616 WIPHY_VENDOR_CMD_NEED_RUNNING,
8617 .doit = wlan_hdd_cfg80211_conditional_chan_switch
8618 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07008619#ifdef WLAN_FEATURE_NAN_DATAPATH
8620 {
8621 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8622 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
8623 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8624 WIPHY_VENDOR_CMD_NEED_NETDEV |
8625 WIPHY_VENDOR_CMD_NEED_RUNNING,
8626 .doit = wlan_hdd_cfg80211_process_ndp_cmd
8627 },
8628#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308629 {
8630 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8631 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
8632 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8633 WIPHY_VENDOR_CMD_NEED_NETDEV |
8634 WIPHY_VENDOR_CMD_NEED_RUNNING,
8635 .doit = wlan_hdd_cfg80211_get_wakelock_stats
8636 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308637 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308638 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8639 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
8640 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8641 WIPHY_VENDOR_CMD_NEED_NETDEV |
8642 WIPHY_VENDOR_CMD_NEED_RUNNING,
8643 .doit = wlan_hdd_cfg80211_get_bus_size
8644 },
8645 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308646 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
8647 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8648 WIPHY_VENDOR_CMD_NEED_NETDEV |
8649 WIPHY_VENDOR_CMD_NEED_RUNNING,
8650 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308651 },
8652 {
8653 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8654 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
8655 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8656 WIPHY_VENDOR_CMD_NEED_NETDEV |
8657 WIPHY_VENDOR_CMD_NEED_RUNNING,
8658 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05308659 },
8660#ifdef WLAN_FEATURE_DISA
8661 {
8662 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8663 .info.subcmd =
8664 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
8665 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8666 WIPHY_VENDOR_CMD_NEED_NETDEV |
8667 WIPHY_VENDOR_CMD_NEED_RUNNING,
8668 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
8669 },
8670#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -07008671#ifdef FEATURE_WLAN_TDLS
8672 {
8673 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8674 .info.subcmd =
8675 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
8676 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8677 WIPHY_VENDOR_CMD_NEED_NETDEV |
8678 WIPHY_VENDOR_CMD_NEED_RUNNING,
8679 .doit = wlan_hdd_cfg80211_configure_tdls_mode
8680 }
8681#endif
Paul Zhang3a210c52016-12-08 10:18:12 +08008682#ifdef WLAN_UMAC_CONVERGENCE
8683 COMMON_VENDOR_COMMANDS
8684#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008685};
8686
Anurag Chouhan7c01cc42016-12-16 21:33:43 +05308687#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
8688 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
8689 defined(FEATURE_WLAN_SCAN_PNO)
8690/**
8691 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
8692 * @wiphy: pointer to wiphy
8693 * @config: pointer to config
8694 *
8695 * Return: None
8696 */
8697static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
8698 struct hdd_config *config)
8699{
8700 if (config->configPNOScanSupport) {
8701 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8702 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
8703 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
8704 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
8705 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
8706 if (config->max_sched_scan_plan_interval)
8707 wiphy->max_sched_scan_plan_interval =
8708 config->max_sched_scan_plan_interval;
8709 if (config->max_sched_scan_plan_iterations)
8710 wiphy->max_sched_scan_plan_iterations =
8711 config->max_sched_scan_plan_iterations;
8712 }
8713}
8714#else
8715static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
8716 struct hdd_config *config)
8717{
8718}
8719#endif
8720
8721
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008722/**
8723 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
8724 * @priv_size: Size of the hdd context.
8725 *
8726 * Allocate wiphy context and hdd context.
8727 *
8728 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008729 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008730hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008731{
8732 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008733 hdd_context_t *hdd_ctx;
8734
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008735 ENTER();
8736
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008737 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
8738
8739 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008740 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008741 return NULL;
8742 }
8743
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008744 hdd_ctx = wiphy_priv(wiphy);
8745
8746 hdd_ctx->wiphy = wiphy;
8747
8748 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008749}
8750
8751/*
8752 * FUNCTION: wlan_hdd_cfg80211_update_band
8753 * This function is called from the supplicant through a
8754 * private ioctl to change the band value
8755 */
8756int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
8757{
8758 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07008759 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008760
8761 ENTER();
8762
Dustin Browna30892e2016-10-12 17:28:36 -07008763 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008764
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008765 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008766 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008767
8768 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8769 struct ieee80211_supported_band *band = wiphy->bands[i];
8770
8771 channelEnabledState =
8772 cds_get_channel_state(band->channels[j].
8773 hw_value);
8774
Dustin Browna30892e2016-10-12 17:28:36 -07008775 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008776 /* 5G only */
8777#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8778 /* Enable Social channels for P2P */
8779 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8780 (band->channels[j].center_freq)
8781 && CHANNEL_STATE_ENABLE ==
8782 channelEnabledState)
8783 band->channels[j].flags &=
8784 ~IEEE80211_CHAN_DISABLED;
8785 else
8786#endif
8787 band->channels[j].flags |=
8788 IEEE80211_CHAN_DISABLED;
8789 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07008790 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008791 eCSR_BAND_24 == eBand) {
8792 /* 2G only */
8793 band->channels[j].flags |=
8794 IEEE80211_CHAN_DISABLED;
8795 continue;
8796 }
8797
Amar Singhal6842e8f2016-02-23 16:30:32 -08008798 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008799 band->channels[j].flags &=
8800 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008801 }
8802 }
8803 return 0;
8804}
8805
8806/*
8807 * FUNCTION: wlan_hdd_cfg80211_init
8808 * This function is called by hdd_wlan_startup()
8809 * during initialization.
8810 * This function is used to initialize and register wiphy structure.
8811 */
8812int wlan_hdd_cfg80211_init(struct device *dev,
8813 struct wiphy *wiphy, struct hdd_config *pCfg)
8814{
8815 int i, j;
8816 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8817
8818 ENTER();
8819
8820 /* Now bind the underlying wlan device with wiphy */
8821 set_wiphy_dev(wiphy, dev);
8822
8823 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
8824
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008825#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
8826 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008827 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008828#else
8829 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008830 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008831#endif
8832
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008833 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
8834 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
8835 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
8836#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
8837 | WIPHY_FLAG_4ADDR_STATION
8838#endif
8839 | WIPHY_FLAG_OFFCHAN_TX;
8840
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008841#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
8842 wiphy->wowlan = &wowlan_support_cfg80211_init;
8843#else
8844 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
8845 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
8846 wiphy->wowlan.pattern_min_len = 1;
8847 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
8848#endif
8849
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07008850 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008851#ifdef FEATURE_WLAN_ESE
8852 || pCfg->isEseIniFeatureEnabled
8853#endif
8854 ) {
8855 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
8856 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008857#ifdef FEATURE_WLAN_TDLS
8858 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
8859 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
8860#endif
8861
8862 wiphy->features |= NL80211_FEATURE_HT_IBSS;
8863
Naveen Rawatc77e6e72016-08-05 15:19:03 -07008864#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
8865 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
8866#endif
8867
Anurag Chouhan7c01cc42016-12-16 21:33:43 +05308868 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008869
8870#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05308871 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008872#endif
8873
8874 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
8875 driver can still register regulatory callback and
8876 it will get regulatory settings in wiphy->band[], but
8877 driver need to determine what to do with both
8878 regulatory settings */
8879
8880 wiphy->reg_notifier = hdd_reg_notifier;
8881
8882#if defined QCA_WIFI_FTM
8883}
8884#endif
8885
8886 wiphy->max_scan_ssids = MAX_SCAN_SSID;
8887
8888 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
8889
8890 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
8891
Arun Khandavallifae92942016-08-01 13:31:08 +05308892 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
8893 | BIT(NL80211_IFTYPE_ADHOC)
8894 | BIT(NL80211_IFTYPE_P2P_CLIENT)
8895 | BIT(NL80211_IFTYPE_P2P_GO)
8896 | BIT(NL80211_IFTYPE_AP)
8897 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008898
Arun Khandavallifae92942016-08-01 13:31:08 +05308899 if (pCfg->advertiseConcurrentOperation) {
8900 if (pCfg->enableMCC) {
8901 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07008902
Arun Khandavallifae92942016-08-01 13:31:08 +05308903 for (i = 0;
8904 i < ARRAY_SIZE(wlan_hdd_iface_combination);
8905 i++) {
8906 if (!pCfg->allowMCCGODiffBI)
8907 wlan_hdd_iface_combination[i].
8908 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008909 }
8910 }
8911 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +05308912 ARRAY_SIZE(wlan_hdd_iface_combination);
8913 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008914 }
8915
8916 /* Before registering we need to update the ht capabilitied based
8917 * on ini values*/
8918 if (!pCfg->ShortGI20MhzEnable) {
8919 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
8920 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008921 }
8922
8923 if (!pCfg->ShortGI40MhzEnable) {
8924 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
8925 }
8926
8927 if (!pCfg->nChannelBondingMode5GHz) {
8928 wlan_hdd_band_5_ghz.ht_cap.cap &=
8929 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
8930 }
8931
Abhishek Singhf512bf32016-05-04 16:47:46 +05308932 /*
8933 * In case of static linked driver at the time of driver unload,
8934 * module exit doesn't happens. Module cleanup helps in cleaning
8935 * of static memory.
8936 * If driver load happens statically, at the time of driver unload,
8937 * wiphy flags don't get reset because of static memory.
8938 * It's better not to store channel in static memory.
8939 */
Dustin Browna30892e2016-10-12 17:28:36 -07008940 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
8941 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05308942 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07008943 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05308944 hdd_err("Not enough memory to allocate channels");
8945 return -ENOMEM;
8946 }
Dustin Browna30892e2016-10-12 17:28:36 -07008947 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05308948 &hdd_channels_2_4_ghz[0],
8949 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +05308950 if ((hdd_is_5g_supported(pHddCtx)) &&
8951 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
8952 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
8953 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
8954 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -07008955 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
8956 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05308957 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07008958 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05308959 hdd_err("Not enough memory to allocate channels");
8960 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -07008961 bands[NL80211_BAND_2GHZ]->channels);
8962 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +05308963 return -ENOMEM;
8964 }
Dustin Browna30892e2016-10-12 17:28:36 -07008965 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05308966 &hdd_channels_5_ghz[0],
8967 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008968 }
8969
Dustin Browna30892e2016-10-12 17:28:36 -07008970 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008971
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008972 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008973 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008974
8975 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8976 struct ieee80211_supported_band *band = wiphy->bands[i];
8977
Dustin Browna30892e2016-10-12 17:28:36 -07008978 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008979 eCSR_BAND_5G == pCfg->nBandCapability) {
8980 /* 5G only */
8981#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8982 /* Enable social channels for P2P */
8983 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8984 (band->channels[j].center_freq))
8985 band->channels[j].flags &=
8986 ~IEEE80211_CHAN_DISABLED;
8987 else
8988#endif
8989 band->channels[j].flags |=
8990 IEEE80211_CHAN_DISABLED;
8991 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07008992 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008993 eCSR_BAND_24 == pCfg->nBandCapability) {
8994 /* 2G only */
8995 band->channels[j].flags |=
8996 IEEE80211_CHAN_DISABLED;
8997 continue;
8998 }
8999 }
9000 }
9001 /*Initialise the supported cipher suite details */
9002 wiphy->cipher_suites = hdd_cipher_suites;
9003 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
9004
9005 /*signal strength in mBm (100*dBm) */
9006 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
9007 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
9008
Anurag Chouhan6d760662016-02-20 16:05:43 +05309009 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009010 wiphy->n_vendor_commands =
9011 ARRAY_SIZE(hdd_wiphy_vendor_commands);
9012 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
9013
9014 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
9015 wiphy->n_vendor_events =
9016 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
9017 }
9018
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009019 if (pCfg->enableDFSMasterCap) {
9020 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
9021 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009022
9023 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
9024
9025#ifdef QCA_HT_2040_COEX
9026 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
9027#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +05309028 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
Abhishek Singh1bdb1572015-10-16 16:24:19 +05309029 hdd_add_channel_switch_support(&wiphy->flags);
9030
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009031 EXIT();
9032 return 0;
9033}
9034
Abhishek Singhf512bf32016-05-04 16:47:46 +05309035/**
Yingying Tang80e15f32016-09-27 18:23:01 +08009036 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
9037 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +05309038 *
9039 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +05309040 * memory allocated in wlan_hdd_cfg80211_init also
9041 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +05309042 *
9043 * Return: void
9044 */
9045void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
9046{
9047 int i;
9048
Dustin Browna30892e2016-10-12 17:28:36 -07009049 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05309050 if (NULL != wiphy->bands[i] &&
9051 (NULL != wiphy->bands[i]->channels)) {
9052 qdf_mem_free(wiphy->bands[i]->channels);
9053 wiphy->bands[i]->channels = NULL;
9054 }
9055 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +05309056 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +05309057}
9058
Yingying Tang80e15f32016-09-27 18:23:01 +08009059/**
9060 * wlan_hdd_update_band_cap() - update capabilities for supported bands
9061 * @hdd_ctx: HDD context
9062 *
9063 * this function will update capabilities for supported bands
9064 *
9065 * Return: void
9066 */
9067static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
9068{
9069 uint32_t val32;
9070 uint16_t val16;
9071 tSirMacHTCapabilityInfo *ht_cap_info;
9072 QDF_STATUS status;
9073
9074 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
9075 if (QDF_STATUS_SUCCESS != status) {
9076 hdd_err("could not get HT capability info");
9077 val32 = 0;
9078 }
9079 val16 = (uint16_t)val32;
9080 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
9081
9082 if (ht_cap_info->txSTBC == true) {
9083 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
9084 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
9085 IEEE80211_HT_CAP_TX_STBC;
9086 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
9087 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
9088 IEEE80211_HT_CAP_TX_STBC;
9089 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08009090
9091 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
9092 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
9093 vht_cap.vht_supported = 0;
9094 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
9095 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
9096 vht_cap.vht_supported = 0;
9097 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
9098 }
Yingying Tang80e15f32016-09-27 18:23:01 +08009099}
9100
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009101/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309102 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009103 * initialization. In wlan_hdd_cfg80211_init, only the
9104 * default values will be initialized. The final initialization
9105 * of all required members can be done here.
9106 */
Yingying Tang80e15f32016-09-27 18:23:01 +08009107void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009108{
Yingying Tang80e15f32016-09-27 18:23:01 +08009109 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
9110
9111 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009112}
9113
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08009114/**
9115 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
9116 * @cfg: hdd cfg
9117 *
9118 * this function update 11n mode in hdd cfg
9119 *
9120 * Return: void
9121 */
9122void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
9123{
9124 if (sme_is_feature_supported_by_fw(DOT11AC)) {
9125 hdd_notice("support 11ac");
9126 } else {
9127 hdd_notice("not support 11ac");
9128 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
9129 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
9130 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
9131 cfg->sap_p2p_11ac_override = 0;
9132 }
9133 }
9134}
9135
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009136/* In this function we are registering wiphy. */
9137int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
9138{
9139 ENTER();
9140 /* Register our wiphy dev with cfg80211 */
9141 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009142 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009143 return -EIO;
9144 }
9145
9146 EXIT();
9147 return 0;
9148}
9149
9150/*
9151 HDD function to update wiphy capability based on target offload status.
9152
9153 wlan_hdd_cfg80211_init() does initialization of all wiphy related
9154 capability even before downloading firmware to the target. In discrete
9155 case, host will get know certain offload capability (say sched_scan
9156 caps) only after downloading firmware to the target and target boots up.
9157 This function is used to override setting done in wlan_hdd_cfg80211_init()
9158 based on target capability.
9159 */
9160void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
9161{
9162#ifdef FEATURE_WLAN_SCAN_PNO
9163 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9164 struct hdd_config *pCfg = pHddCtx->config;
9165
9166 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
9167 * control comes here. Here just we need to clear it if firmware doesn't
9168 * have PNO support. */
9169 if (!pCfg->PnoOffload) {
9170 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
9171 wiphy->max_sched_scan_ssids = 0;
9172 wiphy->max_match_sets = 0;
9173 wiphy->max_sched_scan_ie_len = 0;
9174 }
9175#endif
9176}
9177
9178/* This function registers for all frame which supplicant is interested in */
9179void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
9180{
9181 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9182 /* Register for all P2P action, public action etc frames */
9183 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9184
9185 ENTER();
9186
Abhishek Singh7996eb72015-12-30 17:24:02 +05309187 /* Register frame indication call back */
9188 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
9189
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +05309190 /* Register for p2p ack indication */
9191 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
9192
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009193 /* Right now we are registering these frame when driver is getting
9194 initialized. Once we will move to 2.6.37 kernel, in which we have
9195 frame register ops, we will move this code as a part of that */
9196 /* GAS Initial Request */
9197 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9198 (uint8_t *) GAS_INITIAL_REQ,
9199 GAS_INITIAL_REQ_SIZE);
9200
9201 /* GAS Initial Response */
9202 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9203 (uint8_t *) GAS_INITIAL_RSP,
9204 GAS_INITIAL_RSP_SIZE);
9205
9206 /* GAS Comeback Request */
9207 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9208 (uint8_t *) GAS_COMEBACK_REQ,
9209 GAS_COMEBACK_REQ_SIZE);
9210
9211 /* GAS Comeback Response */
9212 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9213 (uint8_t *) GAS_COMEBACK_RSP,
9214 GAS_COMEBACK_RSP_SIZE);
9215
9216 /* P2P Public Action */
9217 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9218 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9219 P2P_PUBLIC_ACTION_FRAME_SIZE);
9220
9221 /* P2P Action */
9222 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9223 (uint8_t *) P2P_ACTION_FRAME,
9224 P2P_ACTION_FRAME_SIZE);
9225
9226 /* WNM BSS Transition Request frame */
9227 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9228 (uint8_t *) WNM_BSS_ACTION_FRAME,
9229 WNM_BSS_ACTION_FRAME_SIZE);
9230
9231 /* WNM-Notification */
9232 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
9233 (uint8_t *) WNM_NOTIFICATION_FRAME,
9234 WNM_NOTIFICATION_FRAME_SIZE);
9235}
9236
9237void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
9238{
9239 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9240 /* Register for all P2P action, public action etc frames */
9241 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9242
9243 ENTER();
9244
9245 /* Right now we are registering these frame when driver is getting
9246 initialized. Once we will move to 2.6.37 kernel, in which we have
9247 frame register ops, we will move this code as a part of that */
9248 /* GAS Initial Request */
9249
9250 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9251 (uint8_t *) GAS_INITIAL_REQ,
9252 GAS_INITIAL_REQ_SIZE);
9253
9254 /* GAS Initial Response */
9255 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9256 (uint8_t *) GAS_INITIAL_RSP,
9257 GAS_INITIAL_RSP_SIZE);
9258
9259 /* GAS Comeback Request */
9260 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9261 (uint8_t *) GAS_COMEBACK_REQ,
9262 GAS_COMEBACK_REQ_SIZE);
9263
9264 /* GAS Comeback Response */
9265 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9266 (uint8_t *) GAS_COMEBACK_RSP,
9267 GAS_COMEBACK_RSP_SIZE);
9268
9269 /* P2P Public Action */
9270 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9271 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9272 P2P_PUBLIC_ACTION_FRAME_SIZE);
9273
9274 /* P2P Action */
9275 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9276 (uint8_t *) P2P_ACTION_FRAME,
9277 P2P_ACTION_FRAME_SIZE);
9278
9279 /* WNM-Notification */
9280 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
9281 (uint8_t *) WNM_NOTIFICATION_FRAME,
9282 WNM_NOTIFICATION_FRAME_SIZE);
9283}
9284
9285#ifdef FEATURE_WLAN_WAPI
9286void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
9287 const uint8_t *mac_addr, const uint8_t *key,
9288 int key_Len)
9289{
9290 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9291 tCsrRoamSetKey setKey;
9292 bool isConnected = true;
9293 int status = 0;
9294 uint32_t roamId = 0xFF;
9295 uint8_t *pKeyPtr = NULL;
9296 int n = 0;
9297
Jeff Johnson46b40792016-06-29 14:03:14 -07009298 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009299 hdd_device_mode_to_string(pAdapter->device_mode),
9300 pAdapter->device_mode);
9301
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309302 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009303 setKey.keyId = key_index; /* Store Key ID */
9304 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
9305 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
9306 setKey.paeRole = 0; /* the PAE role */
9307 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05309308 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009309 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309310 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009311 }
9312 setKey.keyLength = key_Len;
9313 pKeyPtr = setKey.Key;
9314 memcpy(pKeyPtr, key, key_Len);
9315
Jeff Johnson46b40792016-06-29 14:03:14 -07009316 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009317 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -07009318 hdd_notice("WAPI KEY Data[%d]:%02x ",
9319 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009320
9321 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
9322 if (isConnected) {
9323 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9324 pAdapter->sessionId, &setKey, &roamId);
9325 }
9326 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -07009327 hdd_err("sme_roam_set_key returned ERROR status= %d",
9328 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009329 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
9330 }
9331}
9332#endif /* FEATURE_WLAN_WAPI */
9333
9334uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
9335 uint8_t eid)
9336{
9337 int left = length;
9338 uint8_t *ptr = (uint8_t *)ies_ptr;
9339 uint8_t elem_id, elem_len;
9340
9341 while (left >= 2) {
9342 elem_id = ptr[0];
9343 elem_len = ptr[1];
9344 left -= 2;
9345 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -07009346 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009347 eid, elem_len, left);
9348 return NULL;
9349 }
9350 if (elem_id == eid) {
9351 return ptr;
9352 }
9353
9354 left -= elem_len;
9355 ptr += (elem_len + 2);
9356 }
9357 return NULL;
9358}
9359
9360/*
9361 * FUNCTION: wlan_hdd_validate_operation_channel
9362 * called by wlan_hdd_cfg80211_start_bss() and
9363 * wlan_hdd_set_channel()
9364 * This function validates whether given channel is part of valid
9365 * channel list.
9366 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309367QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009368 int channel)
9369{
9370
9371 uint32_t num_ch = 0;
9372 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
9373 u32 indx = 0;
9374 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9375 uint8_t fValidChannel = false, count = 0;
9376 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
9377
9378 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
9379
9380 if (hdd_pConfig_ini->sapAllowAllChannel) {
9381 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -08009382 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07009383 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009384 fValidChannel = true;
9385 break;
9386 }
9387 }
9388 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -07009389 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309390 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009391 }
9392 } else {
9393 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
9394 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009395 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309396 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009397 }
9398 for (indx = 0; indx < num_ch; indx++) {
9399 if (channel == valid_ch[indx]) {
9400 break;
9401 }
9402 }
9403
9404 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -07009405 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309406 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009407 }
9408 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309409 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009410
9411}
9412
9413#ifdef DHCP_SERVER_OFFLOAD
9414static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
9415{
9416 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
9417 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
9418 uint8_t numEntries = 0;
9419 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
9420 uint8_t num;
9421 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309422 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009423 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -07009424 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009425 return;
9426 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009427 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
9428 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
9429 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
9430 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
9431 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
9432 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -07009433 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009434 goto end;
9435 }
9436 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009437 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009438 goto end;
9439 }
9440 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -07009441 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009442 goto end;
9443 }
9444 for (num = 0; num < numEntries; num++) {
9445 temp = srv_ip[num];
9446 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
9447 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309448 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009449 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009450 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009451 goto end;
9452 }
Jeff Johnson77848112016-06-29 14:52:06 -07009453 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009454end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309455 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009456 return;
9457}
9458#endif /* DHCP_SERVER_OFFLOAD */
9459
9460static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9461 struct net_device *dev,
9462 struct bss_parameters *params)
9463{
9464 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9465 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9466 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309467 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009468
9469 ENTER();
9470
Anurag Chouhan6d760662016-02-20 16:05:43 +05309471 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009472 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009473 return -EINVAL;
9474 }
9475
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05309476 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
9477 hdd_err("invalid session id: %d", pAdapter->sessionId);
9478 return -EINVAL;
9479 }
9480
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309481 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009482 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
9483 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -07009484 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009485 hdd_device_mode_to_string(pAdapter->device_mode),
9486 pAdapter->device_mode, params->ap_isolate);
9487
9488 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9489 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309490 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009491 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009492
Krunal Sonib4326f22016-03-10 13:05:51 -08009493 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
9494 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009495 return -EOPNOTSUPP;
9496 }
9497
9498 /* ap_isolate == -1 means that in change bss, upper layer doesn't
9499 * want to update this parameter */
9500 if (-1 != params->ap_isolate) {
9501 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
9502 !!params->ap_isolate;
9503
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309504 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009505 pAdapter->sessionId,
9506 pAdapter->sessionCtx.
9507 ap.
9508 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309509 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009510 ret = -EINVAL;
9511 }
9512 }
9513
9514 EXIT();
9515 return ret;
9516}
9517
Krunal Soni8c37e322016-02-03 16:08:37 -08009518/**
9519 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
9520 * @ndev: pointer to net device provided by supplicant
9521 * @type: type of the interface, upper layer wanted to change
9522 *
9523 * Upper layer provides the new interface mode that needs to be changed
9524 * for given net device
9525 *
9526 * Return: success or failure in terms of integer value
9527 */
9528static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009529 enum nl80211_iftype type)
9530{
Krunal Soni8c37e322016-02-03 16:08:37 -08009531 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9532 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9533 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009534 hdd_wext_state_t *wext;
9535 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309536 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009537
9538 ENTER();
9539
Krunal Soni8c37e322016-02-03 16:08:37 -08009540 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009541 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009542 return 0;
9543 }
9544
9545 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -08009546 hdd_stop_adapter(hdd_ctx, adapter, true);
9547 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009548 wdev->iftype = type;
9549 /*Check for sub-string p2p to confirm its a p2p interface */
9550 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -08009551 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009552 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009553 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -08009554 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -08009555 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009556 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -08009557 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009558 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009559 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009560 }
Krunal Soni8c37e322016-02-03 16:08:37 -08009561 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
9562 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -08009563 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
9564 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009565 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -08009566 adapter->scan_info.scanAddIE.length;
9567 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309568 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -08009569 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
9570 wext->roamProfile.phyMode =
9571 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
9572 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009573 EXIT();
9574 return status;
9575}
9576
9577static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9578 struct net_device *dev,
9579 struct bss_parameters *params)
9580{
9581 int ret;
9582
9583 cds_ssr_protect(__func__);
9584 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
9585 cds_ssr_unprotect(__func__);
9586
9587 return ret;
9588}
9589
9590/* FUNCTION: wlan_hdd_change_country_code_cd
9591 * to wait for contry code completion
9592 */
9593void *wlan_hdd_change_country_code_cb(void *pAdapter)
9594{
9595 hdd_adapter_t *call_back_pAdapter = pAdapter;
9596 complete(&call_back_pAdapter->change_country_code);
9597 return NULL;
9598}
9599
Rajeev Kumar98edb772016-01-19 12:42:19 -08009600/**
9601 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9602 * @wiphy: Pointer to the wiphy structure
9603 * @ndev: Pointer to the net device
9604 * @type: Interface type
9605 * @flags: Flags for change interface
9606 * @params: Pointer to change interface parameters
9607 *
9608 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009609 */
9610static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9611 struct net_device *ndev,
9612 enum nl80211_iftype type,
9613 u32 *flags,
9614 struct vif_params *params)
9615{
9616 struct wireless_dev *wdev;
9617 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9618 hdd_context_t *pHddCtx;
9619 tCsrRoamProfile *pRoamProfile = NULL;
9620 eCsrRoamBssType LastBSSType;
9621 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309622 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009623 int status;
9624
9625 ENTER();
9626
Anurag Chouhan6d760662016-02-20 16:05:43 +05309627 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009628 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009629 return -EINVAL;
9630 }
9631
9632 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9633 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309634 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009635 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009636
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309637 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009638 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
9639 pAdapter->sessionId, type));
9640
Jeff Johnson77848112016-06-29 14:52:06 -07009641 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009642 pAdapter->device_mode, type);
9643
Arun Khandavallifae92942016-08-01 13:31:08 +05309644 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
9645 if (status) {
9646 hdd_err("Failed to start modules");
9647 return -EINVAL;
9648 }
9649
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009650 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009651 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
9652 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009653 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009654 return -EINVAL;
9655 }
9656
9657 pConfig = pHddCtx->config;
9658 wdev = ndev->ieee80211_ptr;
9659
9660 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009661 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009662
9663 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
9664
Krunal Sonib4326f22016-03-10 13:05:51 -08009665 if ((pAdapter->device_mode == QDF_STA_MODE) ||
9666 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
9667 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
9668 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009669 hdd_wext_state_t *pWextState =
9670 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9671
9672 pRoamProfile = &pWextState->roamProfile;
9673 LastBSSType = pRoamProfile->BSSType;
9674
9675 switch (type) {
9676 case NL80211_IFTYPE_STATION:
9677 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -08009678 case NL80211_IFTYPE_ADHOC:
9679 if (type == NL80211_IFTYPE_ADHOC) {
9680 wlan_hdd_tdls_exit(pAdapter);
9681 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -07009682 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -08009683 }
9684 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
9685 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309686 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009687 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309688 if (hdd_start_adapter(pAdapter)) {
9689 hdd_err("Failed to start adapter :%d",
9690 pAdapter->device_mode);
9691 return -EINVAL;
9692 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009693 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009694 case NL80211_IFTYPE_AP:
9695 case NL80211_IFTYPE_P2P_GO:
9696 {
Jeff Johnson77848112016-06-29 14:52:06 -07009697 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009698 (type ==
9699 NL80211_IFTYPE_AP) ? "SoftAP" :
9700 "P2pGo");
9701
9702 /* Cancel any remain on channel for GO mode */
9703 if (NL80211_IFTYPE_P2P_GO == type) {
9704 wlan_hdd_cancel_existing_remain_on_channel
9705 (pAdapter);
9706 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009707
Arun Khandavallifae92942016-08-01 13:31:08 +05309708 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009709 /* De-init the adapter */
9710 hdd_deinit_adapter(pHddCtx, pAdapter, true);
9711 memset(&pAdapter->sessionCtx, 0,
9712 sizeof(pAdapter->sessionCtx));
9713 pAdapter->device_mode =
9714 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -08009715 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
9716 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009717
9718 /*
9719 * Fw will take care incase of concurrency
9720 */
9721
Krunal Sonib4326f22016-03-10 13:05:51 -08009722 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009723 && (pConfig->apRandomBssidEnabled)) {
9724 /* To meet Android requirements create a randomized
9725 MAC address of the form 02:1A:11:Fx:xx:xx */
9726 get_random_bytes(&ndev->dev_addr[3], 3);
9727 ndev->dev_addr[0] = 0x02;
9728 ndev->dev_addr[1] = 0x1A;
9729 ndev->dev_addr[2] = 0x11;
9730 ndev->dev_addr[3] |= 0xF0;
9731 memcpy(pAdapter->macAddressCurrent.
9732 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309733 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009734 pr_info("wlan: Generated HotSpot BSSID "
9735 MAC_ADDRESS_STR "\n",
9736 MAC_ADDR_ARRAY(ndev->dev_addr));
9737 }
9738
9739 hdd_set_ap_ops(pAdapter->dev);
9740
Arun Khandavallifae92942016-08-01 13:31:08 +05309741 if (hdd_start_adapter(pAdapter)) {
9742 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009743 return -EINVAL;
9744 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009745 /* Interface type changed update in wiphy structure */
9746 if (wdev) {
9747 wdev->iftype = type;
9748 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009749 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009750 return -EINVAL;
9751 }
9752 goto done;
9753 }
9754
9755 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009756 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009757 type);
9758 return -EOPNOTSUPP;
9759 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009760 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9761 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009762 switch (type) {
9763 case NL80211_IFTYPE_STATION:
9764 case NL80211_IFTYPE_P2P_CLIENT:
9765 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -08009766 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
9767 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309768 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009769 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309770 if (hdd_start_adapter(pAdapter)) {
9771 hdd_err("Failed to start adapter :%d",
9772 pAdapter->device_mode);
9773 return -EINVAL;
9774 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009775 goto done;
9776
9777 case NL80211_IFTYPE_AP:
9778 case NL80211_IFTYPE_P2P_GO:
9779 wdev->iftype = type;
9780 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009781 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009782 goto done;
9783
9784 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009785 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009786 type);
9787 return -EOPNOTSUPP;
9788 }
9789 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009790 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009791 pAdapter->device_mode);
9792 return -EOPNOTSUPP;
9793 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009794done:
9795 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009796 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009797
Jeff Johnson2ae6f712016-09-23 15:08:48 -07009798 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009799
9800 EXIT();
9801 return 0;
9802}
9803
Rajeev Kumar98edb772016-01-19 12:42:19 -08009804/**
9805 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9806 * @wiphy: Pointer to the wiphy structure
9807 * @ndev: Pointer to the net device
9808 * @type: Interface type
9809 * @flags: Flags for change interface
9810 * @params: Pointer to change interface parameters
9811 *
9812 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009813 */
9814static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9815 struct net_device *ndev,
9816 enum nl80211_iftype type,
9817 u32 *flags,
9818 struct vif_params *params)
9819{
9820 int ret;
9821
9822 cds_ssr_protect(__func__);
9823 ret =
9824 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
9825 cds_ssr_unprotect(__func__);
9826
9827 return ret;
9828}
9829
9830#ifdef FEATURE_WLAN_TDLS
9831static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
9832 int index, uint8_t match)
9833{
9834 int i;
9835 for (i = 0; i < index; i++) {
9836 if (arr[i] == match)
9837 return true;
9838 }
9839 return false;
9840}
9841#endif
9842
9843/**
9844 * __wlan_hdd_change_station() - change station
9845 * @wiphy: Pointer to the wiphy structure
9846 * @dev: Pointer to the net device.
9847 * @mac: bssid
9848 * @params: Pointer to station parameters
9849 *
9850 * Return: 0 for success, error number on failure.
9851 */
9852#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9853static int __wlan_hdd_change_station(struct wiphy *wiphy,
9854 struct net_device *dev,
9855 const uint8_t *mac,
9856 struct station_parameters *params)
9857#else
9858static int __wlan_hdd_change_station(struct wiphy *wiphy,
9859 struct net_device *dev,
9860 uint8_t *mac,
9861 struct station_parameters *params)
9862#endif
9863{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309864 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009865 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9866 hdd_context_t *pHddCtx;
9867 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +05309868 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009869#ifdef FEATURE_WLAN_TDLS
9870 tCsrStaParams StaParams = { 0 };
9871 uint8_t isBufSta = 0;
9872 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +05309873 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009874#endif
9875 int ret;
9876
9877 ENTER();
9878
Anurag Chouhan6d760662016-02-20 16:05:43 +05309879 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009880 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009881 return -EINVAL;
9882 }
9883
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309884 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009885 TRACE_CODE_HDD_CHANGE_STATION,
9886 pAdapter->sessionId, params->listen_interval));
9887
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05309888 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
9889 hdd_err("invalid session id: %d", pAdapter->sessionId);
9890 return -EINVAL;
9891 }
9892
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009893 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9894 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309895 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009896 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009897
9898 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9899
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309900 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009901
Krunal Sonib4326f22016-03-10 13:05:51 -08009902 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9903 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009904 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
9905 status =
9906 hdd_softap_change_sta_state(pAdapter,
9907 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -08009908 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009909
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309910 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009911 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009912 return -EINVAL;
9913 }
9914 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009915 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
9916 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009917#ifdef FEATURE_WLAN_TDLS
9918 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -07009919
9920 if (cds_is_sub_20_mhz_enabled()) {
9921 hdd_err("TDLS not allowed with sub 20 MHz");
9922 return -EINVAL;
9923 }
9924
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009925 StaParams.capability = params->capability;
9926 StaParams.uapsd_queues = params->uapsd_queues;
9927 StaParams.max_sp = params->max_sp;
9928
9929 /* Convert (first channel , number of channels) tuple to
9930 * the total list of channels. This goes with the assumption
9931 * that if the first channel is < 14, then the next channels
9932 * are an incremental of 1 else an incremental of 4 till the number
9933 * of channels.
9934 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009935 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009936 if (0 != params->supported_channels_len) {
9937 int i = 0, j = 0, k = 0, no_of_channels = 0;
9938 int num_unique_channels;
9939 int next;
9940 for (i = 0;
9941 i < params->supported_channels_len
9942 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
9943 int wifi_chan_index;
9944 if (!wlan_hdd_is_duplicate_channel
9945 (StaParams.supported_channels, j,
9946 params->supported_channels[i])) {
9947 StaParams.
9948 supported_channels[j] =
9949 params->
9950 supported_channels[i];
9951 } else {
9952 continue;
9953 }
9954 wifi_chan_index =
9955 ((StaParams.supported_channels[j] <=
9956 HDD_CHANNEL_14) ? 1 : 4);
9957 no_of_channels =
9958 params->supported_channels[i + 1];
9959
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009960 hdd_notice("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 -08009961 StaParams.
9962 supported_channels[j],
9963 wifi_chan_index,
9964 no_of_channels);
9965 for (k = 1; k <= no_of_channels &&
9966 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
9967 k++) {
9968 next =
9969 StaParams.
9970 supported_channels[j] +
9971 wifi_chan_index;
9972 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
9973 StaParams.
9974 supported_channels[j
9975 +
9976 1]
9977 = next;
9978 } else {
9979 continue;
9980 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009981 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009982 j + 1,
9983 StaParams.
9984 supported_channels[j +
9985 1]);
9986 j += 1;
9987 }
9988 }
9989 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009990 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009991 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009992 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009993 StaParams.
9994 supported_channels[i]);
9995 }
9996 if (MAX_CHANNEL < num_unique_channels)
9997 num_unique_channels = MAX_CHANNEL;
9998 StaParams.supported_channels_len =
9999 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010000 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010001 StaParams.supported_channels_len);
10002 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010003 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010004 params->supported_oper_classes,
10005 params->supported_oper_classes_len);
10006 StaParams.supported_oper_classes_len =
10007 params->supported_oper_classes_len;
10008
10009 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010010 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010011 params->ext_capab,
10012 sizeof(StaParams.extn_capability));
10013
10014 if (NULL != params->ht_capa) {
10015 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010016 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010017 sizeof(tSirHTCap));
10018 }
10019
10020 StaParams.supported_rates_len =
10021 params->supported_rates_len;
10022
10023 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
10024 * The supported_rates array , for all the structures propogating till Add Sta
10025 * to the firmware has to be modified , if the supplicant (ieee80211) is
10026 * modified to send more rates.
10027 */
10028
10029 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
10030 */
10031 if (StaParams.supported_rates_len >
10032 SIR_MAC_MAX_SUPP_RATES)
10033 StaParams.supported_rates_len =
10034 SIR_MAC_MAX_SUPP_RATES;
10035
10036 if (0 != StaParams.supported_rates_len) {
10037 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010038 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010039 params->supported_rates,
10040 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010041 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010042 StaParams.supported_rates_len);
10043 for (i = 0; i < StaParams.supported_rates_len;
10044 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010045 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010046 StaParams.supported_rates[i]);
10047 }
10048
10049 if (NULL != params->vht_capa) {
10050 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010051 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010052 params->vht_capa,
10053 sizeof(tSirVHTCap));
10054 }
10055
10056 if (0 != params->ext_capab_len) {
10057 /*Define A Macro : TODO Sunil */
10058 if ((1 << 4) & StaParams.extn_capability[3]) {
10059 isBufSta = 1;
10060 }
10061 /* TDLS Channel Switching Support */
10062 if ((1 << 6) & StaParams.extn_capability[3]) {
10063 isOffChannelSupported = 1;
10064 }
10065 }
10066
Nitesh Shah99934ac2016-09-05 15:54:08 +053010067 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053010068 (params->ht_capa || params->vht_capa ||
10069 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053010070 is_qos_wmm_sta = true;
10071
10072 hdd_notice("%s: TDLS Peer is QOS capable"
10073 " is_qos_wmm_sta= %d HTcapPresent = %d",
10074 __func__, is_qos_wmm_sta,
10075 StaParams.htcap_present);
10076
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010077 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053010078 &StaParams,
10079 isBufSta,
10080 isOffChannelSupported,
10081 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010082 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010083 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010084 return -EINVAL;
10085 }
10086
10087 status =
10088 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
10089 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010090 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010091 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010092 return -EINVAL;
10093 }
10094 }
10095#endif
10096 }
10097 EXIT();
10098 return ret;
10099}
10100
10101/**
10102 * wlan_hdd_change_station() - cfg80211 change station handler function
10103 * @wiphy: Pointer to the wiphy structure
10104 * @dev: Pointer to the net device.
10105 * @mac: bssid
10106 * @params: Pointer to station parameters
10107 *
10108 * This is the cfg80211 change station handler function which invokes
10109 * the internal function @__wlan_hdd_change_station with
10110 * SSR protection.
10111 *
10112 * Return: 0 for success, error number on failure.
10113 */
10114#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
10115static int wlan_hdd_change_station(struct wiphy *wiphy,
10116 struct net_device *dev,
10117 const u8 *mac,
10118 struct station_parameters *params)
10119#else
10120static int wlan_hdd_change_station(struct wiphy *wiphy,
10121 struct net_device *dev,
10122 u8 *mac,
10123 struct station_parameters *params)
10124#endif
10125{
10126 int ret;
10127
10128 cds_ssr_protect(__func__);
10129 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
10130 cds_ssr_unprotect(__func__);
10131
10132 return ret;
10133}
10134
10135/*
10136 * FUNCTION: __wlan_hdd_cfg80211_add_key
10137 * This function is used to initialize the key information
10138 */
10139static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10140 struct net_device *ndev,
10141 u8 key_index, bool pairwise,
10142 const u8 *mac_addr,
10143 struct key_params *params)
10144{
10145 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10146 tCsrRoamSetKey setKey;
10147 int status;
10148 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010149 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010150 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010151 hdd_context_t *pHddCtx;
10152 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10153
10154 ENTER();
10155
Anurag Chouhan6d760662016-02-20 16:05:43 +053010156 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010157 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010158 return -EINVAL;
10159 }
10160
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010161 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10162 hdd_err("invalid session id: %d", pAdapter->sessionId);
10163 return -EINVAL;
10164 }
10165
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010166 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010167 TRACE_CODE_HDD_CFG80211_ADD_KEY,
10168 pAdapter->sessionId, params->key_len));
10169 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10170 status = wlan_hdd_validate_context(pHddCtx);
10171
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010172 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010173 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010174
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010175 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010176 hdd_device_mode_to_string(pAdapter->device_mode),
10177 pAdapter->device_mode);
10178
10179 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010180 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010181
10182 return -EINVAL;
10183 }
10184
10185 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010186 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010187
10188 return -EINVAL;
10189 }
10190
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010191 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010192
10193 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010194 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010195 setKey.keyId = key_index;
10196 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010197 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010198
10199 switch (params->cipher) {
10200 case WLAN_CIPHER_SUITE_WEP40:
10201 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
10202 break;
10203
10204 case WLAN_CIPHER_SUITE_WEP104:
10205 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
10206 break;
10207
10208 case WLAN_CIPHER_SUITE_TKIP:
10209 {
10210 u8 *pKey = &setKey.Key[0];
10211 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
10212
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010213 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010214
10215 /*Supplicant sends the 32bytes key in this order
10216
10217 |--------------|----------|----------|
10218 | Tk1 |TX-MIC | RX Mic |
10219 |||--------------|----------|----------|
10220 <---16bytes---><--8bytes--><--8bytes-->
10221
10222 */
10223 /*Sme expects the 32 bytes key to be in the below order
10224
10225 |--------------|----------|----------|
10226 | Tk1 |RX-MIC | TX Mic |
10227 |||--------------|----------|----------|
10228 <---16bytes---><--8bytes--><--8bytes-->
10229 */
10230 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010231 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010232
10233 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010234 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010235
10236 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010237 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010238
10239 break;
10240 }
10241
10242 case WLAN_CIPHER_SUITE_CCMP:
10243 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
10244 break;
10245
10246#ifdef FEATURE_WLAN_WAPI
10247 case WLAN_CIPHER_SUITE_SMS4:
10248 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010249 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010250 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
10251 mac_addr, params->key,
10252 params->key_len);
10253 return 0;
10254 }
10255#endif
10256
10257#ifdef FEATURE_WLAN_ESE
10258 case WLAN_CIPHER_SUITE_KRK:
10259 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
10260 break;
10261#ifdef WLAN_FEATURE_ROAM_OFFLOAD
10262 case WLAN_CIPHER_SUITE_BTK:
10263 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
10264 break;
10265#endif
10266#endif
10267
10268#ifdef WLAN_FEATURE_11W
10269 case WLAN_CIPHER_SUITE_AES_CMAC:
10270 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
10271 break;
10272#endif
10273
10274 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010275 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010276 return -EOPNOTSUPP;
10277 }
10278
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010279 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010280
10281 if (!pairwise) {
10282 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010283 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010284 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010285 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010286 } else {
10287 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010288 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010289 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010290 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010291 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010292 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010293 /* if a key is already installed, block all subsequent ones */
10294 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010295 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010296 return 0;
10297 }
10298
10299 setKey.keyDirection = eSIR_TX_RX;
10300 /*Set the group key */
10301 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10302 pAdapter->sessionId, &setKey, &roamId);
10303
10304 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010305 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010306 return -EINVAL;
10307 }
10308 /*Save the keys here and call sme_roam_set_key for setting
10309 the PTK after peer joins the IBSS network */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010310 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010311 &setKey, sizeof(tCsrRoamSetKey));
10312
10313 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
10314 return status;
10315 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010316 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10317 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010318 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10319 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070010320 status = wlansap_set_key_sta(
10321 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010322 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010323 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010324 __LINE__, status);
10325 }
10326 }
10327
10328 /* Save the key in ap ctx for use on START_BASS and restart */
10329 if (pairwise ||
10330 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
10331 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010332 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010333 sizeof(tCsrRoamSetKey));
10334 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010335 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010336 sizeof(tCsrRoamSetKey));
10337
Krunal Sonib4326f22016-03-10 13:05:51 -080010338 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
10339 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010340 hdd_wext_state_t *pWextState =
10341 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10342 hdd_station_ctx_t *pHddStaCtx =
10343 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10344
10345 if (!pairwise) {
10346 /* set group key */
10347 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010348 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010349 __func__, __LINE__);
10350 hdd_perform_roam_set_key_complete(pAdapter);
10351 }
10352 }
10353
10354 pWextState->roamProfile.Keys.KeyLength[key_index] =
10355 (u8) params->key_len;
10356
10357 pWextState->roamProfile.Keys.defaultIndex = key_index;
10358
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010359 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010360 KeyMaterial[key_index][0], params->key,
10361 params->key_len);
10362
10363 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10364
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010365 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010366 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10367 setKey.keyDirection);
10368
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010369 /* The supplicant may attempt to set the PTK once pre-authentication
10370 is done. Save the key in the UMAC and include it in the ADD BSS
10371 request */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010372 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010373 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010374 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010375 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010376 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010377 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010378 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010379 return -EINVAL;
10380 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010381
10382 /* issue set key request to SME */
10383 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10384 pAdapter->sessionId, &setKey, &roamId);
10385
10386 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010387 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010388 pHddStaCtx->roam_info.roamingState =
10389 HDD_ROAM_STATE_NONE;
10390 return -EINVAL;
10391 }
10392
10393 /* in case of IBSS as there was no information available about WEP keys during
10394 * IBSS join, group key intialized with NULL key, so re-initialize group key
10395 * with correct value*/
10396 if ((eCSR_BSS_TYPE_START_IBSS ==
10397 pWextState->roamProfile.BSSType)
10398 &&
10399 !((IW_AUTH_KEY_MGMT_802_1X ==
10400 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
10401 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
10402 pHddStaCtx->conn_info.authType)
10403 )
10404 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
10405 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
10406 )
10407 ) {
10408 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010409 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010410
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010411 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010412 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10413 setKey.keyDirection);
10414
10415 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10416 pAdapter->sessionId, &setKey,
10417 &roamId);
10418
10419 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010420 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010421 pHddStaCtx->roam_info.roamingState =
10422 HDD_ROAM_STATE_NONE;
10423 return -EINVAL;
10424 }
10425 }
10426 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010427 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010428 return 0;
10429}
10430
10431static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10432 struct net_device *ndev,
10433 u8 key_index, bool pairwise,
10434 const u8 *mac_addr,
10435 struct key_params *params)
10436{
10437 int ret;
10438 cds_ssr_protect(__func__);
10439 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
10440 mac_addr, params);
10441 cds_ssr_unprotect(__func__);
10442
10443 return ret;
10444}
10445
10446/*
10447 * FUNCTION: __wlan_hdd_cfg80211_get_key
10448 * This function is used to get the key information
10449 */
10450static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10451 struct net_device *ndev,
10452 u8 key_index, bool pairwise,
10453 const u8 *mac_addr, void *cookie,
10454 void (*callback)(void *cookie,
10455 struct key_params *)
10456 )
10457{
10458 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10459 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10460 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
10461 struct key_params params;
10462
10463 ENTER();
10464
Anurag Chouhan6d760662016-02-20 16:05:43 +053010465 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010466 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010467 return -EINVAL;
10468 }
10469
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010470 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010471 hdd_device_mode_to_string(pAdapter->device_mode),
10472 pAdapter->device_mode);
10473
10474 memset(&params, 0, sizeof(params));
10475
10476 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010477 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010478 key_index);
10479 return -EINVAL;
10480 }
10481
10482 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
10483 case eCSR_ENCRYPT_TYPE_NONE:
10484 params.cipher = IW_AUTH_CIPHER_NONE;
10485 break;
10486
10487 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
10488 case eCSR_ENCRYPT_TYPE_WEP40:
10489 params.cipher = WLAN_CIPHER_SUITE_WEP40;
10490 break;
10491
10492 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
10493 case eCSR_ENCRYPT_TYPE_WEP104:
10494 params.cipher = WLAN_CIPHER_SUITE_WEP104;
10495 break;
10496
10497 case eCSR_ENCRYPT_TYPE_TKIP:
10498 params.cipher = WLAN_CIPHER_SUITE_TKIP;
10499 break;
10500
10501 case eCSR_ENCRYPT_TYPE_AES:
10502 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
10503 break;
10504
10505 default:
10506 params.cipher = IW_AUTH_CIPHER_NONE;
10507 break;
10508 }
10509
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010510 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010511 TRACE_CODE_HDD_CFG80211_GET_KEY,
10512 pAdapter->sessionId, params.cipher));
10513
10514 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
10515 params.seq_len = 0;
10516 params.seq = NULL;
10517 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
10518 callback(cookie, &params);
10519
10520 EXIT();
10521 return 0;
10522}
10523
10524static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10525 struct net_device *ndev,
10526 u8 key_index, bool pairwise,
10527 const u8 *mac_addr, void *cookie,
10528 void (*callback)(void *cookie,
10529 struct key_params *)
10530 )
10531{
10532 int ret;
10533
10534 cds_ssr_protect(__func__);
10535 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
10536 mac_addr, cookie, callback);
10537 cds_ssr_unprotect(__func__);
10538
10539 return ret;
10540}
10541
10542/**
10543 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
10544 * @wiphy: wiphy interface context
10545 * @ndev: pointer to net device
10546 * @key_index: Key index used in 802.11 frames
10547 * @unicast: true if it is unicast key
10548 * @multicast: true if it is multicast key
10549 *
10550 * This function is required for cfg80211_ops API.
10551 * It is used to delete the key information
10552 * Underlying hardware implementation does not have API to delete the
10553 * encryption key. It is automatically deleted when the peer is
10554 * removed. Hence this function currently does nothing.
10555 * Future implementation may interprete delete key operation to
10556 * replacing the key with a random junk value, effectively making it
10557 * useless.
10558 *
10559 * Return: status code, always 0.
10560 */
10561
10562static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10563 struct net_device *ndev,
10564 u8 key_index,
10565 bool pairwise, const u8 *mac_addr)
10566{
10567 EXIT();
10568 return 0;
10569}
10570
10571/**
10572 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
10573 * @wiphy: Pointer to wiphy structure.
10574 * @dev: Pointer to net_device structure.
10575 * @key_index: key index
10576 * @pairwise: pairwise
10577 * @mac_addr: mac address
10578 *
10579 * This is the cfg80211 delete key handler function which invokes
10580 * the internal function @__wlan_hdd_cfg80211_del_key with
10581 * SSR protection.
10582 *
10583 * Return: 0 for success, error number on failure.
10584 */
10585static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10586 struct net_device *dev,
10587 u8 key_index,
10588 bool pairwise, const u8 *mac_addr)
10589{
10590 int ret;
10591
10592 cds_ssr_protect(__func__);
10593 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
10594 pairwise, mac_addr);
10595 cds_ssr_unprotect(__func__);
10596
10597 return ret;
10598}
10599
10600/*
10601 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
10602 * This function is used to set the default tx key index
10603 */
10604static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10605 struct net_device *ndev,
10606 u8 key_index,
10607 bool unicast, bool multicast)
10608{
10609 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10610 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10611 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10612 hdd_context_t *pHddCtx;
10613 int status;
10614
10615 ENTER();
10616
Anurag Chouhan6d760662016-02-20 16:05:43 +053010617 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010618 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010619 return -EINVAL;
10620 }
10621
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010622 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10623 hdd_err("invalid session id: %d", pAdapter->sessionId);
10624 return -EINVAL;
10625 }
10626
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010627 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010628 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
10629 pAdapter->sessionId, key_index));
10630
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010631 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010632 hdd_device_mode_to_string(pAdapter->device_mode),
10633 pAdapter->device_mode, key_index);
10634
10635 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010636 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010637 return -EINVAL;
10638 }
10639
10640 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10641 status = wlan_hdd_validate_context(pHddCtx);
10642
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010643 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010644 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010645
Krunal Sonib4326f22016-03-10 13:05:51 -080010646 if ((pAdapter->device_mode == QDF_STA_MODE) ||
10647 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010648 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10649 pHddStaCtx->conn_info.ucEncryptionType) &&
10650 (eCSR_ENCRYPT_TYPE_AES !=
10651 pHddStaCtx->conn_info.ucEncryptionType)) {
10652 /* If default key index is not same as previous one,
10653 * then update the default key index */
10654
10655 tCsrRoamSetKey setKey;
10656 uint32_t roamId = 0xFF;
10657 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
10658
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010659 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010660
10661 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010662 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010663 setKey.keyId = key_index;
10664 setKey.keyLength = Keys->KeyLength[key_index];
10665
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010666 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010667 &Keys->KeyMaterial[key_index][0],
10668 Keys->KeyLength[key_index]);
10669
10670 setKey.keyDirection = eSIR_TX_RX;
10671
Anurag Chouhanc5548422016-02-24 18:33:27 +053010672 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010673 &pHddStaCtx->conn_info.bssId);
10674
10675 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
10676 pWextState->roamProfile.EncryptionType.
10677 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
10678 /* In the case of dynamic wep supplicant hardcodes DWEP type
10679 * to eCSR_ENCRYPT_TYPE_WEP104 even though ap is configured for
10680 * WEP-40 encryption. In this canse the key length is 5 but the
10681 * encryption type is 104 hence checking the key langht(5) and
10682 * encryption type(104) and switching encryption type to 40*/
10683 pWextState->roamProfile.EncryptionType.
10684 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10685 pWextState->roamProfile.mcEncryptionType.
10686 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10687 }
10688
10689 setKey.encType =
10690 pWextState->roamProfile.EncryptionType.
10691 encryptionType[0];
10692
10693 /* Issue set key request */
10694 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10695 pAdapter->sessionId, &setKey,
10696 &roamId);
10697
10698 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010699 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010700 status);
10701 return -EINVAL;
10702 }
10703 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010704 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010705 /* In SoftAp mode setting key direction for default mode */
10706 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10707 pWextState->roamProfile.EncryptionType.encryptionType[0])
10708 && (eCSR_ENCRYPT_TYPE_AES !=
10709 pWextState->roamProfile.EncryptionType.
10710 encryptionType[0])) {
10711 /* Saving key direction for default key index to TX default */
10712 hdd_ap_ctx_t *pAPCtx =
10713 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10714 pAPCtx->wepKey[key_index].keyDirection =
10715 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010716 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053010717 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010718 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010719 }
10720 }
10721
10722 EXIT();
10723 return status;
10724}
10725
10726static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10727 struct net_device *ndev,
10728 u8 key_index,
10729 bool unicast, bool multicast)
10730{
10731 int ret;
10732 cds_ssr_protect(__func__);
10733 ret =
10734 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
10735 multicast);
10736 cds_ssr_unprotect(__func__);
10737
10738 return ret;
10739}
10740
Abhishek Singhc9941602016-08-09 16:06:22 +053010741/*
10742 * wlan_hdd_cfg80211_get_bss :to get the bss from kernel cache.
10743 * @wiphy: wiphy pointer
10744 * @channel: channel of the BSS
10745 * @bssid: Bssid of BSS
10746 * @ssid: Ssid of the BSS
10747 * @ssid_len: ssid length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010748 *
Abhishek Singhc9941602016-08-09 16:06:22 +053010749 * Return: bss found in kernel cache
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010750 */
Abhishek Singhc9941602016-08-09 16:06:22 +053010751#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010752static
Abhishek Singhc9941602016-08-09 16:06:22 +053010753struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10754 struct ieee80211_channel *channel, const u8 *bssid,
10755 const u8 *ssid, size_t ssid_len)
10756{
10757 return cfg80211_get_bss(wiphy, channel, bssid,
10758 ssid,
10759 ssid_len,
10760 WLAN_CAPABILITY_ESS,
10761 WLAN_CAPABILITY_ESS);
10762}
10763#else
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010764static
Abhishek Singhc9941602016-08-09 16:06:22 +053010765struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10766 struct ieee80211_channel *channel, const u8 *bssid,
10767 const u8 *ssid, size_t ssid_len)
10768{
10769 return cfg80211_get_bss(wiphy, channel, bssid,
10770 ssid,
10771 ssid_len,
10772 IEEE80211_BSS_TYPE_ESS,
10773 IEEE80211_PRIVACY_ANY);
10774}
10775#endif
10776
10777
10778/*
10779 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
10780 * interface that BSS might have been lost.
10781 * @pAdapter: adaptor
10782 * @bssid: bssid which might have been lost
10783 *
10784 * Return: bss which is unlinked from kernel cache
10785 */
10786struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
10787 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010788{
10789 struct net_device *dev = pAdapter->dev;
10790 struct wireless_dev *wdev = dev->ieee80211_ptr;
10791 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010792 struct cfg80211_bss *bss = NULL;
10793
Abhishek Singhc9941602016-08-09 16:06:22 +053010794 bss = wlan_hdd_cfg80211_get_bss(wiphy, NULL, bssid,
10795 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010796 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010797 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010798 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053010799 hdd_info("cfg80211_unlink_bss called for BSSID "
10800 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010801 cfg80211_unlink_bss(wiphy, bss);
10802 }
10803 return bss;
10804}
10805
Abhishek Singhc9941602016-08-09 16:06:22 +053010806
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010807/**
10808 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
10809 * @pAdapter: Pointer to adapter
10810 * @bss_desc: Pointer to bss descriptor
10811 *
10812 * This function is used to inform the BSS details to nl80211 interface.
10813 *
10814 * Return: struct cfg80211_bss pointer
10815 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053010816struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
10817 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010818{
10819 /*
10820 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
10821 * already exists in bss data base of cfg80211 for that particular BSS
10822 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
10823 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
10824 * As of now there is no possibility to get the mgmt(probe response)
10825 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
10826 * and passing to cfg80211_inform_bss_frame.
10827 */
10828 struct net_device *dev = pAdapter->dev;
10829 struct wireless_dev *wdev = dev->ieee80211_ptr;
10830 struct wiphy *wiphy = wdev->wiphy;
10831 int chan_no = bss_desc->channelId;
10832#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10833 qcom_ie_age *qie_age = NULL;
10834 int ie_length =
10835 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
10836#else
10837 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
10838#endif
10839 const char *ie =
10840 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
10841 unsigned int freq;
10842 struct ieee80211_channel *chan;
10843 struct ieee80211_mgmt *mgmt = NULL;
10844 struct cfg80211_bss *bss_status = NULL;
10845 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
10846 int rssi = 0;
10847 hdd_context_t *pHddCtx;
10848 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010849 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010850 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010851
10852 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10853 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010854 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010855 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010856
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010857 cfg_param = pHddCtx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010858 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
10859 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010860 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010861 return NULL;
10862 }
10863
10864 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
10865
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010866 /* Android does not want the timestamp from the frame.
10867 Instead it wants a monotonic increasing value */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070010868 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010869 mgmt->u.probe_resp.timestamp =
10870 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010871
10872 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
10873 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
10874
10875#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10876 /* GPS Requirement: need age ie per entry. Using vendor specific. */
10877 /* Assuming this is the last IE, copy at the end */
10878 ie_length -= sizeof(qcom_ie_age);
10879 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
10880 qie_age->element_id = QCOM_VENDOR_IE_ID;
10881 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
10882 qie_age->oui_1 = QCOM_OUI1;
10883 qie_age->oui_2 = QCOM_OUI2;
10884 qie_age->oui_3 = QCOM_OUI3;
10885 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053010886 /*
10887 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
10888 * all bss related timestamp is in units of ms. Due to this when scan
10889 * results are sent to lowi the scan age is high.To address this,
10890 * send age in units of 1/10 ms.
10891 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010892 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053010893 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010894 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070010895 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
10896 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070010897 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
10898 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010899#endif
10900
10901 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
10902 if (bss_desc->fProbeRsp) {
10903 mgmt->frame_control |=
10904 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
10905 } else {
10906 mgmt->frame_control |=
10907 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
10908 }
10909
10910 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070010911 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010912 freq =
10913 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070010914 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010915 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070010916 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010917 freq =
10918 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070010919 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010920 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010921 hdd_err("Invalid chan_no %d", chan_no);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010922 kfree(mgmt);
10923 return NULL;
10924 }
10925
10926 chan = __ieee80211_get_channel(wiphy, freq);
10927 /* When the band is changed on the fly using the GUI, three things are done
10928 * 1. scan abort
10929 * 2. flush scan results from cache
10930 * 3. update the band with the new band user specified (refer to the
10931 * hdd_set_band_helper function) as part of the scan abort, message will be
10932 * queued to PE and we proceed with flushing and changinh the band.
10933 * PE will stop the scanning further and report back the results what ever
10934 * it had till now by calling the call back function.
10935 * if the time between update band and scandone call back is sufficient
10936 * enough the band change reflects in SME, SME validates the channels
10937 * and discards the channels correponding to previous band and calls back
10938 * with zero bss results. but if the time between band update and scan done
10939 * callback is very small then band change will not reflect in SME and SME
10940 * reports to HDD all the channels correponding to previous band.this is due
10941 * to race condition.but those channels are invalid to the new band and so
10942 * this function __ieee80211_get_channel will return NULL.Each time we
10943 * report scan result with this pointer null warning kernel trace is printed.
10944 * if the scan results contain large number of APs continuosly kernel
10945 * warning trace is printed and it will lead to apps watch dog bark.
10946 * So drop the bss and continue to next bss.
10947 */
10948 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053010949 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
10950 chan_no, freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010951 kfree(mgmt);
10952 return NULL;
10953 }
10954
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010955 /* Based on .ini configuration, raw rssi can be reported for bss.
10956 * Raw rssi is typically used for estimating power.
10957 */
10958
10959 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
10960 bss_desc->rssi;
10961
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010962 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053010963 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010964
SaidiReddy Yenuga1fa40972016-11-15 13:44:15 +053010965 hdd_log(LOG1, "BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010966 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070010967 (int)(rssi / 100),
10968 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010969
10970 bss_status =
10971 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
10972 GFP_KERNEL);
10973 kfree(mgmt);
10974 return bss_status;
10975}
10976
10977/**
10978 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
10979 * @pAdapter: Pointer to adapter
10980 * @pRoamInfo: Pointer to roam info
10981 *
10982 * This function is used to update the BSS data base of CFG8011
10983 *
10984 * Return: struct cfg80211_bss pointer
10985 */
10986struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
10987 tCsrRoamInfo *pRoamInfo)
10988{
10989 tCsrRoamConnectedProfile roamProfile;
10990 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10991 struct cfg80211_bss *bss = NULL;
10992
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010993 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
10994 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
10995
10996 if (NULL != roamProfile.pBssDesc) {
10997 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10998 roamProfile.pBssDesc);
10999
11000 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011001 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011002
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080011003 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011004 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011005 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011006 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011007 return bss;
11008}
11009/**
11010 * wlan_hdd_cfg80211_update_bss() - update bss
11011 * @wiphy: Pointer to wiphy
11012 * @pAdapter: Pointer to adapter
11013 * @scan_time: scan request timestamp
11014 *
11015 * Return: zero if success, non-zero otherwise
11016 */
11017int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
11018 hdd_adapter_t *pAdapter,
11019 uint32_t scan_time)
11020{
11021 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11022 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011023 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011024 tScanResultHandle pResult;
11025 struct cfg80211_bss *bss_status = NULL;
11026 hdd_context_t *pHddCtx;
11027 int ret;
11028
11029 ENTER();
11030
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011031 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11032 hdd_err("invalid session id: %d", pAdapter->sessionId);
11033 return -EINVAL;
11034 }
11035
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011036 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011037 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
11038 NO_SESSION, pAdapter->sessionId));
11039
11040 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11041 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011042 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011043 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011044
11045 /* start getting scan results and populate cgf80211 BSS database */
11046 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
11047
11048 /* no scan results */
11049 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011050 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053011051 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011052 }
11053
11054 pScanResult = sme_scan_result_get_first(hHal, pResult);
11055
11056 while (pScanResult) {
11057 /*
11058 * - cfg80211_inform_bss() is not updating ie field of bss
11059 * entry if entry already exists in bss data base of cfg80211
11060 * for that particular BSS ID. Using cfg80211_inform_bss_frame
11061 * to update thebss entry instead of cfg80211_inform_bss,
11062 * But this call expects mgmt packet as input. As of now
11063 * there is no possibility to get the mgmt(probe response)
11064 * frame from PE, converting bss_desc to
11065 * ieee80211_mgmt(probe response) and passing to c
11066 * fg80211_inform_bss_frame.
11067 * - Update BSS only if beacon timestamp is later than
11068 * scan request timestamp.
11069 */
11070 if ((scan_time == 0) ||
11071 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053011072 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011073 bss_status =
11074 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
11075 &pScanResult->BssDescriptor);
11076
11077 if (NULL == bss_status) {
11078 hdd_info("NULL returned by cfg80211_inform_bss_frame");
11079 } else {
11080 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011081 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011082 bss_status);
11083 }
11084 } else {
11085 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
11086 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
11087 }
11088 pScanResult = sme_scan_result_get_next(hHal, pResult);
11089 }
11090
11091 sme_scan_result_purge(hHal, pResult);
11092 /*
11093 * For SAP mode, scan is invoked by hostapd during SAP start
11094 * if hostapd is restarted, we need to flush previous scan
11095 * result so that it will reflect environment change
11096 */
Krunal Sonib4326f22016-03-10 13:05:51 -080011097 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011098#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
11099 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
11100#endif
11101 )
11102 sme_scan_flush_result(hHal);
11103
11104 EXIT();
11105 return 0;
11106}
11107
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011108/**
11109 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
11110 * @pAdapter: Pointer to adapter
11111 * @pRoamInfo: Pointer to roam info
11112 * @index: Index
11113 * @preauth: Preauth flag
11114 *
11115 * This function is used to notify the supplicant of a new PMKSA candidate.
11116 *
11117 * Return: 0 for success, non-zero for failure
11118 */
11119int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
11120 tCsrRoamInfo *pRoamInfo,
11121 int index, bool preauth)
11122{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011123 struct net_device *dev = pAdapter->dev;
11124 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
11125
11126 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011127 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011128
11129 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011130 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011131 return -EINVAL;
11132 }
11133
11134 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011135 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011136 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
11137 cfg80211_pmksa_candidate_notify(dev, index,
11138 pRoamInfo->bssid.bytes,
11139 preauth, GFP_KERNEL);
11140 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011141 return 0;
11142}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011143
11144#ifdef FEATURE_WLAN_LFR_METRICS
11145/**
11146 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
11147 * @pAdapter: Pointer to adapter
11148 * @pRoamInfo: Pointer to roam info
11149 *
11150 * 802.11r/LFR metrics reporting function to report preauth initiation
11151 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011152 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011153 */
11154#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011155QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011156 tCsrRoamInfo *pRoamInfo)
11157{
11158 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11159 union iwreq_data wrqu;
11160
11161 ENTER();
11162
11163 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011164 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011165 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011166 }
11167
11168 /* create the event */
11169 memset(&wrqu, 0, sizeof(wrqu));
11170 memset(metrics_notification, 0, sizeof(metrics_notification));
11171
11172 wrqu.data.pointer = metrics_notification;
11173 wrqu.data.length = scnprintf(metrics_notification,
11174 sizeof(metrics_notification),
11175 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
11176 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11177
11178 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11179 metrics_notification);
11180
11181 EXIT();
11182
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011183 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011184}
11185
11186/**
11187 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11188 * @pAdapter: Pointer to adapter
11189 * @pRoamInfo: Pointer to roam info
11190 * @preauth_status: Preauth status
11191 *
11192 * 802.11r/LFR metrics reporting function to report handover initiation
11193 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011194 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011195 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011196QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011197wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
11198 tCsrRoamInfo *pRoamInfo,
11199 bool preauth_status)
11200{
11201 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11202 union iwreq_data wrqu;
11203
11204 ENTER();
11205
11206 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011207 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011208 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011209 }
11210
11211 /* create the event */
11212 memset(&wrqu, 0, sizeof(wrqu));
11213 memset(metrics_notification, 0, sizeof(metrics_notification));
11214
11215 scnprintf(metrics_notification, sizeof(metrics_notification),
11216 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
11217 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11218
11219 if (1 == preauth_status)
11220 strlcat(metrics_notification, " true",
11221 sizeof(metrics_notification));
11222 else
11223 strlcat(metrics_notification, " false",
11224 sizeof(metrics_notification));
11225
11226 wrqu.data.pointer = metrics_notification;
11227 wrqu.data.length = strlen(metrics_notification);
11228
11229 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11230 metrics_notification);
11231
11232 EXIT();
11233
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011234 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011235}
11236
11237/**
11238 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11239 * @pAdapter: Pointer to adapter
11240 * @pRoamInfo: Pointer to roam info
11241 *
11242 * 802.11r/LFR metrics reporting function to report handover initiation
11243 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011244 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011245 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011246QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011247 tCsrRoamInfo *pRoamInfo)
11248{
11249 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11250 union iwreq_data wrqu;
11251
11252 ENTER();
11253
11254 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011255 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011256 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011257 }
11258
11259 /* create the event */
11260 memset(&wrqu, 0, sizeof(wrqu));
11261 memset(metrics_notification, 0, sizeof(metrics_notification));
11262
11263 wrqu.data.pointer = metrics_notification;
11264 wrqu.data.length = scnprintf(metrics_notification,
11265 sizeof(metrics_notification),
11266 "QCOM: LFR_PREAUTH_HANDOVER "
11267 MAC_ADDRESS_STR,
11268 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11269
11270 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11271 metrics_notification);
11272
11273 EXIT();
11274
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011275 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011276}
11277#endif
11278
11279/**
11280 * hdd_select_cbmode() - select channel bonding mode
11281 * @pAdapter: Pointer to adapter
11282 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011283 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011284 *
11285 * Return: none
11286 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011287void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
11288 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011289{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011290 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011291 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011292 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011293
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011294 /*
11295 * CDS api expects secondary channel for calculating
11296 * the channel params
11297 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011298 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011299 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
11300 if (operationChannel >= 1 && operationChannel <= 5)
11301 sec_ch = operationChannel + 4;
11302 else if (operationChannel >= 6 && operationChannel <= 13)
11303 sec_ch = operationChannel - 4;
11304 }
11305
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011306 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011307 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011308
11309 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011310 eHddDot11Mode hdd_dot11_mode;
11311 uint8_t iniDot11Mode =
11312 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
11313
11314 hdd_notice("Dot11Mode is %u", iniDot11Mode);
11315 switch (iniDot11Mode) {
11316 case eHDD_DOT11_MODE_AUTO:
11317 case eHDD_DOT11_MODE_11ac:
11318 case eHDD_DOT11_MODE_11ac_ONLY:
11319 if (sme_is_feature_supported_by_fw(DOT11AC))
11320 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
11321 else
11322 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11323 break;
11324 case eHDD_DOT11_MODE_11n:
11325 case eHDD_DOT11_MODE_11n_ONLY:
11326 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11327 break;
11328 default:
11329 hdd_dot11_mode = iniDot11Mode;
11330 break;
11331 }
11332 ch_info->channel_width = ch_params->ch_width;
11333 ch_info->phy_mode =
11334 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011335 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011336 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011337 hdd_info("ch_info width %d, phymode %d channel %d",
11338 ch_info->channel_width, ch_info->phy_mode,
11339 ch_info->channel);
11340 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011341}
11342
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011343/**
11344 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
11345 * @adapter: STA adapter
11346 * @roam_profile: STA roam profile
11347 *
11348 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
11349 *
11350 * Return: false if sta-sap conc is not allowed, else return true
11351 */
11352static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
11353 tCsrRoamProfile *roam_profile)
11354{
11355 hdd_context_t *hdd_ctx;
11356 hdd_adapter_t *ap_adapter;
11357 hdd_ap_ctx_t *hdd_ap_ctx;
11358 hdd_hostapd_state_t *hostapd_state;
11359 uint8_t channel = 0;
11360 QDF_STATUS status;
11361
11362 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11363 if (!hdd_ctx) {
11364 hdd_err("HDD context is NULL");
11365 return true;
11366 }
11367
11368 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
11369 /* probably no sap running, no handling required */
11370 if (ap_adapter == NULL)
11371 return true;
11372
11373 /*
11374 * sap is not in started state, so it is fine to go ahead with sta.
11375 * if sap is currently doing CAC then don't allow sta to go further.
11376 */
11377 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
11378 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
11379 return true;
11380
11381 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
11382 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
11383 return false;
11384 }
11385
11386 /*
11387 * log and return error, if we allow STA to go through, we don't
11388 * know what is going to happen better stop sta connection
11389 */
11390 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
11391 if (NULL == hdd_ap_ctx) {
11392 hdd_err("AP context not found");
11393 return false;
11394 }
11395
11396 /* sap is on non-dfs channel, nothing to handle */
11397 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
11398 hdd_info("sap is on non-dfs channel, sta is allowed");
11399 return true;
11400 }
11401 /*
11402 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053011403 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011404 */
11405 status = cds_get_channel_from_scan_result(adapter,
11406 roam_profile, &channel);
11407
Nitesh Shah59774522016-09-16 15:14:21 +053011408 /*
11409 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
11410 * channels for roaming case.
11411 */
11412 if (CDS_IS_CHANNEL_24GHZ(channel)) {
11413 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
11414 return true;
11415 }
11416
11417 /*
11418 * If channel is 0 or DFS then better to call pcl and find out the
11419 * best channel. If channel is non-dfs 5 GHz then better move SAP
11420 * to STA's channel to make scc, so we have room for 3port MCC
11421 * scenario.
11422 */
11423 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011424 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
11425 true);
11426
11427 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
11428 qdf_event_reset(&hostapd_state->qdf_event);
11429 status = wlansap_set_channel_change_with_csa(
11430 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
11431 hdd_ap_ctx->sapConfig.ch_width_orig);
11432
11433 if (QDF_STATUS_SUCCESS != status) {
11434 hdd_err("Set channel with CSA IE failed, can't allow STA");
11435 return false;
11436 }
11437
11438 /*
11439 * wait here for SAP to finish the channel switch. When channel
11440 * switch happens, SAP sends few beacons with CSA_IE. After
11441 * successfully Transmission of those beacons, it will move its
11442 * state from started to disconnected and move to new channel.
11443 * once it moves to new channel, sap again moves its state
11444 * machine from disconnected to started and set this event.
11445 * wait for 10 secs to finish this.
11446 */
11447 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
11448 if (!QDF_IS_STATUS_SUCCESS(status)) {
11449 hdd_err("wait for qdf_event failed, STA not allowed!!");
11450 return false;
11451 }
11452
11453 return true;
11454}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011455
Krunal Soni31949422016-07-29 17:17:53 -070011456/**
11457 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011458 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070011459 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011460 * @ssid_len: Length of ssid
11461 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070011462 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011463 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011464 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011465 *
11466 * This function is used to start the association process
11467 *
11468 * Return: 0 for success, non-zero for failure
11469 */
Krunal Soni31949422016-07-29 17:17:53 -070011470static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011471 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070011472 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011473 u8 operatingChannel,
11474 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011475{
11476 int status = 0;
11477 hdd_wext_state_t *pWextState;
11478 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011479 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011480 uint32_t roamId;
11481 tCsrRoamProfile *pRoamProfile;
11482 eCsrAuthType RSNAuthType;
11483 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053011484 uint8_t channel = 0;
11485 struct sir_hw_mode_params hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011486
11487 ENTER();
11488
11489 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11490 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011491 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011492
11493 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011494 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011495 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011496
11497 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011498 hdd_err("wrong SSID len");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011499 return -EINVAL;
11500 }
11501
11502 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053011503 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
11504 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011505
11506 if (pRoamProfile) {
11507 hdd_station_ctx_t *pHddStaCtx;
11508 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11509
11510 if (HDD_WMM_USER_MODE_NO_QOS ==
11511 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
11512 /*QoS not enabled in cfg file */
11513 pRoamProfile->uapsd_mask = 0;
11514 } else {
11515 /*QoS enabled, update uapsd mask from cfg file */
11516 pRoamProfile->uapsd_mask =
11517 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
11518 }
11519
11520 pRoamProfile->SSIDs.numOfSSIDs = 1;
11521 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011522 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011523 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011524 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011525 ssid, ssid_len);
11526
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011527 pRoamProfile->do_not_roam = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011528 if (bssid) {
11529 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011530 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011531 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011532 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011533 /*
11534 * Save BSSID in seperate variable as
11535 * pRoamProfile's BSSID is getting zeroed out in the
11536 * association process. In case of join failure
11537 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011538 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011539 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011540 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011541 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011542 } else if (bssid_hint) {
11543 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011544 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011545 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011546 /*
11547 * Save BSSID in a separate variable as
11548 * pRoamProfile's BSSID is getting zeroed out in the
11549 * association process. In case of join failure
11550 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011551 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011552 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011553 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011554 hdd_info("bssid_hint is given by upper layer %pM",
11555 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011556 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011557 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011558 QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011559 hdd_info("no bssid given by upper layer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011560 }
11561
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011562 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011563 pRoamProfile->SSIDs.SSIDList->SSID.length,
11564 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
11565 operatingChannel);
11566
11567 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
11568 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011569 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011570 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
11571 }
11572#ifdef FEATURE_WLAN_WAPI
11573 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011574 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011575 switch (pAdapter->wapi_info.wapiAuthMode) {
11576 case WAPI_AUTH_MODE_PSK:
11577 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011578 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011579 pAdapter->wapi_info.wapiAuthMode);
11580 pRoamProfile->AuthType.authType[0] =
11581 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
11582 break;
11583 }
11584 case WAPI_AUTH_MODE_CERT:
11585 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011586 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011587 pAdapter->wapi_info.wapiAuthMode);
11588 pRoamProfile->AuthType.authType[0] =
11589 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
11590 break;
11591 }
11592 } /* End of switch */
11593 if (pAdapter->wapi_info.wapiAuthMode ==
11594 WAPI_AUTH_MODE_PSK
11595 || pAdapter->wapi_info.wapiAuthMode ==
11596 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011597 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011598 pRoamProfile->AuthType.numEntries = 1;
11599 pRoamProfile->EncryptionType.numEntries = 1;
11600 pRoamProfile->EncryptionType.encryptionType[0] =
11601 eCSR_ENCRYPT_TYPE_WPI;
11602 pRoamProfile->mcEncryptionType.numEntries = 1;
11603 pRoamProfile->mcEncryptionType.
11604 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
11605 }
11606 }
Krunal Soni31949422016-07-29 17:17:53 -070011607#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011608#ifdef WLAN_FEATURE_GTK_OFFLOAD
11609 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080011610 if ((QDF_STA_MODE == pAdapter->device_mode) ||
11611 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011612 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
11613 sizeof(tSirGtkOffloadParams));
11614 pHddStaCtx->gtkOffloadReqParams.ulFlags =
11615 GTK_OFFLOAD_DISABLE;
11616 }
11617#endif
11618 pRoamProfile->csrPersona = pAdapter->device_mode;
11619
11620 if (operatingChannel) {
11621 pRoamProfile->ChannelInfo.ChannelList =
11622 &operatingChannel;
11623 pRoamProfile->ChannelInfo.numOfChannels = 1;
11624 } else {
11625 pRoamProfile->ChannelInfo.ChannelList = NULL;
11626 pRoamProfile->ChannelInfo.numOfChannels = 0;
11627 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011628 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011629 && operatingChannel) {
11630 /*
11631 * Need to post the IBSS power save parameters
11632 * to WMA. WMA will configure this parameters
11633 * to firmware if power save is enabled by the
11634 * firmware.
11635 */
11636 status = hdd_set_ibss_power_save_params(pAdapter);
11637
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011638 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011639 hdd_err("Set IBSS Power Save Params Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011640 return -EINVAL;
11641 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011642 pRoamProfile->ch_params.ch_width =
11643 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053011644 /*
11645 * In IBSS mode while operating in 2.4 GHz,
11646 * the device supports only 20 MHz.
11647 */
11648 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
11649 pRoamProfile->ch_params.ch_width =
11650 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011651 hdd_select_cbmode(pAdapter, operatingChannel,
11652 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011653 }
Abhishek Singh99bce862016-06-20 15:10:51 +053011654 /*
11655 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
11656 * or pmf=2 is an explicit configuration in the supplicant
11657 * configuration, drop the connection request.
11658 */
11659 if (pWextState->roamProfile.MFPEnabled &&
11660 !(pWextState->roamProfile.MFPRequired ||
11661 pWextState->roamProfile.MFPCapable)) {
11662 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
11663 pWextState->roamProfile.MFPEnabled,
11664 pWextState->roamProfile.MFPRequired,
11665 pWextState->roamProfile.MFPCapable);
11666 return -EINVAL;
11667 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011668
Krunal Soni3091bcc2016-06-23 12:28:21 -070011669 if (true == cds_is_connection_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011670 hdd_err("Connection refused: conn in progress");
11671 return -EINVAL;
11672 }
11673
Krunal Soni31949422016-07-29 17:17:53 -070011674 /*
11675 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011676 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070011677 * enhancements, the supplicant is not issuing the scan command
11678 * now. So the unicast frames which are sent from the host are
11679 * not having the additional IEs. If it is P2P CLIENT and there
11680 * is no additional IE present in roamProfile, then use the
11681 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011682 */
11683
Krunal Sonib4326f22016-03-10 13:05:51 -080011684 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011685 (!pRoamProfile->pAddIEScan)) {
11686 pRoamProfile->pAddIEScan =
11687 &pAdapter->scan_info.scanAddIE.addIEdata[0];
11688 pRoamProfile->nAddIEScanLength =
11689 pAdapter->scan_info.scanAddIE.length;
11690 }
11691 /*
11692 * When policy manager is enabled from ini file, we shouldn't
11693 * check for other concurrency rules.
11694 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070011695 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080011696 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011697 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011698 pAdapter, pRoamProfile, &roamId))
11699 return 0;
11700 }
11701
Krunal Soni3091bcc2016-06-23 12:28:21 -070011702 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011703 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
11704 pRoamProfile))) {
11705 hdd_err("sap-sta conc will fail, can't allow sta");
11706 hdd_conn_set_connection_state(pAdapter,
11707 eConnectionState_NotConnected);
11708 return -ENOMEM;
11709 }
11710
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011711 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011712 if (!sme_config) {
11713 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011714 hdd_conn_set_connection_state(pAdapter,
11715 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011716 return -ENOMEM;
11717 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011718 sme_get_config_param(pHddCtx->hHal, sme_config);
11719 /* These values are not sessionized. So, any change in these SME
11720 * configs on an older or parallel interface will affect the
11721 * cb mode. So, restoring the default INI params before starting
11722 * interfaces such as sta, cli etc.,
11723 */
11724 sme_config->csrConfig.channelBondingMode5GHz =
11725 pHddCtx->config->nChannelBondingMode5GHz;
11726 sme_config->csrConfig.channelBondingMode24GHz =
11727 pHddCtx->config->nChannelBondingMode24GHz;
11728 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011729 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053011730 /*
11731 * Change conn_state to connecting before sme_roam_connect(),
11732 * because sme_roam_connect() has a direct path to call
11733 * hdd_sme_roam_callback(), which will change the conn_state
11734 * If direct path, conn_state will be accordingly changed to
11735 * NotConnected or Associated by either
11736 * hdd_association_completion_handler() or
11737 * hdd_dis_connect_handler() in sme_RoamCallback()if
11738 * sme_RomConnect is to be queued,
11739 * Connecting state will remain until it is completed.
11740 *
11741 * If connection state is not changed, connection state will
11742 * remain in eConnectionState_NotConnected state.
11743 * In hdd_association_completion_handler, "hddDisconInProgress"
11744 * is set to true if conn state is
11745 * eConnectionState_NotConnected.
11746 * If "hddDisconInProgress" is set to true then cfg80211 layer
11747 * is not informed of connect result indication which
11748 * is an issue.
11749 */
11750 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053011751 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053011752 hdd_conn_set_connection_state(pAdapter,
11753 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011754
Komal Seelama89be8d2016-09-29 11:09:26 +053011755 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
11756 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011757 status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
11758 pAdapter->sessionId, pRoamProfile,
11759 &roamId);
11760
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011761 if ((QDF_STATUS_SUCCESS != status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080011762 (QDF_STA_MODE == pAdapter->device_mode ||
11763 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011764 hdd_err("sme_roam_connect (session %d) failed with "
11765 "status %d. -> NotConnected",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011766 pAdapter->sessionId, status);
11767 /* change back to NotAssociated */
11768 hdd_conn_set_connection_state(pAdapter,
11769 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053011770 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
11771 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011772 }
11773
11774 pRoamProfile->ChannelInfo.ChannelList = NULL;
11775 pRoamProfile->ChannelInfo.numOfChannels = 0;
11776
Nitesh Shah044fd672016-10-13 18:53:25 +053011777 if (!QDF_IS_STATUS_SUCCESS(
11778 wma_get_current_hw_mode(&hw_mode))) {
11779 hdd_err("wma_get_current_hw_mode failed");
11780 return status;
11781 }
11782
11783 if ((QDF_STA_MODE == pAdapter->device_mode)
11784 && hw_mode.dbs_cap) {
11785 cds_get_channel_from_scan_result(pAdapter,
11786 pRoamProfile, &channel);
11787 if (channel)
11788 cds_checkn_update_hw_mode_single_mac_mode
11789 (channel);
11790 }
11791
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011792 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011793 hdd_err("No valid Roam profile");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011794 return -EINVAL;
11795 }
11796 EXIT();
11797 return status;
11798}
11799
11800/**
11801 * wlan_hdd_cfg80211_set_auth_type() - set auth type
11802 * @pAdapter: Pointer to adapter
11803 * @auth_type: Auth type
11804 *
11805 * This function is used to set the authentication type (OPEN/SHARED).
11806 *
11807 * Return: 0 for success, non-zero for failure
11808 */
11809static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
11810 enum nl80211_auth_type auth_type)
11811{
11812 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11813 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11814
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011815 /*set authentication type */
11816 switch (auth_type) {
11817 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011818 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011819 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
11820 break;
11821
11822 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011823 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011824 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011825 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
11826 break;
11827
11828 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011829 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011830 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
11831 break;
11832#ifdef FEATURE_WLAN_ESE
11833 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011834 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011835 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
11836 break;
11837#endif
11838
11839 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011840 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011841 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
11842 return -EINVAL;
11843 }
11844
11845 pWextState->roamProfile.AuthType.authType[0] =
11846 pHddStaCtx->conn_info.authType;
11847 return 0;
11848}
11849
11850/**
11851 * wlan_hdd_set_akm_suite() - set key management type
11852 * @pAdapter: Pointer to adapter
11853 * @key_mgmt: Key management type
11854 *
11855 * This function is used to set the key mgmt type(PSK/8021x).
11856 *
11857 * Return: 0 for success, non-zero for failure
11858 */
11859static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
11860{
11861 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11862
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011863#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
11864#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
11865 /*set key mgmt type */
11866 switch (key_mgmt) {
11867 case WLAN_AKM_SUITE_PSK:
11868 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011869 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011870 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011871 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
11872 break;
11873
11874 case WLAN_AKM_SUITE_8021X_SHA256:
11875 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011876 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011877 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011878 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11879 break;
11880#ifdef FEATURE_WLAN_ESE
11881#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
11882#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
11883 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011884 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011885 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
11886 break;
11887#endif
11888#ifndef WLAN_AKM_SUITE_OSEN
11889#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
11890#endif
11891 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011892 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011893 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11894 break;
11895
11896 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011897 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011898 return -EINVAL;
11899
11900 }
11901 return 0;
11902}
11903
11904/**
11905 * wlan_hdd_cfg80211_set_cipher() - set encryption type
11906 * @pAdapter: Pointer to adapter
11907 * @cipher: Cipher type
11908 * @ucast: Unicast flag
11909 *
11910 * This function is used to set the encryption type
11911 * (NONE/WEP40/WEP104/TKIP/CCMP).
11912 *
11913 * Return: 0 for success, non-zero for failure
11914 */
11915static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
11916 u32 cipher, bool ucast)
11917{
11918 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11919 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11920 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11921
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011922 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080011923 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011924 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11925 } else {
11926
11927 /*set encryption method */
11928 switch (cipher) {
11929 case IW_AUTH_CIPHER_NONE:
11930 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11931 break;
11932
11933 case WLAN_CIPHER_SUITE_WEP40:
11934 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
11935 break;
11936
11937 case WLAN_CIPHER_SUITE_WEP104:
11938 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
11939 break;
11940
11941 case WLAN_CIPHER_SUITE_TKIP:
11942 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
11943 break;
11944
11945 case WLAN_CIPHER_SUITE_CCMP:
11946 encryptionType = eCSR_ENCRYPT_TYPE_AES;
11947 break;
11948#ifdef FEATURE_WLAN_WAPI
11949 case WLAN_CIPHER_SUITE_SMS4:
11950 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
11951 break;
11952#endif
11953
11954#ifdef FEATURE_WLAN_ESE
11955 case WLAN_CIPHER_SUITE_KRK:
11956 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
11957 break;
11958#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11959 case WLAN_CIPHER_SUITE_BTK:
11960 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
11961 break;
11962#endif
11963#endif
11964 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011965 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011966 return -EOPNOTSUPP;
11967 }
11968 }
11969
11970 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011971 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011972 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
11973 pWextState->roamProfile.EncryptionType.numEntries = 1;
11974 pWextState->roamProfile.EncryptionType.encryptionType[0] =
11975 encryptionType;
11976 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011977 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011978 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
11979 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
11980 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
11981 encryptionType;
11982 }
11983
11984 return 0;
11985}
11986
11987/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011988 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
11989 * @wext_state: Pointer to wext state
11990 * @gen_ie: Pointer to IE data
11991 * @len: length of IE data
11992 *
11993 * Return: 0 for success, non-zero for failure
11994 */
11995static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
11996 const uint8_t *gen_ie, uint16_t len)
11997{
11998 uint16_t cur_add_ie_len =
11999 wext_state->assocAddIE.length;
12000
12001 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12002 (wext_state->assocAddIE.length + len)) {
12003 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
12004 QDF_ASSERT(0);
12005 return -ENOMEM;
12006 }
12007 memcpy(wext_state->assocAddIE.addIEdata +
12008 cur_add_ie_len, gen_ie, len);
12009 wext_state->assocAddIE.length += len;
12010
12011 wext_state->roamProfile.pAddIEAssoc =
12012 wext_state->assocAddIE.addIEdata;
12013 wext_state->roamProfile.nAddIEAssocLength =
12014 wext_state->assocAddIE.length;
12015 return 0;
12016}
12017
12018/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012019 * wlan_hdd_cfg80211_set_ie() - set IEs
12020 * @pAdapter: Pointer to adapter
12021 * @ie: Pointer ot ie
12022 * @ie: IE length
12023 *
12024 * Return: 0 for success, non-zero for failure
12025 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012026static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012027 size_t ie_len)
12028{
12029 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12030 const uint8_t *genie = ie;
12031 uint16_t remLen = ie_len;
12032#ifdef FEATURE_WLAN_WAPI
12033 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
12034 u16 *tmp;
12035 uint16_t akmsuiteCount;
12036 int *akmlist;
12037#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012038 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012039
12040 /* clear previous assocAddIE */
12041 pWextState->assocAddIE.length = 0;
12042 pWextState->roamProfile.bWPSAssociation = false;
12043 pWextState->roamProfile.bOSENAssociation = false;
12044
12045 while (remLen >= 2) {
12046 uint16_t eLen = 0;
12047 uint8_t elementId;
12048 elementId = *genie++;
12049 eLen = *genie++;
12050 remLen -= 2;
12051
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012052 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012053
12054 switch (elementId) {
12055 case DOT11F_EID_WPA:
12056 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 -070012057 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012058 return -EINVAL;
12059 } else if (0 ==
12060 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
12061 uint16_t curAddIELen =
12062 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012063 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012064
12065 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12066 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012067 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012068 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012069 return -ENOMEM;
12070 }
12071 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
12072 memcpy(pWextState->assocAddIE.addIEdata +
12073 curAddIELen, genie - 2, eLen + 2);
12074 pWextState->assocAddIE.length += eLen + 2;
12075
12076 pWextState->roamProfile.bWPSAssociation = true;
12077 pWextState->roamProfile.pAddIEAssoc =
12078 pWextState->assocAddIE.addIEdata;
12079 pWextState->roamProfile.nAddIEAssocLength =
12080 pWextState->assocAddIE.length;
12081 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012082 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012083 memset(pWextState->WPARSNIE, 0,
12084 MAX_WPA_RSN_IE_LEN);
12085 memcpy(pWextState->WPARSNIE, genie - 2,
12086 (eLen + 2));
12087 pWextState->roamProfile.pWPAReqIE =
12088 pWextState->WPARSNIE;
12089 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
12090 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
12091 P2P_OUI_TYPE_SIZE))) {
12092 uint16_t curAddIELen =
12093 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012094 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012095
12096 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12097 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012098 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012099 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012100 return -ENOMEM;
12101 }
12102 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
12103 memcpy(pWextState->assocAddIE.addIEdata +
12104 curAddIELen, genie - 2, eLen + 2);
12105 pWextState->assocAddIE.length += eLen + 2;
12106
12107 pWextState->roamProfile.pAddIEAssoc =
12108 pWextState->assocAddIE.addIEdata;
12109 pWextState->roamProfile.nAddIEAssocLength =
12110 pWextState->assocAddIE.length;
12111 }
12112#ifdef WLAN_FEATURE_WFD
12113 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
12114 WFD_OUI_TYPE_SIZE)) &&
12115 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080012116 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012117 pAdapter->device_mode)) {
12118 uint16_t curAddIELen =
12119 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012120 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012121
12122 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12123 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012124 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012125 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012126 return -ENOMEM;
12127 }
12128 /* WFD IE is saved to Additional IE ; it should
12129 * be accumulated to handle WPS IE + P2P IE +
12130 * WFD IE */
12131 memcpy(pWextState->assocAddIE.addIEdata +
12132 curAddIELen, genie - 2, eLen + 2);
12133 pWextState->assocAddIE.length += eLen + 2;
12134
12135 pWextState->roamProfile.pAddIEAssoc =
12136 pWextState->assocAddIE.addIEdata;
12137 pWextState->roamProfile.nAddIEAssocLength =
12138 pWextState->assocAddIE.length;
12139 }
12140#endif
12141 /* Appending HS 2.0 Indication Element in Assiciation Request */
12142 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
12143 HS20_OUI_TYPE_SIZE))) {
12144 uint16_t curAddIELen =
12145 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012146 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012147
12148 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12149 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012150 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012151 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012152 return -ENOMEM;
12153 }
12154 memcpy(pWextState->assocAddIE.addIEdata +
12155 curAddIELen, genie - 2, eLen + 2);
12156 pWextState->assocAddIE.length += eLen + 2;
12157
12158 pWextState->roamProfile.pAddIEAssoc =
12159 pWextState->assocAddIE.addIEdata;
12160 pWextState->roamProfile.nAddIEAssocLength =
12161 pWextState->assocAddIE.length;
12162 }
12163 /* Appending OSEN Information Element in Assiciation Request */
12164 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
12165 OSEN_OUI_TYPE_SIZE))) {
12166 uint16_t curAddIELen =
12167 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012168 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012169
12170 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12171 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012172 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012173 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012174 return -ENOMEM;
12175 }
12176 memcpy(pWextState->assocAddIE.addIEdata +
12177 curAddIELen, genie - 2, eLen + 2);
12178 pWextState->assocAddIE.length += eLen + 2;
12179
12180 pWextState->roamProfile.bOSENAssociation = true;
12181 pWextState->roamProfile.pAddIEAssoc =
12182 pWextState->assocAddIE.addIEdata;
12183 pWextState->roamProfile.nAddIEAssocLength =
12184 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012185 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
12186 MBO_OUI_TYPE_SIZE))){
12187 hdd_info("Set MBO IE(len %d)", eLen + 2);
12188 status = wlan_hdd_add_assoc_ie(pWextState,
12189 genie - 2, eLen + 2);
12190 if (status)
12191 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012192 } else {
12193 uint16_t add_ie_len =
12194 pWextState->assocAddIE.length;
12195
12196 hdd_info("Set OSEN IE(len %d)", eLen + 2);
12197
12198 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12199 (pWextState->assocAddIE.length + eLen)) {
12200 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012201 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012202 return -ENOMEM;
12203 }
12204
12205 memcpy(pWextState->assocAddIE.addIEdata +
12206 add_ie_len, genie - 2, eLen + 2);
12207 pWextState->assocAddIE.length += eLen + 2;
12208
12209 pWextState->roamProfile.pAddIEAssoc =
12210 pWextState->assocAddIE.addIEdata;
12211 pWextState->roamProfile.nAddIEAssocLength =
12212 pWextState->assocAddIE.length;
12213 }
12214 break;
12215 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012216 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012217 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
12218 memcpy(pWextState->WPARSNIE, genie - 2,
12219 (eLen + 2));
12220 pWextState->roamProfile.pRSNReqIE =
12221 pWextState->WPARSNIE;
12222 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
12223 break;
12224 /*
12225 * Appending Extended Capabilities with Interworking bit set
12226 * in Assoc Req.
12227 *
12228 * In assoc req this EXT Cap will only be taken into account if
12229 * interworkingService bit is set to 1. Currently
12230 * driver is only interested in interworkingService capability
12231 * from supplicant. If in future any other EXT Cap info is
12232 * required from supplicat, it needs to be handled while
12233 * sending Assoc Req in LIM.
12234 */
12235 case DOT11F_EID_EXTCAP:
12236 {
12237 uint16_t curAddIELen =
12238 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012239 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012240
12241 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12242 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012243 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012244 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012245 return -ENOMEM;
12246 }
12247 memcpy(pWextState->assocAddIE.addIEdata +
12248 curAddIELen, genie - 2, eLen + 2);
12249 pWextState->assocAddIE.length += eLen + 2;
12250
12251 pWextState->roamProfile.pAddIEAssoc =
12252 pWextState->assocAddIE.addIEdata;
12253 pWextState->roamProfile.nAddIEAssocLength =
12254 pWextState->assocAddIE.length;
12255 break;
12256 }
12257#ifdef FEATURE_WLAN_WAPI
12258 case WLAN_EID_WAPI:
12259 /* Setting WAPI Mode to ON=1 */
12260 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012261 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012262 tmp = (u16 *) ie;
12263 tmp = tmp + 2; /* Skip element Id and Len, Version */
12264 akmsuiteCount = WPA_GET_LE16(tmp);
12265 tmp = tmp + 1;
12266 akmlist = (int *)(tmp);
12267 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
12268 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
12269 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012270 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012271 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012272 return -EINVAL;
12273 }
12274
12275 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012276 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012277 pAdapter->wapi_info.wapiAuthMode =
12278 WAPI_AUTH_MODE_PSK;
12279 }
12280 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012281 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012282 pAdapter->wapi_info.wapiAuthMode =
12283 WAPI_AUTH_MODE_CERT;
12284 }
12285 break;
12286#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012287 case DOT11F_EID_SUPPOPERATINGCLASSES:
12288 {
12289 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
12290 status = wlan_hdd_add_assoc_ie(pWextState,
12291 genie - 2, eLen + 2);
12292 if (status)
12293 return status;
12294 break;
12295 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012296 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012297 hdd_err("Set UNKNOWN IE %X", elementId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012298 /* when Unknown IE is received we should break and continue
12299 * to the next IE in the buffer instead we were returning
12300 * so changing this to break */
12301 break;
12302 }
12303 genie += eLen;
12304 remLen -= eLen;
12305 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012306 return 0;
12307}
12308
12309/**
12310 * hdd_is_wpaie_present() - check for WPA ie
12311 * @ie: Pointer to ie
12312 * @ie_len: Ie length
12313 *
12314 * Parse the received IE to find the WPA IE
12315 *
12316 * Return: true if wpa ie is found else false
12317 */
12318static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
12319{
12320 uint8_t eLen = 0;
12321 uint16_t remLen = ie_len;
12322 uint8_t elementId = 0;
12323
12324 while (remLen >= 2) {
12325 elementId = *ie++;
12326 eLen = *ie++;
12327 remLen -= 2;
12328 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012329 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012330 return false;
12331 }
12332 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
12333 /* OUI - 0x00 0X50 0XF2
12334 * WPA Information Element - 0x01
12335 * WPA version - 0x01
12336 */
12337 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
12338 return true;
12339 }
12340 ie += eLen;
12341 remLen -= eLen;
12342 }
12343 return false;
12344}
12345
12346/**
12347 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
12348 * @pAdapter: Pointer to adapter
12349 * @req: Pointer to security parameters
12350 *
12351 * Return: 0 for success, non-zero for failure
12352 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012353static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
12354 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012355{
12356 int status = 0;
12357 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12358 ENTER();
12359
12360 /*set wpa version */
12361 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
12362
12363 if (req->crypto.wpa_versions) {
12364 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
12365 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
12366 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
12367 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12368 }
12369 }
12370
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012371 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012372
12373 /*set authentication type */
12374 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
12375
12376 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012377 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012378 return status;
12379 }
12380
12381 /*set key mgmt type */
12382 if (req->crypto.n_akm_suites) {
12383 status =
12384 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
12385 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012386 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012387 return status;
12388 }
12389 }
12390
12391 /*set pairwise cipher type */
12392 if (req->crypto.n_ciphers_pairwise) {
12393 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
12394 req->crypto.
12395 ciphers_pairwise[0],
12396 true);
12397 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012398 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012399 return status;
12400 }
12401 } else {
12402 /*Reset previous cipher suite to none */
12403 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
12404 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012405 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012406 return status;
12407 }
12408 }
12409
12410 /*set group cipher type */
12411 status =
12412 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
12413 false);
12414
12415 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012416 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012417 return status;
12418 }
12419#ifdef WLAN_FEATURE_11W
12420 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
12421#endif
12422
12423 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
12424 if (req->ie_len) {
12425 status =
12426 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
12427 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012428 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012429 return status;
12430 }
12431 }
12432
12433 /*incase of WEP set default key information */
12434 if (req->key && req->key_len) {
12435 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
12436 || (WLAN_CIPHER_SUITE_WEP104 ==
12437 req->crypto.ciphers_pairwise[0])
12438 ) {
12439 if (IW_AUTH_KEY_MGMT_802_1X
12440 ==
12441 (pWextState->
12442 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012443 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012444 return -EOPNOTSUPP;
12445 } else {
12446 u8 key_len = req->key_len;
12447 u8 key_idx = req->key_idx;
12448
12449 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
12450 key_len)
12451 && (CSR_MAX_NUM_KEY > key_idx)
12452 ) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012453 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012454 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012455 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012456 Keys.
12457 KeyMaterial[key_idx][0],
12458 req->key, key_len);
12459 pWextState->roamProfile.Keys.
12460 KeyLength[key_idx] = (u8) key_len;
12461 pWextState->roamProfile.Keys.
12462 defaultIndex = (u8) key_idx;
12463 }
12464 }
12465 }
12466 }
12467
12468 return status;
12469}
12470
12471/**
12472 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
12473 * @pAdapter: Pointer to adapter
12474 *
12475 * This function is used to disconnect from previous connection
12476 *
12477 * Return: 0 for success, non-zero for failure
12478 */
12479static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
12480{
12481 unsigned long rc;
12482 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012483 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012484
12485 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12486
Jeff Johnson9edf9572016-10-03 15:24:49 -070012487 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053012488 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
12489 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
12490 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012491 hdd_conn_set_connection_state(pAdapter,
12492 eConnectionState_Disconnecting);
12493 /* Issue disconnect to CSR */
12494 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012495
12496 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12497 pAdapter->sessionId,
12498 eCSR_DISCONNECT_REASON_UNSPECIFIED);
12499 /*
12500 * Wait here instead of returning directly, this will block the
12501 * next connect command and allow processing of the scan for
12502 * ssid and the previous connect command in CSR. Else we might
12503 * hit some race conditions leading to SME and HDD out of sync.
12504 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012505 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012506 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
12507 } else if (0 != status) {
12508 hdd_err("csrRoamDisconnect failure, returned %d",
12509 (int)status);
12510 pHddStaCtx->staDebugState = status;
12511 result = -EINVAL;
12512 goto disconnected;
12513 }
12514
12515 rc = wait_for_completion_timeout(
12516 &pAdapter->disconnect_comp_var,
12517 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012518 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012519 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
12520 pAdapter->sessionId, pHddStaCtx->staDebugState);
12521 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012522 }
12523 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012524 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012525 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012526 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012527 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012528 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012529 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012530 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012531 }
12532 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012533disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012534 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12535 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012536}
12537
12538/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012539 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
12540 * @adapter: Pointer to the HDD adapter
12541 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070012542 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012543 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012544 * This function will start reassociation if prev_bssid is set and bssid/
12545 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012546 *
Naveen Rawat07332902016-07-27 09:13:17 -070012547 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012548 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053012549#if defined(CFG80211_CONNECT_PREV_BSSID) || \
12550 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070012551static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12552 struct cfg80211_connect_params *req,
12553 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012554{
Naveen Rawat07332902016-07-27 09:13:17 -070012555 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012556 const uint8_t *bssid = NULL;
12557 uint16_t channel = 0;
12558
12559 if (req->bssid)
12560 bssid = req->bssid;
12561 else if (req->bssid_hint)
12562 bssid = req->bssid_hint;
12563
12564 if (req->channel)
12565 channel = req->channel->hw_value;
12566 else if (req->channel_hint)
12567 channel = req->channel_hint->hw_value;
12568
12569 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070012570 reassoc = true;
12571 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012572 channel, MAC_ADDR_ARRAY(bssid));
12573 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012574 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070012575 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012576 }
Naveen Rawat07332902016-07-27 09:13:17 -070012577 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012578}
12579#else
Naveen Rawat07332902016-07-27 09:13:17 -070012580static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12581 struct cfg80211_connect_params *req,
12582 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012583{
Naveen Rawat07332902016-07-27 09:13:17 -070012584 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012585}
12586#endif
12587
12588/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012589 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
12590 * @wiphy: Pointer to wiphy
12591 * @dev: Pointer to network device
12592 * @req: Pointer to cfg80211 connect request
12593 *
12594 * This function is used to start the association process
12595 *
12596 * Return: 0 for success, non-zero for failure
12597 */
12598static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12599 struct net_device *ndev,
12600 struct cfg80211_connect_params *req)
12601{
12602 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012603 u16 channel;
12604#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
12605 const u8 *bssid_hint = req->bssid_hint;
12606#else
12607 const u8 *bssid_hint = NULL;
12608#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012609 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12610 hdd_context_t *pHddCtx;
12611
12612 ENTER();
12613
Anurag Chouhan6d760662016-02-20 16:05:43 +053012614 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012615 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012616 return -EINVAL;
12617 }
12618
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012619 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12620 hdd_err("invalid session id: %d", pAdapter->sessionId);
12621 return -EINVAL;
12622 }
12623
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012624 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012625 TRACE_CODE_HDD_CFG80211_CONNECT,
12626 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012627 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012628 hdd_device_mode_to_string(pAdapter->device_mode),
12629 pAdapter->device_mode);
12630
Krunal Sonib4326f22016-03-10 13:05:51 -080012631 if (pAdapter->device_mode != QDF_STA_MODE &&
12632 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012633 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012634 hdd_device_mode_to_string(pAdapter->device_mode),
12635 pAdapter->device_mode);
12636 return -EINVAL;
12637 }
12638
12639 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12640 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012641 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012642 return -EINVAL;
12643 }
12644
12645 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012646 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012647 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012648
Naveen Rawat07332902016-07-27 09:13:17 -070012649 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012650 return status;
12651
Agrawal Ashishf156e942016-08-04 14:54:47 +053012652 wlan_hdd_disable_roaming(pAdapter);
12653
12654 /* Try disconnecting if already in connected state */
12655 status = wlan_hdd_try_disconnect(pAdapter);
12656 if (0 > status) {
12657 hdd_err("Failed to disconnect the existing connection");
12658 return -EALREADY;
12659 }
12660
12661 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012662 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012663 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012664 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012665 pAdapter->device_mode),
12666 req->channel->hw_value, HW_MODE_20_MHZ)) {
12667 hdd_err("This concurrency combination is not allowed");
12668 return -ECONNREFUSED;
12669 }
12670 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012671 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012672 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012673 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
12674 hdd_err("This concurrency combination is not allowed");
12675 return -ECONNREFUSED;
12676 }
12677 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012678
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012679 /*initialise security parameters */
12680 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
12681
12682 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012683 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012684 return status;
12685 }
12686
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012687 if (req->channel)
12688 channel = req->channel->hw_value;
12689 else
12690 channel = 0;
12691 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
12692 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012693 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012694 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012695 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012696 return status;
12697 }
12698 EXIT();
12699 return status;
12700}
12701
12702/**
12703 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
12704 * @wiphy: Pointer to wiphy
12705 * @dev: Pointer to network device
12706 * @req: Pointer to cfg80211 connect request
12707 *
12708 * Return: 0 for success, non-zero for failure
12709 */
12710static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12711 struct net_device *ndev,
12712 struct cfg80211_connect_params *req)
12713{
12714 int ret;
12715 cds_ssr_protect(__func__);
12716 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
12717 cds_ssr_unprotect(__func__);
12718
12719 return ret;
12720}
12721
12722/**
12723 * wlan_hdd_disconnect() - hdd disconnect api
12724 * @pAdapter: Pointer to adapter
12725 * @reason: Disconnect reason code
12726 *
12727 * This function is used to issue a disconnect request to SME
12728 *
12729 * Return: 0 for success, non-zero for failure
12730 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012731static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012732{
12733 int status, result = 0;
12734 unsigned long rc;
12735 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12736 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12737
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012738 ENTER();
12739
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012740 status = wlan_hdd_validate_context(pHddCtx);
12741
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012742 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012743 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012744
12745 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012746 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012747 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
12748 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012749 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012750 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
12751 INIT_COMPLETION(pAdapter->disconnect_comp_var);
12752
12753 /*issue disconnect */
12754
12755 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12756 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053012757 /*
12758 * Wait here instead of returning directly, this will block the next
12759 * connect command and allow processing of the scan for ssid and
12760 * the previous connect command in CSR. Else we might hit some
12761 * race conditions leading to SME and HDD out of sync.
12762 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012763 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012764 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012765 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012766 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012767 (int)status);
12768 pHddStaCtx->staDebugState = status;
12769 result = -EINVAL;
12770 goto disconnected;
12771 }
12772 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
12773 msecs_to_jiffies
12774 (WLAN_WAIT_TIME_DISCONNECT));
12775
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012776 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012777 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012778 result = -ETIMEDOUT;
12779 }
12780disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012781 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12782#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
12783 /* Sending disconnect event to userspace for kernel version < 3.11
12784 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
12785 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012786 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053012787 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
12788 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012789#endif
12790
12791 return result;
12792}
12793
12794/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012795 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
12796 * @reason: ieee80211 reason code.
12797 *
12798 * This utility function helps log string conversion of reason code.
12799 *
12800 * Return: string conversion of reason code, if match found;
12801 * "Unknown" otherwise.
12802 */
12803static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
12804{
12805 switch (reason) {
12806 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
12807 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
12808 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
12809 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
12810 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
12811 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
12812 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
12813 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
12814 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
12815 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
12816 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
12817 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
12818 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
12819 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
12820 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
12821 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
12822 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
12823 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
12824 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
12825 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
12826 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
12827 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
12828 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
12829 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
12830 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
12831 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
12832 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
12833 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
12834 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
12835 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
12836 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
12837 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
12838 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
12839 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
12840 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
12841 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
12842 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
12843 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
12844 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
12845 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
12846 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
12847 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
12848 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
12849 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
12850 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
12851 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
12852 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
12853 default:
12854 return "Unknown";
12855 }
12856}
12857
12858/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012859 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12860 * @wiphy: Pointer to wiphy
12861 * @dev: Pointer to network device
12862 * @reason: Disconnect reason code
12863 *
12864 * This function is used to issue a disconnect request to SME
12865 *
12866 * Return: 0 for success, non-zero for failure
12867 */
12868static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12869 struct net_device *dev, u16 reason)
12870{
12871 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12872 int status;
12873 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12874 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12875#ifdef FEATURE_WLAN_TDLS
12876 uint8_t staIdx;
12877#endif
12878
12879 ENTER();
12880
Anurag Chouhan6d760662016-02-20 16:05:43 +053012881 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012882 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012883 return -EINVAL;
12884 }
12885
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012886 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12887 hdd_err("invalid session id: %d", pAdapter->sessionId);
12888 return -EINVAL;
12889 }
12890
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012891 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012892 TRACE_CODE_HDD_CFG80211_DISCONNECT,
12893 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012894 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012895 hdd_device_mode_to_string(pAdapter->device_mode),
12896 pAdapter->device_mode, reason);
12897
12898 status = wlan_hdd_validate_context(pHddCtx);
12899
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012900 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012901 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012902
12903 /* Issue disconnect request to SME, if station is in connected state */
12904 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
12905 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
12906 eCsrRoamDisconnectReason reasonCode =
12907 eCSR_DISCONNECT_REASON_UNSPECIFIED;
12908 hdd_scaninfo_t *pScanInfo;
12909
12910 switch (reason) {
12911 case WLAN_REASON_MIC_FAILURE:
12912 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
12913 break;
12914
12915 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
12916 case WLAN_REASON_DISASSOC_AP_BUSY:
12917 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
12918 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
12919 break;
12920
12921 case WLAN_REASON_PREV_AUTH_NOT_VALID:
12922 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
12923 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
12924 break;
12925
12926 case WLAN_REASON_DEAUTH_LEAVING:
12927 reasonCode =
12928 pHddCtx->config->
12929 gEnableDeauthToDisassocMap ?
12930 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
12931 eCSR_DISCONNECT_REASON_DEAUTH;
12932 break;
12933 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
12934 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
12935 break;
12936 default:
12937 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
12938 break;
12939 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012940 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012941 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012942 pScanInfo = &pAdapter->scan_info;
12943 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012944 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012945 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
12946 eCSR_SCAN_ABORT_DEFAULT);
12947 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053012948 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012949#ifdef FEATURE_WLAN_TDLS
12950 /* First clean up the tdls peers if any */
12951 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
12952 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
12953 pAdapter->sessionId)
12954 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
12955 uint8_t *mac;
12956 mac =
12957 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012958 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
12959 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012960 pHddCtx->tdlsConnInfo[staIdx].staId,
12961 pAdapter->sessionId,
12962 MAC_ADDR_ARRAY(mac));
12963 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
12964 (pAdapter),
12965 pAdapter->sessionId, mac);
12966 }
12967 }
12968#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012969 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012970 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012971 hdd_info("Disconnect request from user space with reason: %s",
12972 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012973 status = wlan_hdd_disconnect(pAdapter, reasonCode);
12974 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012975 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012976 return -EINVAL;
12977 }
12978 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012979 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012980 pHddStaCtx->conn_info.connState);
12981 }
12982
12983 return status;
12984}
12985
12986/**
12987 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12988 * @wiphy: Pointer to wiphy
12989 * @dev: Pointer to network device
12990 * @reason: Disconnect reason code
12991 *
12992 * Return: 0 for success, non-zero for failure
12993 */
12994static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12995 struct net_device *dev, u16 reason)
12996{
12997 int ret;
12998 cds_ssr_protect(__func__);
12999 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
13000 cds_ssr_unprotect(__func__);
13001
13002 return ret;
13003}
13004
13005/**
13006 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
13007 * @pAdapter: Pointer to adapter
13008 * @param: Pointer to IBSS parameters
13009 *
13010 * This function is used to initialize the security settings in IBSS mode
13011 *
13012 * Return: 0 for success, non-zero for failure
13013 */
13014static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
13015 struct cfg80211_ibss_params
13016 *params)
13017{
13018 int status = 0;
13019 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13020 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13021 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13022
13023 ENTER();
13024
13025 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013026 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013027 pHddStaCtx->ibss_enc_key_installed = 0;
13028
13029 if (params->ie_len && (NULL != params->ie)) {
13030 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
13031 params->ie_len, WLAN_EID_RSN)) {
13032 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13033 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13034 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
13035 tDot11fIEWPA dot11WPAIE;
13036 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13037 u8 *ie;
13038
13039 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
13040 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
13041 params->ie_len,
13042 DOT11F_EID_WPA);
13043 if (NULL != ie) {
13044 pWextState->wpaVersion =
13045 IW_AUTH_WPA_VERSION_WPA;
13046 /* Unpack the WPA IE */
13047 /* Skip past the EID byte and length byte - and four byte WiFi OUI */
13048 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
13049 &ie[2 + 4],
13050 ie[1] - 4, &dot11WPAIE);
13051 /*Extract the multicast cipher, the encType for unicast
13052 cipher for wpa-none is none */
13053 encryptionType =
13054 hdd_translate_wpa_to_csr_encryption_type
13055 (dot11WPAIE.multicast_cipher);
13056 }
13057 }
13058
13059 status =
13060 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
13061 params->ie_len);
13062
13063 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013064 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013065 return status;
13066 }
13067 }
13068
13069 pWextState->roamProfile.AuthType.authType[0] =
13070 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13071
13072 if (params->privacy) {
13073 /* Security enabled IBSS, At this time there is no information
13074 * available about the security paramters, so initialise the
13075 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
13076 * The correct security parameters will be updated later in
13077 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
13078 * set inorder enable privacy bit in beacons
13079 */
13080
13081 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
13082 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013083 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013084 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13085 pWextState->roamProfile.EncryptionType.numEntries = 1;
13086 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13087 encryptionType;
13088 return status;
13089}
13090
13091/**
13092 * __wlan_hdd_cfg80211_join_ibss() - join ibss
13093 * @wiphy: Pointer to wiphy
13094 * @dev: Pointer to network device
13095 * @param: Pointer to IBSS join parameters
13096 *
13097 * This function is used to create/join an IBSS network
13098 *
13099 * Return: 0 for success, non-zero for failure
13100 */
13101static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13102 struct net_device *dev,
13103 struct cfg80211_ibss_params *params)
13104{
13105 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13106 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13107 tCsrRoamProfile *pRoamProfile;
13108 int status;
13109 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13110 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053013111 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013112 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013113
13114 ENTER();
13115
Anurag Chouhan6d760662016-02-20 16:05:43 +053013116 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013117 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013118 return -EINVAL;
13119 }
13120
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013121 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13122 hdd_err("invalid session id: %d", pAdapter->sessionId);
13123 return -EINVAL;
13124 }
13125
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013126 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013127 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
13128 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013129 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013130 hdd_device_mode_to_string(pAdapter->device_mode),
13131 pAdapter->device_mode);
13132
13133 status = wlan_hdd_validate_context(pHddCtx);
13134
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013135 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013136 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013137
13138 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053013139 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013140 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
13141 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
13142 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13143 int indx;
13144
13145 /* Get channel number */
13146 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013147 params->
13148 chandef.
13149 chan->
13150 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013151
13152 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
13153 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013154 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013155 return -EOPNOTSUPP;
13156 }
13157
13158 for (indx = 0; indx < numChans; indx++) {
13159 if (channelNum == validChan[indx]) {
13160 break;
13161 }
13162 }
13163 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013164 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013165 return -EINVAL;
13166 }
13167 }
13168
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013169 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013170 HW_MODE_20_MHZ)) {
13171 hdd_err("This concurrency combination is not allowed");
13172 return -ECONNREFUSED;
13173 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013174
Krunal Soni3091bcc2016-06-23 12:28:21 -070013175 status = qdf_reset_connection_update();
13176 if (!QDF_IS_STATUS_SUCCESS(status))
13177 hdd_err("ERR: clear event failed");
13178
13179 status = cds_current_connections_update(pAdapter->sessionId,
13180 channelNum,
13181 SIR_UPDATE_REASON_JOIN_IBSS);
13182 if (QDF_STATUS_E_FAILURE == status) {
13183 hdd_err("ERROR: connections update failed!!");
13184 return -EINVAL;
13185 }
13186
13187 if (QDF_STATUS_SUCCESS == status) {
13188 status = qdf_wait_for_connection_update();
13189 if (!QDF_IS_STATUS_SUCCESS(status)) {
13190 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013191 return -EINVAL;
13192 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013193 }
13194
13195 /*Try disconnecting if already in connected state */
13196 status = wlan_hdd_try_disconnect(pAdapter);
13197 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013198 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013199 return -EALREADY;
13200 }
13201
13202 pRoamProfile = &pWextState->roamProfile;
13203
13204 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013205 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013206 return -EINVAL;
13207 }
13208
13209 /* enable selected protection checks in IBSS mode */
13210 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
13211
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013212 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013213 WNI_CFG_IBSS_ATIM_WIN_SIZE,
13214 pHddCtx->config->
13215 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013216 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013217 }
13218
13219 /* BSSID is provided by upper layers hence no need to AUTO generate */
13220 if (NULL != params->bssid) {
13221 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013222 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013223 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013224 return -EIO;
13225 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013226 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013227 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
13228 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013229 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013230 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013231 return -EIO;
13232 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053013233 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013234 }
13235 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
13236 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
13237 pRoamProfile->beaconInterval = params->beacon_interval;
13238 else {
13239 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013240 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013241 params->beacon_interval, pRoamProfile->beaconInterval);
13242 }
13243
13244 /* Set Channel */
13245 if (channelNum) {
13246 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013247 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013248 pRoamProfile->ChannelInfo.numOfChannels = 1;
13249 pHddStaCtx->conn_info.operationChannel = channelNum;
13250 pRoamProfile->ChannelInfo.ChannelList =
13251 &pHddStaCtx->conn_info.operationChannel;
13252 }
13253
13254 /* Initialize security parameters */
13255 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
13256 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013257 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013258 return status;
13259 }
13260
13261 /* Issue connect start */
13262 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
13263 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013264 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013265 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013266 operationChannel,
13267 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013268
13269 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013270 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013271 return status;
13272 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013273 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013274 return 0;
13275}
13276
13277/**
13278 * wlan_hdd_cfg80211_join_ibss() - join ibss
13279 * @wiphy: Pointer to wiphy
13280 * @dev: Pointer to network device
13281 * @param: Pointer to IBSS join parameters
13282 *
13283 * This function is used to create/join an IBSS network
13284 *
13285 * Return: 0 for success, non-zero for failure
13286 */
13287static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13288 struct net_device *dev,
13289 struct cfg80211_ibss_params *params)
13290{
13291 int ret = 0;
13292
13293 cds_ssr_protect(__func__);
13294 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
13295 cds_ssr_unprotect(__func__);
13296
13297 return ret;
13298}
13299
13300/**
13301 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
13302 * @wiphy: Pointer to wiphy
13303 * @dev: Pointer to network device
13304 *
13305 * This function is used to leave an IBSS network
13306 *
13307 * Return: 0 for success, non-zero for failure
13308 */
13309static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13310 struct net_device *dev)
13311{
13312 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13313 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13314 tCsrRoamProfile *pRoamProfile;
13315 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13316 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013317 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013318 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013319 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013320
13321 ENTER();
13322
Anurag Chouhan6d760662016-02-20 16:05:43 +053013323 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013324 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013325 return -EINVAL;
13326 }
13327
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013328 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13329 hdd_err("invalid session id: %d", pAdapter->sessionId);
13330 return -EINVAL;
13331 }
13332
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013333 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013334 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
13335 pAdapter->sessionId,
13336 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
13337 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013338 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013339 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013340
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013341 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013342 hdd_device_mode_to_string(pAdapter->device_mode),
13343 pAdapter->device_mode);
13344 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013345 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013346 return -EIO;
13347 }
13348
13349 pRoamProfile = &pWextState->roamProfile;
13350
13351 /* Issue disconnect only if interface type is set to IBSS */
13352 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013353 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013354 return -EINVAL;
13355 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013356 /* Clearing add IE of beacon */
13357 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
13358 sizeof(tSirMacAddr));
13359 updateIE.smeSessionId = pAdapter->sessionId;
13360 updateIE.ieBufferlength = 0;
13361 updateIE.pAdditionIEBuffer = NULL;
13362 updateIE.append = true;
13363 updateIE.notify = true;
13364 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
13365 &updateIE,
13366 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013367 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013368 }
13369
13370 /* Reset WNI_CFG_PROBE_RSP Flags */
13371 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013372
13373 /* Issue Disconnect request */
13374 INIT_COMPLETION(pAdapter->disconnect_comp_var);
13375 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13376 pAdapter->sessionId,
13377 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013378 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013379 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013380 hal_status);
13381 return -EAGAIN;
13382 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013383
13384 /* wait for mc thread to cleanup and then return to upper stack
13385 * so by the time upper layer calls the change interface, we are
13386 * all set to proceed further
13387 */
13388 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
13389 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
13390 if (!rc) {
13391 hdd_err("Failed to disconnect, timed out");
13392 return -ETIMEDOUT;
13393 }
13394
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013395 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013396 return 0;
13397}
13398
13399/**
13400 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
13401 * @wiphy: Pointer to wiphy
13402 * @dev: Pointer to network device
13403 *
13404 * This function is used to leave an IBSS network
13405 *
13406 * Return: 0 for success, non-zero for failure
13407 */
13408static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13409 struct net_device *dev)
13410{
13411 int ret = 0;
13412
13413 cds_ssr_protect(__func__);
13414 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
13415 cds_ssr_unprotect(__func__);
13416
13417 return ret;
13418}
13419
13420/**
13421 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13422 * @wiphy: Pointer to wiphy
13423 * @changed: Parameters changed
13424 *
13425 * This function is used to set the phy parameters. RTS Threshold/FRAG
13426 * Threshold/Retry Count etc.
13427 *
13428 * Return: 0 for success, non-zero for failure
13429 */
13430static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
13431 u32 changed)
13432{
13433 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13434 tHalHandle hHal = pHddCtx->hHal;
13435 int status;
13436
13437 ENTER();
13438
Anurag Chouhan6d760662016-02-20 16:05:43 +053013439 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013440 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013441 return -EINVAL;
13442 }
13443
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013444 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013445 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
13446 NO_SESSION, wiphy->rts_threshold));
13447 status = wlan_hdd_validate_context(pHddCtx);
13448
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013449 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013450 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013451
13452 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
13453 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
13454 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
13455
13456 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
13457 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013458 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013459 rts_threshold);
13460 return -EINVAL;
13461 }
13462
13463 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
13464 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013465 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013466 rts_threshold);
13467 return -EIO;
13468 }
13469
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013470 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013471 }
13472
13473 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
13474 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
13475 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
13476 wiphy->frag_threshold;
13477
13478 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
13479 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013480 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013481 frag_threshold);
13482 return -EINVAL;
13483 }
13484
13485 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
13486 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013487 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013488 frag_threshold);
13489 return -EIO;
13490 }
13491
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013492 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013493 }
13494
13495 if ((changed & WIPHY_PARAM_RETRY_SHORT)
13496 || (changed & WIPHY_PARAM_RETRY_LONG)) {
13497 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
13498 wiphy->retry_short : wiphy->retry_long;
13499
13500 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
13501 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013502 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013503 return -EINVAL;
13504 }
13505
13506 if (changed & WIPHY_PARAM_RETRY_SHORT) {
13507 if (0 != sme_cfg_set_int(hHal,
13508 WNI_CFG_LONG_RETRY_LIMIT,
13509 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013510 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013511 retry_value);
13512 return -EIO;
13513 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013514 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013515 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
13516 if (0 != sme_cfg_set_int(hHal,
13517 WNI_CFG_SHORT_RETRY_LIMIT,
13518 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013519 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013520 retry_value);
13521 return -EIO;
13522 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013523 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013524 }
13525 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013526 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013527 return 0;
13528}
13529
13530/**
13531 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13532 * @wiphy: Pointer to wiphy
13533 * @changed: Parameters changed
13534 *
13535 * Return: 0 for success, non-zero for failure
13536 */
13537static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
13538{
13539 int ret;
13540
13541 cds_ssr_protect(__func__);
13542 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
13543 cds_ssr_unprotect(__func__);
13544
13545 return ret;
13546}
13547
13548/**
13549 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
13550 * key
13551 * @wiphy: Pointer to wiphy
13552 * @dev: Pointer to network device
13553 * @key_index: Key index
13554 *
13555 * Return: 0
13556 */
13557static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13558 struct net_device *netdev,
13559 u8 key_index)
13560{
13561 ENTER();
13562 return 0;
13563}
13564
13565/**
13566 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
13567 * wlan_hdd_set_default_mgmt_key
13568 * @wiphy: pointer to wiphy
13569 * @netdev: pointer to net_device structure
13570 * @key_index: key index
13571 *
13572 * Return: 0 on success, error number on failure
13573 */
13574static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13575 struct net_device *netdev,
13576 u8 key_index)
13577{
13578 int ret;
13579
13580 cds_ssr_protect(__func__);
13581 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
13582 cds_ssr_unprotect(__func__);
13583
13584 return ret;
13585}
13586
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013587/**
13588 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
13589 * @wiphy: Pointer to wiphy
13590 * @dev: Pointer to network device
13591 * @params: Pointer to tx queue parameters
13592 *
13593 * Return: 0
13594 */
13595static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
13596 struct net_device *dev,
13597 struct ieee80211_txq_params *params)
13598{
13599 ENTER();
13600 return 0;
13601}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013602
13603/**
13604 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
13605 * @wiphy: pointer to wiphy
13606 * @netdev: pointer to net_device structure
13607 * @params: pointer to ieee80211_txq_params
13608 *
13609 * Return: 0 on success, error number on failure
13610 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013611static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
13612 struct net_device *dev,
13613 struct ieee80211_txq_params *params)
13614{
13615 int ret;
13616
13617 cds_ssr_protect(__func__);
13618 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
13619 cds_ssr_unprotect(__func__);
13620
13621 return ret;
13622}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013623
13624/**
13625 * __wlan_hdd_cfg80211_del_station() - delete station v2
13626 * @wiphy: Pointer to wiphy
13627 * @param: Pointer to delete station parameter
13628 *
13629 * Return: 0 for success, non-zero for failure
13630 */
13631static
13632int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13633 struct net_device *dev,
13634 struct tagCsrDelStaParams *pDelStaParams)
13635{
13636 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13637 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013638 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013639 hdd_hostapd_state_t *hapd_state;
13640 int status;
13641 uint8_t staId;
13642 uint8_t *mac;
13643
13644 ENTER();
13645
Anurag Chouhan6d760662016-02-20 16:05:43 +053013646 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013647 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013648 return -EINVAL;
13649 }
13650
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013651 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13652 hdd_err("invalid session id: %d", pAdapter->sessionId);
13653 return -EINVAL;
13654 }
13655
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013656 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013657 TRACE_CODE_HDD_CFG80211_DEL_STA,
13658 pAdapter->sessionId, pAdapter->device_mode));
13659
13660 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13661 status = wlan_hdd_validate_context(pHddCtx);
13662
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013663 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013664 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013665
13666 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
13667
Krunal Sonib4326f22016-03-10 13:05:51 -080013668 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
13669 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013670
13671 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
13672 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013673 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013674 return 0;
13675 }
13676
Anurag Chouhanc5548422016-02-24 18:33:27 +053013677 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013678 uint16_t i;
13679 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
13680 if ((pAdapter->aStaInfo[i].isUsed) &&
13681 (!pAdapter->aStaInfo[i].
13682 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013683 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013684 mac,
13685 pAdapter->aStaInfo[i].
13686 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013687 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013688 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13689 hdd_ipa_wlan_evt(pAdapter,
13690 pAdapter->
13691 aStaInfo[i].
13692 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013693 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013694 mac);
13695 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013696 hdd_notice("Delete STA with MAC::"
13697 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013698 MAC_ADDR_ARRAY(mac));
13699
13700 if (pHddCtx->dev_dfs_cac_status ==
13701 DFS_CAC_IN_PROGRESS)
13702 goto fn_end;
13703
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013704 qdf_event_reset(&hapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013705 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053013706 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013707 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013708 hdd_softap_sta_deauth(pAdapter,
13709 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013710 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013711 pAdapter->aStaInfo[i].
13712 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013713 qdf_status =
13714 qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013715 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013716 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013717 if (!QDF_IS_STATUS_SUCCESS(
13718 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013719 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013720 }
13721 }
13722 }
13723 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013724 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013725 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013726 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013727 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013728 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013729 hdd_notice("Skip DEL STA as this is not used::"
13730 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013731 MAC_ADDR_ARRAY(mac));
13732 return -ENOENT;
13733 }
13734
13735 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13736 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013737 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013738 }
13739
13740 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
13741 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013742 hdd_notice("Skip DEL STA as deauth is in progress::"
13743 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013744 MAC_ADDR_ARRAY(mac));
13745 return -ENOENT;
13746 }
13747
13748 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
13749
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013750 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013751 MAC_ADDR_ARRAY(mac));
13752
13753 /* Case: SAP in ACS selected DFS ch and client connected
13754 * Now Radar detected. Then if random channel is another
13755 * DFS ch then new CAC is initiated and no TX allowed.
13756 * So do not send any mgmt frames as it will timeout
13757 * during CAC.
13758 */
13759
13760 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
13761 goto fn_end;
13762
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013763 qdf_event_reset(&hapd_state->qdf_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053013764 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
13765 (pAdapter), pAdapter->sessionId,
13766 (uint8_t *)&pDelStaParams->peerMacAddr,
13767 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013768 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013769 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013770 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013771 pAdapter->aStaInfo[staId].isDeauthInProgress =
13772 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013773 hdd_notice("STA removal failed for ::"
13774 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013775 MAC_ADDR_ARRAY(mac));
13776 return -ENOENT;
13777 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053013778 qdf_status = qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013779 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013780 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013781 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013782 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013783 }
13784 }
13785 }
13786
13787fn_end:
13788 EXIT();
13789 return 0;
13790}
13791
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013792#if defined(USE_CFG80211_DEL_STA_V2)
13793/**
13794 * wlan_hdd_del_station() - delete station wrapper
13795 * @adapter: pointer to the hdd adapter
13796 *
13797 * Return: None
13798 */
13799void wlan_hdd_del_station(hdd_adapter_t *adapter)
13800{
13801 struct station_del_parameters del_sta;
13802 del_sta.mac = NULL;
13803 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
13804 del_sta.reason_code = eCsrForcedDeauthSta;
13805
13806 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
13807 &del_sta);
13808}
13809#else
13810void wlan_hdd_del_station(hdd_adapter_t *adapter)
13811{
13812 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
13813}
13814#endif
13815
13816#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013817/**
13818 * wlan_hdd_cfg80211_del_station() - delete station v2
13819 * @wiphy: Pointer to wiphy
13820 * @param: Pointer to delete station parameter
13821 *
13822 * Return: 0 for success, non-zero for failure
13823 */
13824int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13825 struct net_device *dev,
13826 struct station_del_parameters *param)
13827#else
13828/**
13829 * wlan_hdd_cfg80211_del_station() - delete station
13830 * @wiphy: Pointer to wiphy
13831 * @mac: Pointer to station mac address
13832 *
13833 * Return: 0 for success, non-zero for failure
13834 */
13835#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13836int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13837 struct net_device *dev,
13838 const uint8_t *mac)
13839#else
13840int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13841 struct net_device *dev,
13842 uint8_t *mac)
13843#endif
13844#endif
13845{
13846 int ret;
13847 struct tagCsrDelStaParams delStaParams;
13848
13849 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013850#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013851 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013852 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013853 return -EINVAL;
13854 }
13855 wlansap_populate_del_sta_params(param->mac, param->reason_code,
13856 param->subtype, &delStaParams);
13857#else
13858 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
13859 (SIR_MAC_MGMT_DEAUTH >> 4),
13860 &delStaParams);
13861#endif
13862 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
13863 cds_ssr_unprotect(__func__);
13864
13865 return ret;
13866}
13867
13868/**
13869 * __wlan_hdd_cfg80211_add_station() - add station
13870 * @wiphy: Pointer to wiphy
13871 * @mac: Pointer to station mac address
13872 * @pmksa: Pointer to add station parameter
13873 *
13874 * Return: 0 for success, non-zero for failure
13875 */
13876static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13877 struct net_device *dev,
13878 const uint8_t *mac,
13879 struct station_parameters *params)
13880{
13881 int status = -EPERM;
13882#ifdef FEATURE_WLAN_TDLS
13883 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13884 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13885 u32 mask, set;
13886
13887 ENTER();
13888
Anurag Chouhan6d760662016-02-20 16:05:43 +053013889 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013890 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013891 return -EINVAL;
13892 }
13893
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013894 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13895 hdd_err("invalid session id: %d", pAdapter->sessionId);
13896 return -EINVAL;
13897 }
13898
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013899 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013900 TRACE_CODE_HDD_CFG80211_ADD_STA,
13901 pAdapter->sessionId, params->listen_interval));
13902
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013903 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013904 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013905
13906 mask = params->sta_flags_mask;
13907
13908 set = params->sta_flags_set;
13909
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013910 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013911 MAC_ADDR_ARRAY(mac));
13912
13913 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13914 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13915 status =
13916 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
13917 }
13918 }
13919#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013920 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013921 return status;
13922}
13923
13924/**
13925 * wlan_hdd_cfg80211_add_station() - add station
13926 * @wiphy: Pointer to wiphy
13927 * @mac: Pointer to station mac address
13928 * @pmksa: Pointer to add station parameter
13929 *
13930 * Return: 0 for success, non-zero for failure
13931 */
13932#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13933static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13934 struct net_device *dev,
13935 const uint8_t *mac,
13936 struct station_parameters *params)
13937#else
13938static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13939 struct net_device *dev, uint8_t *mac,
13940 struct station_parameters *params)
13941#endif
13942{
13943 int ret;
13944
13945 cds_ssr_protect(__func__);
13946 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
13947 cds_ssr_unprotect(__func__);
13948
13949 return ret;
13950}
13951
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013952/**
13953 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
13954 * @wiphy: Pointer to wiphy
13955 * @dev: Pointer to network device
13956 * @pmksa: Pointer to set pmksa parameter
13957 *
13958 * Return: 0 for success, non-zero for failure
13959 */
13960static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13961 struct net_device *dev,
13962 struct cfg80211_pmksa *pmksa)
13963{
13964 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13965 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13966 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013967 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013968 int status;
13969 tPmkidCacheInfo pmk_id;
13970
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013971 ENTER();
13972
Anurag Chouhan6d760662016-02-20 16:05:43 +053013973 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013974 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013975 return -EINVAL;
13976 }
13977
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013978 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13979 hdd_err("invalid session id: %d", pAdapter->sessionId);
13980 return -EINVAL;
13981 }
13982
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013983 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013984 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013985 return -EINVAL;
13986 }
13987
13988 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013989 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013990 pmksa->bssid, pmksa->pmkid);
13991 return -EINVAL;
13992 }
13993
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013994 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013995 MAC_ADDR_ARRAY(pmksa->bssid));
13996
13997 status = wlan_hdd_validate_context(pHddCtx);
13998
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013999 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014000 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014001
14002 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14003
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014004 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
14005 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014006
14007 /* Add to the PMKSA ID Cache in CSR */
14008 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
14009 &pmk_id, 1, false);
14010
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014011 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014012 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
14013 pAdapter->sessionId, result));
14014
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014015 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014016 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014017}
14018
14019/**
14020 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
14021 * @wiphy: Pointer to wiphy
14022 * @dev: Pointer to network device
14023 * @pmksa: Pointer to set pmksa parameter
14024 *
14025 * Return: 0 for success, non-zero for failure
14026 */
14027static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
14028 struct net_device *dev,
14029 struct cfg80211_pmksa *pmksa)
14030{
14031 int ret;
14032
14033 cds_ssr_protect(__func__);
14034 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
14035 cds_ssr_unprotect(__func__);
14036
14037 return ret;
14038}
14039
14040/**
14041 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
14042 * @wiphy: Pointer to wiphy
14043 * @dev: Pointer to network device
14044 * @pmksa: Pointer to pmksa parameter
14045 *
14046 * Return: 0 for success, non-zero for failure
14047 */
14048static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
14049 struct net_device *dev,
14050 struct cfg80211_pmksa *pmksa)
14051{
14052 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14053 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14054 tHalHandle halHandle;
14055 int status = 0;
14056
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014057 ENTER();
14058
Anurag Chouhan6d760662016-02-20 16:05:43 +053014059 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014060 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014061 return -EINVAL;
14062 }
14063
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014064 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14065 hdd_err("invalid session id: %d", pAdapter->sessionId);
14066 return -EINVAL;
14067 }
14068
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014069 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014070 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014071 return -EINVAL;
14072 }
14073
14074 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014075 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014076 return -EINVAL;
14077 }
14078
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014079 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014080 MAC_ADDR_ARRAY(pmksa->bssid));
14081
14082 status = wlan_hdd_validate_context(pHddCtx);
14083
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014084 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014085 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014086
14087 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14088
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014089 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014090 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
14091 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014092 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014093 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014094 sme_roam_del_pmkid_from_cache(halHandle,
14095 pAdapter->sessionId, pmksa->bssid,
14096 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014097 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014098 MAC_ADDR_ARRAY(pmksa->bssid));
14099 status = -EINVAL;
14100 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014101 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014102 return status;
14103}
14104
14105/**
14106 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
14107 * @wiphy: Pointer to wiphy
14108 * @dev: Pointer to network device
14109 * @pmksa: Pointer to pmksa parameter
14110 *
14111 * Return: 0 for success, non-zero for failure
14112 */
14113static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
14114 struct net_device *dev,
14115 struct cfg80211_pmksa *pmksa)
14116{
14117 int ret;
14118
14119 cds_ssr_protect(__func__);
14120 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
14121 cds_ssr_unprotect(__func__);
14122
14123 return ret;
14124
14125}
14126
14127/**
14128 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
14129 * @wiphy: Pointer to wiphy
14130 * @dev: Pointer to network device
14131 *
14132 * Return: 0 for success, non-zero for failure
14133 */
14134static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
14135 struct net_device *dev)
14136{
14137 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14138 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14139 tHalHandle halHandle;
14140 int status = 0;
14141
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014142 ENTER();
14143
Anurag Chouhan6d760662016-02-20 16:05:43 +053014144 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014145 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014146 return -EINVAL;
14147 }
14148
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014149 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14150 hdd_err("invalid session id: %d", pAdapter->sessionId);
14151 return -EINVAL;
14152 }
14153
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014154 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014155
14156 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14157 status = wlan_hdd_validate_context(pHddCtx);
14158
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014159 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014160 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014161
14162 /* Retrieve halHandle */
14163 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14164
14165 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014166 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014167 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
14168 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014169 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014170 status = -EINVAL;
14171 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014172 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014173 return status;
14174}
14175
14176/**
14177 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
14178 * @wiphy: Pointer to wiphy
14179 * @dev: Pointer to network device
14180 *
14181 * Return: 0 for success, non-zero for failure
14182 */
14183static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
14184 struct net_device *dev)
14185{
14186 int ret;
14187
14188 cds_ssr_protect(__func__);
14189 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
14190 cds_ssr_unprotect(__func__);
14191
14192 return ret;
14193}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014194
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080014195#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014196/**
14197 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
14198 * @wiphy: Pointer to wiphy
14199 * @dev: Pointer to network device
14200 * @ftie: Pointer to fast transition ie parameter
14201 *
14202 * Return: 0 for success, non-zero for failure
14203 */
14204static int
14205__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14206 struct net_device *dev,
14207 struct cfg80211_update_ft_ies_params *ftie)
14208{
14209 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
14210 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14211 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14212 int status;
14213
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014214 ENTER();
14215
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014216 status = wlan_hdd_validate_context(hdd_ctx);
14217 if (status)
14218 return status;
14219
Anurag Chouhan6d760662016-02-20 16:05:43 +053014220 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014221 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014222 return -EINVAL;
14223 }
14224
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014225 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14226 hdd_err("invalid session id: %d", pAdapter->sessionId);
14227 return -EINVAL;
14228 }
14229
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014230 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014231 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
14232 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
14233 /* Added for debug on reception of Re-assoc Req. */
14234 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014235 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014236 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014237 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014238 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014239 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014240 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014241
14242 /* Pass the received FT IEs to SME */
14243 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
14244 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014245 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014246 return 0;
14247}
14248
14249/**
14250 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
14251 * @wiphy: Pointer to wiphy
14252 * @dev: Pointer to network device
14253 * @ftie: Pointer to fast transition ie parameter
14254 *
14255 * Return: 0 for success, non-zero for failure
14256 */
14257static int
14258wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14259 struct net_device *dev,
14260 struct cfg80211_update_ft_ies_params *ftie)
14261{
14262 int ret;
14263
14264 cds_ssr_protect(__func__);
14265 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
14266 cds_ssr_unprotect(__func__);
14267
14268 return ret;
14269}
14270#endif
14271
14272#ifdef WLAN_FEATURE_GTK_OFFLOAD
14273/**
14274 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
14275 * @callbackContext: Callback context
14276 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
14277 *
14278 * Callback rountine called upon receiving response for get offload info
14279 *
14280 * Return: none
14281 */
14282void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
14283 tpSirGtkOffloadGetInfoRspParams
14284 pGtkOffloadGetInfoRsp)
14285{
14286 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
14287 uint8_t tempReplayCounter[8];
14288 hdd_station_ctx_t *pHddStaCtx;
14289
14290 ENTER();
14291
14292 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014293 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014294 return;
14295 }
14296
14297 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014298 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014299 return;
14300 }
14301
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014302 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014303 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014304 return;
14305 }
14306
14307 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14308 /* Update replay counter */
14309 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
14310 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14311
14312 {
14313 /* changing from little to big endian since supplicant
14314 * works on big endian format
14315 */
14316 int i;
14317 uint8_t *p =
14318 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14319
14320 for (i = 0; i < 8; i++) {
14321 tempReplayCounter[7 - i] = (uint8_t) p[i];
14322 }
14323 }
14324
14325 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014326 cfg80211_gtk_rekey_notify(pAdapter->dev,
14327 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014328 tempReplayCounter, GFP_KERNEL);
14329}
14330
14331/**
14332 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14333 * @wiphy: Pointer to wiphy
14334 * @dev: Pointer to network device
14335 * @data: Pointer to rekey data
14336 *
14337 * This function is used to offload GTK rekeying job to the firmware.
14338 *
14339 * Return: 0 for success, non-zero for failure
14340 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014341static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014342int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14343 struct net_device *dev,
14344 struct cfg80211_gtk_rekey_data *data)
14345{
14346 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14347 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14348 hdd_station_ctx_t *pHddStaCtx;
14349 tHalHandle hHal;
14350 int result;
14351 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014352 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014353
14354 ENTER();
14355
Anurag Chouhan6d760662016-02-20 16:05:43 +053014356 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014357 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014358 return -EINVAL;
14359 }
14360
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014361 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14362 hdd_err("invalid session id: %d", pAdapter->sessionId);
14363 return -EINVAL;
14364 }
14365
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014366 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014367 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
14368 pAdapter->sessionId, pAdapter->device_mode));
14369
14370 result = wlan_hdd_validate_context(pHddCtx);
14371
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014372 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014373 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014374
14375 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14376 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14377 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014378 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014379 return -EAGAIN;
14380 }
14381
14382 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
14383 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
14384 NL80211_KCK_LEN);
14385 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
14386 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053014387 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014388 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014389 {
14390 /* changing from big to little endian since driver
14391 * works on little endian format
14392 */
14393 uint8_t *p =
14394 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
14395 ullKeyReplayCounter;
14396 int i;
14397
14398 for (i = 0; i < 8; i++) {
14399 p[7 - i] = data->replay_ctr[i];
14400 }
14401 }
14402
14403 if (true == pHddCtx->hdd_wlan_suspended) {
14404 /* if wlan is suspended, enable GTK offload directly from here */
14405 memcpy(&hddGtkOffloadReqParams,
14406 &pHddStaCtx->gtkOffloadReqParams,
14407 sizeof(tSirGtkOffloadParams));
14408 status =
14409 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
14410 pAdapter->sessionId);
14411
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014412 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014413 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014414 status);
14415 return -EINVAL;
14416 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014417 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014418 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014419 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014420 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014421 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014422 return result;
14423}
14424
14425/**
14426 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14427 * @wiphy: Pointer to wiphy
14428 * @dev: Pointer to network device
14429 * @data: Pointer to rekey data
14430 *
14431 * This function is used to offload GTK rekeying job to the firmware.
14432 *
14433 * Return: 0 for success, non-zero for failure
14434 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014435static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014436int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14437 struct net_device *dev,
14438 struct cfg80211_gtk_rekey_data *data)
14439{
14440 int ret;
14441
14442 cds_ssr_protect(__func__);
14443 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
14444 cds_ssr_unprotect(__func__);
14445
14446 return ret;
14447}
14448#endif /*WLAN_FEATURE_GTK_OFFLOAD */
14449
14450/**
14451 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
14452 * @wiphy: Pointer to wiphy
14453 * @dev: Pointer to network device
14454 * @param: Pointer to access control parameter
14455 *
14456 * Return: 0 for success, non-zero for failure
14457 */
14458static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14459 struct net_device *dev,
14460 const struct cfg80211_acl_data *params)
14461{
14462 int i;
14463 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14464 hdd_hostapd_state_t *pHostapdState;
14465 tsap_Config_t *pConfig;
14466 v_CONTEXT_t p_cds_context = NULL;
14467 hdd_context_t *pHddCtx;
14468 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014469 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014470
14471 ENTER();
14472
Anurag Chouhan6d760662016-02-20 16:05:43 +053014473 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014474 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014475 return -EINVAL;
14476 }
14477
14478 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014479 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014480 return -EINVAL;
14481 }
14482
14483 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14484 status = wlan_hdd_validate_context(pHddCtx);
14485
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014486 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014487 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014488
14489 p_cds_context = pHddCtx->pcds_context;
14490 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14491
14492 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014493 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014494 return -EINVAL;
14495 }
14496
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014497 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014498 params->n_acl_entries);
14499
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014500 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014501 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
14502 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080014503 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014504 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
14505
14506 /* default value */
14507 pConfig->num_accept_mac = 0;
14508 pConfig->num_deny_mac = 0;
14509
14510 /**
14511 * access control policy
14512 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
14513 * listed in hostapd.deny file.
14514 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
14515 * listed in hostapd.accept file.
14516 */
14517 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
14518 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
14519 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
14520 params->acl_policy) {
14521 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
14522 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014523 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014524 params->acl_policy);
14525 return -ENOTSUPP;
14526 }
14527
14528 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
14529 pConfig->num_accept_mac = params->n_acl_entries;
14530 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014531 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
14532 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014533 MAC_ADDR_ARRAY(
14534 params->mac_addrs[i].addr));
14535
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014536 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014537 params->mac_addrs[i].addr,
14538 sizeof(qcmacaddr));
14539 }
14540 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
14541 pConfig->num_deny_mac = params->n_acl_entries;
14542 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014543 hdd_notice("** Add ACL MAC entry %i in BlackList :"
14544 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014545 MAC_ADDR_ARRAY(
14546 params->mac_addrs[i].addr));
14547
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014548 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014549 params->mac_addrs[i].addr,
14550 sizeof(qcmacaddr));
14551 }
14552 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070014553 qdf_status = wlansap_set_mac_acl(
14554 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014555 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014556 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014557 return -EINVAL;
14558 }
14559 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014560 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014561 hdd_device_mode_to_string(pAdapter->device_mode),
14562 pAdapter->device_mode);
14563 return -EINVAL;
14564 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014565 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014566 return 0;
14567}
14568
14569/**
14570 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
14571 * __wlan_hdd_cfg80211_set_mac_acl
14572 * @wiphy: pointer to wiphy structure
14573 * @dev: pointer to net_device
14574 * @params: pointer to cfg80211_acl_data
14575 *
14576 * Return; 0 on success, error number otherwise
14577 */
14578static int
14579wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14580 struct net_device *dev,
14581 const struct cfg80211_acl_data *params)
14582{
14583 int ret;
14584
14585 cds_ssr_protect(__func__);
14586 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
14587 cds_ssr_unprotect(__func__);
14588
14589 return ret;
14590}
14591
14592#ifdef WLAN_NL80211_TESTMODE
14593#ifdef FEATURE_WLAN_LPHB
14594/**
14595 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
14596 * @pHddCtx: Pointer to hdd context
14597 * @lphbInd: Pointer to low power heart beat indication parameter
14598 *
14599 * Return: none
14600 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014601static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
14602 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014603{
14604 struct sk_buff *skb;
14605
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014606 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014607
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014608 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014609 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014610
14611 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014612 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014613 return;
14614 }
14615
14616 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
14617 wiphy, sizeof(tSirLPHBInd),
14618 GFP_ATOMIC);
14619 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014620 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014621 return;
14622 }
14623
14624 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014625 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014626 goto nla_put_failure;
14627 }
14628 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014629 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014630 goto nla_put_failure;
14631 }
14632 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014633 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014634 goto nla_put_failure;
14635 }
14636 cfg80211_testmode_event(skb, GFP_ATOMIC);
14637 return;
14638
14639nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014640 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014641 kfree_skb(skb);
14642
14643 return;
14644}
14645#endif /* FEATURE_WLAN_LPHB */
14646
14647/**
14648 * __wlan_hdd_cfg80211_testmode() - test mode
14649 * @wiphy: Pointer to wiphy
14650 * @data: Data pointer
14651 * @len: Data length
14652 *
14653 * Return: 0 for success, non-zero for failure
14654 */
14655static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14656 void *data, int len)
14657{
14658 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
14659 int err;
14660 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14661
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014662 ENTER();
14663
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014664 err = wlan_hdd_validate_context(pHddCtx);
14665 if (err)
14666 return err;
14667
14668 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
14669 len, wlan_hdd_tm_policy);
14670 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014671 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014672 return err;
14673 }
14674
14675 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014676 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014677 return -EINVAL;
14678 }
14679
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014680 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014681 TRACE_CODE_HDD_CFG80211_TESTMODE,
14682 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014683 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
14684#ifdef FEATURE_WLAN_LPHB
14685 /* Low Power Heartbeat configuration request */
14686 case WLAN_HDD_TM_CMD_WLAN_HB:
14687 {
14688 int buf_len;
14689 void *buf;
14690 tSirLPHBReq *hb_params = NULL;
14691 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014692 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014693
14694 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014695 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014696 return -EINVAL;
14697 }
14698
14699 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14700 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14701
14702 hb_params_temp = (tSirLPHBReq *) buf;
14703 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
14704 && (hb_params_temp->params.lphbTcpParamReq.
14705 timePeriodSec == 0))
14706 return -EINVAL;
14707
14708 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014709 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014710 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014711 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014712 return -ENOMEM;
14713 }
14714
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014715 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014716 smeStatus =
14717 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
14718 hb_params,
14719 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014720 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014721 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014722 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014723 }
14724 return 0;
14725 }
14726#endif /* FEATURE_WLAN_LPHB */
14727
14728#if defined(QCA_WIFI_FTM)
14729 case WLAN_HDD_TM_CMD_WLAN_FTM:
14730 {
14731 int buf_len;
14732 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014733 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014734 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014735 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014736 return -EINVAL;
14737 }
14738
14739 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14740 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14741
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014742 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014743
14744 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
14745
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014746 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014747 err = -EBUSY;
14748 break;
14749 }
14750#endif
14751
14752 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014753 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014754 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
14755 return -EOPNOTSUPP;
14756 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014757 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014758 return err;
14759}
14760
14761/**
14762 * wlan_hdd_cfg80211_testmode() - test mode
14763 * @wiphy: Pointer to wiphy
14764 * @dev: Pointer to network device
14765 * @data: Data pointer
14766 * @len: Data length
14767 *
14768 * Return: 0 for success, non-zero for failure
14769 */
14770static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14771#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
14772 struct wireless_dev *wdev,
14773#endif
14774 void *data, int len)
14775{
14776 int ret;
14777
14778 cds_ssr_protect(__func__);
14779 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
14780 cds_ssr_unprotect(__func__);
14781
14782 return ret;
14783}
14784
14785#if defined(QCA_WIFI_FTM)
14786/**
14787 * wlan_hdd_testmode_rx_event() - test mode rx event handler
14788 * @buf: Pointer to buffer
14789 * @buf_len: Buffer length
14790 *
14791 * Return: none
14792 */
14793void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
14794{
14795 struct sk_buff *skb;
14796 hdd_context_t *hdd_ctx;
14797
14798 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014799 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014800 return;
14801 }
14802
Anurag Chouhan6d760662016-02-20 16:05:43 +053014803 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014804 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014805 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014806 return;
14807 }
14808
14809 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
14810 buf_len, GFP_KERNEL);
14811 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014812 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014813 return;
14814 }
14815
14816 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
14817 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
14818 goto nla_put_failure;
14819
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014820 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014821
14822 cfg80211_testmode_event(skb, GFP_KERNEL);
14823 return;
14824
14825nla_put_failure:
14826 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014827 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014828}
14829#endif
14830#endif /* CONFIG_NL80211_TESTMODE */
14831
14832#ifdef QCA_HT_2040_COEX
14833/**
14834 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14835 * @wiphy: Pointer to wiphy
14836 * @dev: Pointer to network device
14837 * @chandef: Pointer to channel definition parameter
14838 *
14839 * Return: 0 for success, non-zero for failure
14840 */
14841static int
14842__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14843 struct net_device *dev,
14844 struct cfg80211_chan_def *chandef)
14845{
14846 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14847 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014848 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014849 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053014850 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014851
Anurag Chouhan6d760662016-02-20 16:05:43 +053014852 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014853 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014854 return -EINVAL;
14855 }
14856
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014857 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14858 hdd_err("invalid session id: %d", pAdapter->sessionId);
14859 return -EINVAL;
14860 }
14861
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014862 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14863 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053014864 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014865 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014866
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014867 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014868 sme_get_config_param(pHddCtx->hHal, &sme_config);
14869 switch (chandef->width) {
14870 case NL80211_CHAN_WIDTH_20:
14871 if (sme_config.csrConfig.channelBondingMode24GHz !=
14872 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14873 sme_config.csrConfig.channelBondingMode24GHz =
14874 eCSR_INI_SINGLE_CHANNEL_CENTERED;
14875 sme_update_config(pHddCtx->hHal, &sme_config);
14876 cbModeChange = true;
14877 }
14878 break;
14879
14880 case NL80211_CHAN_WIDTH_40:
14881 if (sme_config.csrConfig.channelBondingMode24GHz ==
14882 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14883 if (NL80211_CHAN_HT40MINUS ==
14884 cfg80211_get_chandef_type(chandef))
14885 sme_config.csrConfig.channelBondingMode24GHz =
14886 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
14887 else
14888 sme_config.csrConfig.channelBondingMode24GHz =
14889 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
14890 sme_update_config(pHddCtx->hHal, &sme_config);
14891 cbModeChange = true;
14892 }
14893 break;
14894
14895 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014896 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014897 return -EINVAL;
14898 }
14899
14900 if (!cbModeChange)
14901 return 0;
14902
Krunal Sonib4326f22016-03-10 13:05:51 -080014903 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014904 return 0;
14905
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014906 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014907 sme_config.csrConfig.channelBondingMode24GHz);
14908
14909 /* Change SAP ht2040 mode */
14910 status = hdd_set_sap_ht2040_mode(pAdapter,
14911 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014912 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014913 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014914 return -EINVAL;
14915 }
14916
14917 return 0;
14918}
14919
14920/**
14921 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14922 * @wiphy: Pointer to wiphy
14923 * @dev: Pointer to network device
14924 * @chandef: Pointer to channel definition parameter
14925 *
14926 * Return: 0 for success, non-zero for failure
14927 */
14928static int
14929wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14930 struct net_device *dev,
14931 struct cfg80211_chan_def *chandef)
14932{
14933 int ret;
14934
14935 cds_ssr_protect(__func__);
14936 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
14937 cds_ssr_unprotect(__func__);
14938
14939 return ret;
14940}
14941#endif
14942
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014943#ifdef CHANNEL_SWITCH_SUPPORTED
14944/**
14945 * __wlan_hdd_cfg80211_channel_switch()- function to switch
14946 * channel in SAP/GO
14947 * @wiphy: wiphy pointer
14948 * @dev: dev pointer.
14949 * @csa_params: Change channel params
14950 *
14951 * This function is called to switch channel in SAP/GO
14952 *
14953 * Return: 0 if success else return non zero
14954 */
14955static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14956 struct net_device *dev,
14957 struct cfg80211_csa_settings *csa_params)
14958{
14959 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
14960 hdd_context_t *hdd_ctx;
14961 uint8_t channel;
14962 uint16_t freq;
14963 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080014964 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014965
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014966 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014967 csa_params->chandef.chan->center_freq);
14968
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014969 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
14970 hdd_err("invalid session id: %d", adapter->sessionId);
14971 return -EINVAL;
14972 }
14973
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014974 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
14975 ret = wlan_hdd_validate_context(hdd_ctx);
14976
14977 if (0 != ret)
14978 return ret;
14979
Krunal Sonib4326f22016-03-10 13:05:51 -080014980 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
14981 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014982 return -ENOTSUPP;
14983
14984 freq = csa_params->chandef.chan->center_freq;
14985 channel = cds_freq_to_chan(freq);
14986
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053014987 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
14988
14989 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014990 return ret;
14991}
14992
14993/**
14994 * wlan_hdd_cfg80211_channel_switch()- function to switch
14995 * channel in SAP/GO
14996 * @wiphy: wiphy pointer
14997 * @dev: dev pointer.
14998 * @csa_params: Change channel params
14999 *
15000 * This function is called to switch channel in SAP/GO
15001 *
15002 * Return: 0 if success else return non zero
15003 */
15004static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
15005 struct net_device *dev,
15006 struct cfg80211_csa_settings *csa_params)
15007{
15008 int ret;
15009
15010 cds_ssr_protect(__func__);
15011 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
15012 cds_ssr_unprotect(__func__);
15013 return ret;
15014}
15015#endif
15016
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015017/**
15018 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
15019 * translation from NL to policy manager type
15020 * @type: Generic connection mode type defined in NL
15021 *
15022 *
15023 * This function provides the type translation
15024 *
15025 * Return: cds_con_mode enum
15026 */
15027enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
15028 enum nl80211_iftype type)
15029{
15030 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
15031 switch (type) {
15032 case NL80211_IFTYPE_STATION:
15033 mode = CDS_STA_MODE;
15034 break;
15035 case NL80211_IFTYPE_P2P_CLIENT:
15036 mode = CDS_P2P_CLIENT_MODE;
15037 break;
15038 case NL80211_IFTYPE_P2P_GO:
15039 mode = CDS_P2P_GO_MODE;
15040 break;
15041 case NL80211_IFTYPE_AP:
15042 mode = CDS_SAP_MODE;
15043 break;
15044 case NL80211_IFTYPE_ADHOC:
15045 mode = CDS_IBSS_MODE;
15046 break;
15047 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015048 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015049 type);
15050 }
15051 return mode;
15052}
15053
15054/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015055 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
15056 * @wiphy: Handle to struct wiphy to get handle to module context.
15057 * @chandef: Contains information about the capture channel to be set.
15058 *
15059 * This interface is called if and only if monitor mode interface alone is
15060 * active.
15061 *
15062 * Return: 0 success or error code on failure.
15063 */
15064static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
15065 struct cfg80211_chan_def *chandef)
15066{
15067 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15068 hdd_adapter_t *adapter;
15069 hdd_station_ctx_t *sta_ctx;
15070 struct hdd_mon_set_ch_info *ch_info;
15071 QDF_STATUS status;
15072 tHalHandle hal_hdl;
15073 struct qdf_mac_addr bssid;
15074 tCsrRoamProfile roam_profile;
15075 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070015076 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015077 int ret;
15078 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
15079
15080 ENTER();
15081
15082 ret = wlan_hdd_validate_context(hdd_ctx);
15083 if (ret)
15084 return ret;
15085
15086 hal_hdl = hdd_ctx->hHal;
15087
15088 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
15089 if (!adapter)
15090 return -EIO;
15091
15092 hdd_info("%s: set monitor mode Channel %d and freq %d",
15093 adapter->dev->name, chan_num, chandef->chan->center_freq);
15094
15095 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
15096 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015097 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
15098 roam_profile.ChannelInfo.numOfChannels = 1;
15099 roam_profile.phyMode = ch_info->phy_mode;
15100 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015101 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015102
15103 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
15104 QDF_MAC_ADDR_SIZE);
15105
15106 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070015107 /*
15108 * CDS api expects secondary channel for calculating
15109 * the channel params
15110 */
15111 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
15112 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
15113 if (chan_num >= 1 && chan_num <= 5)
15114 sec_ch = chan_num + 4;
15115 else if (chan_num >= 6 && chan_num <= 13)
15116 sec_ch = chan_num - 4;
15117 }
15118 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015119 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
15120 &roam_profile);
15121 if (status) {
15122 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
15123 status);
15124 ret = qdf_status_to_os_return(status);
15125 return ret;
15126 }
15127 EXIT();
15128 return 0;
15129}
15130
15131/**
15132 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
15133 * @wiphy: Handle to struct wiphy to get handle to module context.
15134 * @chandef: Contains information about the capture channel to be set.
15135 *
15136 * This interface is called if and only if monitor mode interface alone is
15137 * active.
15138 *
15139 * Return: 0 success or error code on failure.
15140 */
15141static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
15142 struct cfg80211_chan_def *chandef)
15143{
15144 int ret;
15145
15146 cds_ssr_protect(__func__);
15147 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
15148 cds_ssr_unprotect(__func__);
15149 return ret;
15150}
15151
15152/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053015153 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
15154 * @adapter: pointer to adapter
15155 *
15156 * Wrapper function to clear link layer stats.
15157 * return - void
15158 */
15159void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
15160{
15161 tSirLLStatsClearReq link_layer_stats_clear_req;
15162 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
15163
Mukul Sharma491021c2016-09-29 21:39:19 +053015164 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
15165 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053015166 link_layer_stats_clear_req.stopReq = 0;
15167 link_layer_stats_clear_req.reqId = 1;
15168 link_layer_stats_clear_req.staId = adapter->sessionId;
15169 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
15170
15171 return;
15172}
15173
15174/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015175 * struct cfg80211_ops - cfg80211_ops
15176 *
15177 * @add_virtual_intf: Add virtual interface
15178 * @del_virtual_intf: Delete virtual interface
15179 * @change_virtual_intf: Change virtual interface
15180 * @change_station: Change station
15181 * @add_beacon: Add beacon in sap mode
15182 * @del_beacon: Delete beacon in sap mode
15183 * @set_beacon: Set beacon in sap mode
15184 * @start_ap: Start ap
15185 * @change_beacon: Change beacon
15186 * @stop_ap: Stop ap
15187 * @change_bss: Change bss
15188 * @add_key: Add key
15189 * @get_key: Get key
15190 * @del_key: Delete key
15191 * @set_default_key: Set default key
15192 * @set_channel: Set channel
15193 * @scan: Scan
15194 * @connect: Connect
15195 * @disconnect: Disconnect
15196 * @join_ibss = Join ibss
15197 * @leave_ibss = Leave ibss
15198 * @set_wiphy_params = Set wiphy params
15199 * @set_tx_power = Set tx power
15200 * @get_tx_power = get tx power
15201 * @remain_on_channel = Remain on channel
15202 * @cancel_remain_on_channel = Cancel remain on channel
15203 * @mgmt_tx = Tx management frame
15204 * @mgmt_tx_cancel_wait = Cancel management tx wait
15205 * @set_default_mgmt_key = Set default management key
15206 * @set_txq_params = Set tx queue parameters
15207 * @get_station = Get station
15208 * @set_power_mgmt = Set power management
15209 * @del_station = Delete station
15210 * @add_station = Add station
15211 * @set_pmksa = Set pmksa
15212 * @del_pmksa = Delete pmksa
15213 * @flush_pmksa = Flush pmksa
15214 * @update_ft_ies = Update FT IEs
15215 * @tdls_mgmt = Tdls management
15216 * @tdls_oper = Tdls operation
15217 * @set_rekey_data = Set rekey data
15218 * @sched_scan_start = Scheduled scan start
15219 * @sched_scan_stop = Scheduled scan stop
15220 * @resume = Resume wlan
15221 * @suspend = Suspend wlan
15222 * @set_mac_acl = Set mac acl
15223 * @testmode_cmd = Test mode command
15224 * @set_ap_chanwidth = Set AP channel bandwidth
15225 * @dump_survey = Dump survey
15226 * @key_mgmt_set_pmk = Set pmk key management
15227 */
15228static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
15229 .add_virtual_intf = wlan_hdd_add_virtual_intf,
15230 .del_virtual_intf = wlan_hdd_del_virtual_intf,
15231 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
15232 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015233 .start_ap = wlan_hdd_cfg80211_start_ap,
15234 .change_beacon = wlan_hdd_cfg80211_change_beacon,
15235 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015236 .change_bss = wlan_hdd_cfg80211_change_bss,
15237 .add_key = wlan_hdd_cfg80211_add_key,
15238 .get_key = wlan_hdd_cfg80211_get_key,
15239 .del_key = wlan_hdd_cfg80211_del_key,
15240 .set_default_key = wlan_hdd_cfg80211_set_default_key,
15241 .scan = wlan_hdd_cfg80211_scan,
15242 .connect = wlan_hdd_cfg80211_connect,
15243 .disconnect = wlan_hdd_cfg80211_disconnect,
15244 .join_ibss = wlan_hdd_cfg80211_join_ibss,
15245 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
15246 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
15247 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
15248 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
15249 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
15250 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
15251 .mgmt_tx = wlan_hdd_mgmt_tx,
15252 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
15253 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
15254 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053015255 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015256 .get_station = wlan_hdd_cfg80211_get_station,
15257 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
15258 .del_station = wlan_hdd_cfg80211_del_station,
15259 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015260 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
15261 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
15262 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015263#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015264 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
15265#endif
15266#ifdef FEATURE_WLAN_TDLS
15267 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
15268 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
15269#endif
15270#ifdef WLAN_FEATURE_GTK_OFFLOAD
15271 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
15272#endif /* WLAN_FEATURE_GTK_OFFLOAD */
15273#ifdef FEATURE_WLAN_SCAN_PNO
15274 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
15275 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
15276#endif /*FEATURE_WLAN_SCAN_PNO */
15277 .resume = wlan_hdd_cfg80211_resume_wlan,
15278 .suspend = wlan_hdd_cfg80211_suspend_wlan,
15279 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
15280#ifdef WLAN_NL80211_TESTMODE
15281 .testmode_cmd = wlan_hdd_cfg80211_testmode,
15282#endif
15283#ifdef QCA_HT_2040_COEX
15284 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
15285#endif
15286 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015287#ifdef CHANNEL_SWITCH_SUPPORTED
15288 .channel_switch = wlan_hdd_cfg80211_channel_switch,
15289#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015290 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053015291#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
15292 defined(CFG80211_ABORT_SCAN)
15293 .abort_scan = wlan_hdd_cfg80211_abort_scan,
15294#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015295};