blob: 81e1b45f0e8fd99c986a93b1c82dc23fc1540ab2 [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
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008687/**
8688 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
8689 * @priv_size: Size of the hdd context.
8690 *
8691 * Allocate wiphy context and hdd context.
8692 *
8693 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008694 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008695hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008696{
8697 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008698 hdd_context_t *hdd_ctx;
8699
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008700 ENTER();
8701
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008702 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
8703
8704 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008705 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008706 return NULL;
8707 }
8708
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008709 hdd_ctx = wiphy_priv(wiphy);
8710
8711 hdd_ctx->wiphy = wiphy;
8712
8713 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008714}
8715
8716/*
8717 * FUNCTION: wlan_hdd_cfg80211_update_band
8718 * This function is called from the supplicant through a
8719 * private ioctl to change the band value
8720 */
8721int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
8722{
8723 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07008724 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008725
8726 ENTER();
8727
Dustin Browna30892e2016-10-12 17:28:36 -07008728 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008729
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008730 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008731 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008732
8733 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8734 struct ieee80211_supported_band *band = wiphy->bands[i];
8735
8736 channelEnabledState =
8737 cds_get_channel_state(band->channels[j].
8738 hw_value);
8739
Dustin Browna30892e2016-10-12 17:28:36 -07008740 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008741 /* 5G only */
8742#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8743 /* Enable Social channels for P2P */
8744 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8745 (band->channels[j].center_freq)
8746 && CHANNEL_STATE_ENABLE ==
8747 channelEnabledState)
8748 band->channels[j].flags &=
8749 ~IEEE80211_CHAN_DISABLED;
8750 else
8751#endif
8752 band->channels[j].flags |=
8753 IEEE80211_CHAN_DISABLED;
8754 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07008755 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008756 eCSR_BAND_24 == eBand) {
8757 /* 2G only */
8758 band->channels[j].flags |=
8759 IEEE80211_CHAN_DISABLED;
8760 continue;
8761 }
8762
Amar Singhal6842e8f2016-02-23 16:30:32 -08008763 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008764 band->channels[j].flags &=
8765 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008766 }
8767 }
8768 return 0;
8769}
8770
8771/*
8772 * FUNCTION: wlan_hdd_cfg80211_init
8773 * This function is called by hdd_wlan_startup()
8774 * during initialization.
8775 * This function is used to initialize and register wiphy structure.
8776 */
8777int wlan_hdd_cfg80211_init(struct device *dev,
8778 struct wiphy *wiphy, struct hdd_config *pCfg)
8779{
8780 int i, j;
8781 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8782
8783 ENTER();
8784
8785 /* Now bind the underlying wlan device with wiphy */
8786 set_wiphy_dev(wiphy, dev);
8787
8788 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
8789
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008790#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
8791 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008792 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008793#else
8794 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008795 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008796#endif
8797
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008798 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
8799 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
8800 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
8801#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
8802 | WIPHY_FLAG_4ADDR_STATION
8803#endif
8804 | WIPHY_FLAG_OFFCHAN_TX;
8805
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008806#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
8807 wiphy->wowlan = &wowlan_support_cfg80211_init;
8808#else
8809 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
8810 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
8811 wiphy->wowlan.pattern_min_len = 1;
8812 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
8813#endif
8814
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07008815 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008816#ifdef FEATURE_WLAN_ESE
8817 || pCfg->isEseIniFeatureEnabled
8818#endif
8819 ) {
8820 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
8821 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008822#ifdef FEATURE_WLAN_TDLS
8823 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
8824 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
8825#endif
8826
8827 wiphy->features |= NL80211_FEATURE_HT_IBSS;
8828
Naveen Rawatc77e6e72016-08-05 15:19:03 -07008829#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
8830 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
8831#endif
8832
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008833#ifdef FEATURE_WLAN_SCAN_PNO
8834 if (pCfg->configPNOScanSupport) {
8835 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8836 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
8837 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
8838 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Ryan Hsub736bc52016-06-15 16:58:24 -07008839#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) || defined(WITH_BACKPORTS)
8840 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
8841#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008842 }
8843#endif /*FEATURE_WLAN_SCAN_PNO */
8844
8845#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05308846 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008847#endif
8848
8849 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
8850 driver can still register regulatory callback and
8851 it will get regulatory settings in wiphy->band[], but
8852 driver need to determine what to do with both
8853 regulatory settings */
8854
8855 wiphy->reg_notifier = hdd_reg_notifier;
8856
8857#if defined QCA_WIFI_FTM
8858}
8859#endif
8860
8861 wiphy->max_scan_ssids = MAX_SCAN_SSID;
8862
8863 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
8864
8865 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
8866
Arun Khandavallifae92942016-08-01 13:31:08 +05308867 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
8868 | BIT(NL80211_IFTYPE_ADHOC)
8869 | BIT(NL80211_IFTYPE_P2P_CLIENT)
8870 | BIT(NL80211_IFTYPE_P2P_GO)
8871 | BIT(NL80211_IFTYPE_AP)
8872 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008873
Arun Khandavallifae92942016-08-01 13:31:08 +05308874 if (pCfg->advertiseConcurrentOperation) {
8875 if (pCfg->enableMCC) {
8876 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07008877
Arun Khandavallifae92942016-08-01 13:31:08 +05308878 for (i = 0;
8879 i < ARRAY_SIZE(wlan_hdd_iface_combination);
8880 i++) {
8881 if (!pCfg->allowMCCGODiffBI)
8882 wlan_hdd_iface_combination[i].
8883 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008884 }
8885 }
8886 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +05308887 ARRAY_SIZE(wlan_hdd_iface_combination);
8888 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008889 }
8890
8891 /* Before registering we need to update the ht capabilitied based
8892 * on ini values*/
8893 if (!pCfg->ShortGI20MhzEnable) {
8894 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
8895 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008896 }
8897
8898 if (!pCfg->ShortGI40MhzEnable) {
8899 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
8900 }
8901
8902 if (!pCfg->nChannelBondingMode5GHz) {
8903 wlan_hdd_band_5_ghz.ht_cap.cap &=
8904 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
8905 }
8906
Abhishek Singhf512bf32016-05-04 16:47:46 +05308907 /*
8908 * In case of static linked driver at the time of driver unload,
8909 * module exit doesn't happens. Module cleanup helps in cleaning
8910 * of static memory.
8911 * If driver load happens statically, at the time of driver unload,
8912 * wiphy flags don't get reset because of static memory.
8913 * It's better not to store channel in static memory.
8914 */
Dustin Browna30892e2016-10-12 17:28:36 -07008915 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
8916 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05308917 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07008918 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05308919 hdd_err("Not enough memory to allocate channels");
8920 return -ENOMEM;
8921 }
Dustin Browna30892e2016-10-12 17:28:36 -07008922 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05308923 &hdd_channels_2_4_ghz[0],
8924 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +05308925 if ((hdd_is_5g_supported(pHddCtx)) &&
8926 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
8927 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
8928 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
8929 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -07008930 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
8931 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05308932 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07008933 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05308934 hdd_err("Not enough memory to allocate channels");
8935 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -07008936 bands[NL80211_BAND_2GHZ]->channels);
8937 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +05308938 return -ENOMEM;
8939 }
Dustin Browna30892e2016-10-12 17:28:36 -07008940 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05308941 &hdd_channels_5_ghz[0],
8942 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008943 }
8944
Dustin Browna30892e2016-10-12 17:28:36 -07008945 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008946
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008947 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008948 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008949
8950 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8951 struct ieee80211_supported_band *band = wiphy->bands[i];
8952
Dustin Browna30892e2016-10-12 17:28:36 -07008953 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008954 eCSR_BAND_5G == pCfg->nBandCapability) {
8955 /* 5G only */
8956#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8957 /* Enable social channels for P2P */
8958 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8959 (band->channels[j].center_freq))
8960 band->channels[j].flags &=
8961 ~IEEE80211_CHAN_DISABLED;
8962 else
8963#endif
8964 band->channels[j].flags |=
8965 IEEE80211_CHAN_DISABLED;
8966 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07008967 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008968 eCSR_BAND_24 == pCfg->nBandCapability) {
8969 /* 2G only */
8970 band->channels[j].flags |=
8971 IEEE80211_CHAN_DISABLED;
8972 continue;
8973 }
8974 }
8975 }
8976 /*Initialise the supported cipher suite details */
8977 wiphy->cipher_suites = hdd_cipher_suites;
8978 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
8979
8980 /*signal strength in mBm (100*dBm) */
8981 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
8982 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
8983
Anurag Chouhan6d760662016-02-20 16:05:43 +05308984 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008985 wiphy->n_vendor_commands =
8986 ARRAY_SIZE(hdd_wiphy_vendor_commands);
8987 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
8988
8989 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
8990 wiphy->n_vendor_events =
8991 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
8992 }
8993
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008994 if (pCfg->enableDFSMasterCap) {
8995 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
8996 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008997
8998 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8999
9000#ifdef QCA_HT_2040_COEX
9001 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
9002#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +05309003 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
Abhishek Singh1bdb1572015-10-16 16:24:19 +05309004 hdd_add_channel_switch_support(&wiphy->flags);
9005
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009006 EXIT();
9007 return 0;
9008}
9009
Abhishek Singhf512bf32016-05-04 16:47:46 +05309010/**
Yingying Tang80e15f32016-09-27 18:23:01 +08009011 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
9012 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +05309013 *
9014 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +05309015 * memory allocated in wlan_hdd_cfg80211_init also
9016 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +05309017 *
9018 * Return: void
9019 */
9020void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
9021{
9022 int i;
9023
Dustin Browna30892e2016-10-12 17:28:36 -07009024 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05309025 if (NULL != wiphy->bands[i] &&
9026 (NULL != wiphy->bands[i]->channels)) {
9027 qdf_mem_free(wiphy->bands[i]->channels);
9028 wiphy->bands[i]->channels = NULL;
9029 }
9030 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +05309031 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +05309032}
9033
Yingying Tang80e15f32016-09-27 18:23:01 +08009034/**
9035 * wlan_hdd_update_band_cap() - update capabilities for supported bands
9036 * @hdd_ctx: HDD context
9037 *
9038 * this function will update capabilities for supported bands
9039 *
9040 * Return: void
9041 */
9042static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
9043{
9044 uint32_t val32;
9045 uint16_t val16;
9046 tSirMacHTCapabilityInfo *ht_cap_info;
9047 QDF_STATUS status;
9048
9049 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
9050 if (QDF_STATUS_SUCCESS != status) {
9051 hdd_err("could not get HT capability info");
9052 val32 = 0;
9053 }
9054 val16 = (uint16_t)val32;
9055 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
9056
9057 if (ht_cap_info->txSTBC == true) {
9058 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
9059 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
9060 IEEE80211_HT_CAP_TX_STBC;
9061 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
9062 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
9063 IEEE80211_HT_CAP_TX_STBC;
9064 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08009065
9066 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
9067 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
9068 vht_cap.vht_supported = 0;
9069 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
9070 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
9071 vht_cap.vht_supported = 0;
9072 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
9073 }
Yingying Tang80e15f32016-09-27 18:23:01 +08009074}
9075
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009076/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309077 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009078 * initialization. In wlan_hdd_cfg80211_init, only the
9079 * default values will be initialized. The final initialization
9080 * of all required members can be done here.
9081 */
Yingying Tang80e15f32016-09-27 18:23:01 +08009082void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009083{
Yingying Tang80e15f32016-09-27 18:23:01 +08009084 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
9085
9086 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009087}
9088
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08009089/**
9090 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
9091 * @cfg: hdd cfg
9092 *
9093 * this function update 11n mode in hdd cfg
9094 *
9095 * Return: void
9096 */
9097void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
9098{
9099 if (sme_is_feature_supported_by_fw(DOT11AC)) {
9100 hdd_notice("support 11ac");
9101 } else {
9102 hdd_notice("not support 11ac");
9103 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
9104 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
9105 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
9106 cfg->sap_p2p_11ac_override = 0;
9107 }
9108 }
9109}
9110
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009111/* In this function we are registering wiphy. */
9112int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
9113{
9114 ENTER();
9115 /* Register our wiphy dev with cfg80211 */
9116 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009117 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009118 return -EIO;
9119 }
9120
9121 EXIT();
9122 return 0;
9123}
9124
9125/*
9126 HDD function to update wiphy capability based on target offload status.
9127
9128 wlan_hdd_cfg80211_init() does initialization of all wiphy related
9129 capability even before downloading firmware to the target. In discrete
9130 case, host will get know certain offload capability (say sched_scan
9131 caps) only after downloading firmware to the target and target boots up.
9132 This function is used to override setting done in wlan_hdd_cfg80211_init()
9133 based on target capability.
9134 */
9135void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
9136{
9137#ifdef FEATURE_WLAN_SCAN_PNO
9138 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9139 struct hdd_config *pCfg = pHddCtx->config;
9140
9141 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
9142 * control comes here. Here just we need to clear it if firmware doesn't
9143 * have PNO support. */
9144 if (!pCfg->PnoOffload) {
9145 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
9146 wiphy->max_sched_scan_ssids = 0;
9147 wiphy->max_match_sets = 0;
9148 wiphy->max_sched_scan_ie_len = 0;
9149 }
9150#endif
9151}
9152
9153/* This function registers for all frame which supplicant is interested in */
9154void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
9155{
9156 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9157 /* Register for all P2P action, public action etc frames */
9158 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9159
9160 ENTER();
9161
Abhishek Singh7996eb72015-12-30 17:24:02 +05309162 /* Register frame indication call back */
9163 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
9164
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +05309165 /* Register for p2p ack indication */
9166 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
9167
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009168 /* Right now we are registering these frame when driver is getting
9169 initialized. Once we will move to 2.6.37 kernel, in which we have
9170 frame register ops, we will move this code as a part of that */
9171 /* GAS Initial Request */
9172 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9173 (uint8_t *) GAS_INITIAL_REQ,
9174 GAS_INITIAL_REQ_SIZE);
9175
9176 /* GAS Initial Response */
9177 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9178 (uint8_t *) GAS_INITIAL_RSP,
9179 GAS_INITIAL_RSP_SIZE);
9180
9181 /* GAS Comeback Request */
9182 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9183 (uint8_t *) GAS_COMEBACK_REQ,
9184 GAS_COMEBACK_REQ_SIZE);
9185
9186 /* GAS Comeback Response */
9187 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9188 (uint8_t *) GAS_COMEBACK_RSP,
9189 GAS_COMEBACK_RSP_SIZE);
9190
9191 /* P2P Public Action */
9192 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9193 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9194 P2P_PUBLIC_ACTION_FRAME_SIZE);
9195
9196 /* P2P Action */
9197 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9198 (uint8_t *) P2P_ACTION_FRAME,
9199 P2P_ACTION_FRAME_SIZE);
9200
9201 /* WNM BSS Transition Request frame */
9202 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9203 (uint8_t *) WNM_BSS_ACTION_FRAME,
9204 WNM_BSS_ACTION_FRAME_SIZE);
9205
9206 /* WNM-Notification */
9207 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
9208 (uint8_t *) WNM_NOTIFICATION_FRAME,
9209 WNM_NOTIFICATION_FRAME_SIZE);
9210}
9211
9212void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
9213{
9214 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9215 /* Register for all P2P action, public action etc frames */
9216 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9217
9218 ENTER();
9219
9220 /* Right now we are registering these frame when driver is getting
9221 initialized. Once we will move to 2.6.37 kernel, in which we have
9222 frame register ops, we will move this code as a part of that */
9223 /* GAS Initial Request */
9224
9225 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9226 (uint8_t *) GAS_INITIAL_REQ,
9227 GAS_INITIAL_REQ_SIZE);
9228
9229 /* GAS Initial Response */
9230 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9231 (uint8_t *) GAS_INITIAL_RSP,
9232 GAS_INITIAL_RSP_SIZE);
9233
9234 /* GAS Comeback Request */
9235 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9236 (uint8_t *) GAS_COMEBACK_REQ,
9237 GAS_COMEBACK_REQ_SIZE);
9238
9239 /* GAS Comeback Response */
9240 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9241 (uint8_t *) GAS_COMEBACK_RSP,
9242 GAS_COMEBACK_RSP_SIZE);
9243
9244 /* P2P Public Action */
9245 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9246 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9247 P2P_PUBLIC_ACTION_FRAME_SIZE);
9248
9249 /* P2P Action */
9250 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9251 (uint8_t *) P2P_ACTION_FRAME,
9252 P2P_ACTION_FRAME_SIZE);
9253
9254 /* WNM-Notification */
9255 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
9256 (uint8_t *) WNM_NOTIFICATION_FRAME,
9257 WNM_NOTIFICATION_FRAME_SIZE);
9258}
9259
9260#ifdef FEATURE_WLAN_WAPI
9261void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
9262 const uint8_t *mac_addr, const uint8_t *key,
9263 int key_Len)
9264{
9265 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9266 tCsrRoamSetKey setKey;
9267 bool isConnected = true;
9268 int status = 0;
9269 uint32_t roamId = 0xFF;
9270 uint8_t *pKeyPtr = NULL;
9271 int n = 0;
9272
Jeff Johnson46b40792016-06-29 14:03:14 -07009273 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009274 hdd_device_mode_to_string(pAdapter->device_mode),
9275 pAdapter->device_mode);
9276
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309277 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009278 setKey.keyId = key_index; /* Store Key ID */
9279 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
9280 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
9281 setKey.paeRole = 0; /* the PAE role */
9282 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05309283 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009284 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309285 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009286 }
9287 setKey.keyLength = key_Len;
9288 pKeyPtr = setKey.Key;
9289 memcpy(pKeyPtr, key, key_Len);
9290
Jeff Johnson46b40792016-06-29 14:03:14 -07009291 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009292 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -07009293 hdd_notice("WAPI KEY Data[%d]:%02x ",
9294 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009295
9296 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
9297 if (isConnected) {
9298 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9299 pAdapter->sessionId, &setKey, &roamId);
9300 }
9301 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -07009302 hdd_err("sme_roam_set_key returned ERROR status= %d",
9303 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009304 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
9305 }
9306}
9307#endif /* FEATURE_WLAN_WAPI */
9308
9309uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
9310 uint8_t eid)
9311{
9312 int left = length;
9313 uint8_t *ptr = (uint8_t *)ies_ptr;
9314 uint8_t elem_id, elem_len;
9315
9316 while (left >= 2) {
9317 elem_id = ptr[0];
9318 elem_len = ptr[1];
9319 left -= 2;
9320 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -07009321 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009322 eid, elem_len, left);
9323 return NULL;
9324 }
9325 if (elem_id == eid) {
9326 return ptr;
9327 }
9328
9329 left -= elem_len;
9330 ptr += (elem_len + 2);
9331 }
9332 return NULL;
9333}
9334
9335/*
9336 * FUNCTION: wlan_hdd_validate_operation_channel
9337 * called by wlan_hdd_cfg80211_start_bss() and
9338 * wlan_hdd_set_channel()
9339 * This function validates whether given channel is part of valid
9340 * channel list.
9341 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309342QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009343 int channel)
9344{
9345
9346 uint32_t num_ch = 0;
9347 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
9348 u32 indx = 0;
9349 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9350 uint8_t fValidChannel = false, count = 0;
9351 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
9352
9353 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
9354
9355 if (hdd_pConfig_ini->sapAllowAllChannel) {
9356 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -08009357 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07009358 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009359 fValidChannel = true;
9360 break;
9361 }
9362 }
9363 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -07009364 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309365 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009366 }
9367 } else {
9368 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
9369 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009370 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309371 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009372 }
9373 for (indx = 0; indx < num_ch; indx++) {
9374 if (channel == valid_ch[indx]) {
9375 break;
9376 }
9377 }
9378
9379 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -07009380 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309381 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009382 }
9383 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309384 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009385
9386}
9387
9388#ifdef DHCP_SERVER_OFFLOAD
9389static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
9390{
9391 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
9392 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
9393 uint8_t numEntries = 0;
9394 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
9395 uint8_t num;
9396 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309397 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009398 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -07009399 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009400 return;
9401 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009402 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
9403 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
9404 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
9405 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
9406 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
9407 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -07009408 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009409 goto end;
9410 }
9411 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009412 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009413 goto end;
9414 }
9415 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -07009416 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009417 goto end;
9418 }
9419 for (num = 0; num < numEntries; num++) {
9420 temp = srv_ip[num];
9421 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
9422 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309423 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009424 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009425 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009426 goto end;
9427 }
Jeff Johnson77848112016-06-29 14:52:06 -07009428 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009429end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309430 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009431 return;
9432}
9433#endif /* DHCP_SERVER_OFFLOAD */
9434
9435static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9436 struct net_device *dev,
9437 struct bss_parameters *params)
9438{
9439 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9440 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9441 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309442 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009443
9444 ENTER();
9445
Anurag Chouhan6d760662016-02-20 16:05:43 +05309446 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009447 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009448 return -EINVAL;
9449 }
9450
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05309451 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
9452 hdd_err("invalid session id: %d", pAdapter->sessionId);
9453 return -EINVAL;
9454 }
9455
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309456 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009457 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
9458 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -07009459 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009460 hdd_device_mode_to_string(pAdapter->device_mode),
9461 pAdapter->device_mode, params->ap_isolate);
9462
9463 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9464 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309465 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009466 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009467
Krunal Sonib4326f22016-03-10 13:05:51 -08009468 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
9469 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009470 return -EOPNOTSUPP;
9471 }
9472
9473 /* ap_isolate == -1 means that in change bss, upper layer doesn't
9474 * want to update this parameter */
9475 if (-1 != params->ap_isolate) {
9476 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
9477 !!params->ap_isolate;
9478
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309479 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009480 pAdapter->sessionId,
9481 pAdapter->sessionCtx.
9482 ap.
9483 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309484 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009485 ret = -EINVAL;
9486 }
9487 }
9488
9489 EXIT();
9490 return ret;
9491}
9492
Krunal Soni8c37e322016-02-03 16:08:37 -08009493/**
9494 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
9495 * @ndev: pointer to net device provided by supplicant
9496 * @type: type of the interface, upper layer wanted to change
9497 *
9498 * Upper layer provides the new interface mode that needs to be changed
9499 * for given net device
9500 *
9501 * Return: success or failure in terms of integer value
9502 */
9503static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009504 enum nl80211_iftype type)
9505{
Krunal Soni8c37e322016-02-03 16:08:37 -08009506 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9507 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9508 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009509 hdd_wext_state_t *wext;
9510 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309511 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009512
9513 ENTER();
9514
Krunal Soni8c37e322016-02-03 16:08:37 -08009515 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009516 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009517 return 0;
9518 }
9519
9520 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -08009521 hdd_stop_adapter(hdd_ctx, adapter, true);
9522 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009523 wdev->iftype = type;
9524 /*Check for sub-string p2p to confirm its a p2p interface */
9525 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -08009526 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009527 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009528 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -08009529 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -08009530 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009531 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -08009532 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009533 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009534 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009535 }
Krunal Soni8c37e322016-02-03 16:08:37 -08009536 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
9537 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -08009538 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
9539 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009540 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -08009541 adapter->scan_info.scanAddIE.length;
9542 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309543 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -08009544 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
9545 wext->roamProfile.phyMode =
9546 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
9547 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009548 EXIT();
9549 return status;
9550}
9551
9552static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9553 struct net_device *dev,
9554 struct bss_parameters *params)
9555{
9556 int ret;
9557
9558 cds_ssr_protect(__func__);
9559 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
9560 cds_ssr_unprotect(__func__);
9561
9562 return ret;
9563}
9564
9565/* FUNCTION: wlan_hdd_change_country_code_cd
9566 * to wait for contry code completion
9567 */
9568void *wlan_hdd_change_country_code_cb(void *pAdapter)
9569{
9570 hdd_adapter_t *call_back_pAdapter = pAdapter;
9571 complete(&call_back_pAdapter->change_country_code);
9572 return NULL;
9573}
9574
Rajeev Kumar98edb772016-01-19 12:42:19 -08009575/**
9576 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9577 * @wiphy: Pointer to the wiphy structure
9578 * @ndev: Pointer to the net device
9579 * @type: Interface type
9580 * @flags: Flags for change interface
9581 * @params: Pointer to change interface parameters
9582 *
9583 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009584 */
9585static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9586 struct net_device *ndev,
9587 enum nl80211_iftype type,
9588 u32 *flags,
9589 struct vif_params *params)
9590{
9591 struct wireless_dev *wdev;
9592 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9593 hdd_context_t *pHddCtx;
9594 tCsrRoamProfile *pRoamProfile = NULL;
9595 eCsrRoamBssType LastBSSType;
9596 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309597 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009598 int status;
9599
9600 ENTER();
9601
Anurag Chouhan6d760662016-02-20 16:05:43 +05309602 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009603 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009604 return -EINVAL;
9605 }
9606
9607 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9608 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309609 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009610 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009611
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309612 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009613 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
9614 pAdapter->sessionId, type));
9615
Jeff Johnson77848112016-06-29 14:52:06 -07009616 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009617 pAdapter->device_mode, type);
9618
Arun Khandavallifae92942016-08-01 13:31:08 +05309619 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
9620 if (status) {
9621 hdd_err("Failed to start modules");
9622 return -EINVAL;
9623 }
9624
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009625 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009626 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
9627 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009628 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009629 return -EINVAL;
9630 }
9631
9632 pConfig = pHddCtx->config;
9633 wdev = ndev->ieee80211_ptr;
9634
9635 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009636 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009637
9638 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
9639
Krunal Sonib4326f22016-03-10 13:05:51 -08009640 if ((pAdapter->device_mode == QDF_STA_MODE) ||
9641 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
9642 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
9643 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009644 hdd_wext_state_t *pWextState =
9645 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9646
9647 pRoamProfile = &pWextState->roamProfile;
9648 LastBSSType = pRoamProfile->BSSType;
9649
9650 switch (type) {
9651 case NL80211_IFTYPE_STATION:
9652 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -08009653 case NL80211_IFTYPE_ADHOC:
9654 if (type == NL80211_IFTYPE_ADHOC) {
9655 wlan_hdd_tdls_exit(pAdapter);
9656 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -07009657 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -08009658 }
9659 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
9660 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309661 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009662 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309663 if (hdd_start_adapter(pAdapter)) {
9664 hdd_err("Failed to start adapter :%d",
9665 pAdapter->device_mode);
9666 return -EINVAL;
9667 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009668 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009669 case NL80211_IFTYPE_AP:
9670 case NL80211_IFTYPE_P2P_GO:
9671 {
Jeff Johnson77848112016-06-29 14:52:06 -07009672 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009673 (type ==
9674 NL80211_IFTYPE_AP) ? "SoftAP" :
9675 "P2pGo");
9676
9677 /* Cancel any remain on channel for GO mode */
9678 if (NL80211_IFTYPE_P2P_GO == type) {
9679 wlan_hdd_cancel_existing_remain_on_channel
9680 (pAdapter);
9681 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009682
Arun Khandavallifae92942016-08-01 13:31:08 +05309683 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009684 /* De-init the adapter */
9685 hdd_deinit_adapter(pHddCtx, pAdapter, true);
9686 memset(&pAdapter->sessionCtx, 0,
9687 sizeof(pAdapter->sessionCtx));
9688 pAdapter->device_mode =
9689 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -08009690 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
9691 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009692
9693 /*
9694 * Fw will take care incase of concurrency
9695 */
9696
Krunal Sonib4326f22016-03-10 13:05:51 -08009697 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009698 && (pConfig->apRandomBssidEnabled)) {
9699 /* To meet Android requirements create a randomized
9700 MAC address of the form 02:1A:11:Fx:xx:xx */
9701 get_random_bytes(&ndev->dev_addr[3], 3);
9702 ndev->dev_addr[0] = 0x02;
9703 ndev->dev_addr[1] = 0x1A;
9704 ndev->dev_addr[2] = 0x11;
9705 ndev->dev_addr[3] |= 0xF0;
9706 memcpy(pAdapter->macAddressCurrent.
9707 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309708 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009709 pr_info("wlan: Generated HotSpot BSSID "
9710 MAC_ADDRESS_STR "\n",
9711 MAC_ADDR_ARRAY(ndev->dev_addr));
9712 }
9713
9714 hdd_set_ap_ops(pAdapter->dev);
9715
Arun Khandavallifae92942016-08-01 13:31:08 +05309716 if (hdd_start_adapter(pAdapter)) {
9717 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009718 return -EINVAL;
9719 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009720 /* Interface type changed update in wiphy structure */
9721 if (wdev) {
9722 wdev->iftype = type;
9723 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009724 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009725 return -EINVAL;
9726 }
9727 goto done;
9728 }
9729
9730 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009731 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009732 type);
9733 return -EOPNOTSUPP;
9734 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009735 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9736 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009737 switch (type) {
9738 case NL80211_IFTYPE_STATION:
9739 case NL80211_IFTYPE_P2P_CLIENT:
9740 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -08009741 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
9742 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309743 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009744 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309745 if (hdd_start_adapter(pAdapter)) {
9746 hdd_err("Failed to start adapter :%d",
9747 pAdapter->device_mode);
9748 return -EINVAL;
9749 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009750 goto done;
9751
9752 case NL80211_IFTYPE_AP:
9753 case NL80211_IFTYPE_P2P_GO:
9754 wdev->iftype = type;
9755 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009756 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009757 goto done;
9758
9759 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009760 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009761 type);
9762 return -EOPNOTSUPP;
9763 }
9764 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009765 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009766 pAdapter->device_mode);
9767 return -EOPNOTSUPP;
9768 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009769done:
9770 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009771 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009772
Jeff Johnson2ae6f712016-09-23 15:08:48 -07009773 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009774
9775 EXIT();
9776 return 0;
9777}
9778
Rajeev Kumar98edb772016-01-19 12:42:19 -08009779/**
9780 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9781 * @wiphy: Pointer to the wiphy structure
9782 * @ndev: Pointer to the net device
9783 * @type: Interface type
9784 * @flags: Flags for change interface
9785 * @params: Pointer to change interface parameters
9786 *
9787 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009788 */
9789static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9790 struct net_device *ndev,
9791 enum nl80211_iftype type,
9792 u32 *flags,
9793 struct vif_params *params)
9794{
9795 int ret;
9796
9797 cds_ssr_protect(__func__);
9798 ret =
9799 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
9800 cds_ssr_unprotect(__func__);
9801
9802 return ret;
9803}
9804
9805#ifdef FEATURE_WLAN_TDLS
9806static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
9807 int index, uint8_t match)
9808{
9809 int i;
9810 for (i = 0; i < index; i++) {
9811 if (arr[i] == match)
9812 return true;
9813 }
9814 return false;
9815}
9816#endif
9817
9818/**
9819 * __wlan_hdd_change_station() - change station
9820 * @wiphy: Pointer to the wiphy structure
9821 * @dev: Pointer to the net device.
9822 * @mac: bssid
9823 * @params: Pointer to station parameters
9824 *
9825 * Return: 0 for success, error number on failure.
9826 */
9827#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9828static int __wlan_hdd_change_station(struct wiphy *wiphy,
9829 struct net_device *dev,
9830 const uint8_t *mac,
9831 struct station_parameters *params)
9832#else
9833static int __wlan_hdd_change_station(struct wiphy *wiphy,
9834 struct net_device *dev,
9835 uint8_t *mac,
9836 struct station_parameters *params)
9837#endif
9838{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309839 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009840 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9841 hdd_context_t *pHddCtx;
9842 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +05309843 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009844#ifdef FEATURE_WLAN_TDLS
9845 tCsrStaParams StaParams = { 0 };
9846 uint8_t isBufSta = 0;
9847 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +05309848 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009849#endif
9850 int ret;
9851
9852 ENTER();
9853
Anurag Chouhan6d760662016-02-20 16:05:43 +05309854 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009855 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009856 return -EINVAL;
9857 }
9858
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309859 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009860 TRACE_CODE_HDD_CHANGE_STATION,
9861 pAdapter->sessionId, params->listen_interval));
9862
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05309863 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
9864 hdd_err("invalid session id: %d", pAdapter->sessionId);
9865 return -EINVAL;
9866 }
9867
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009868 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9869 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309870 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009871 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009872
9873 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9874
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309875 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009876
Krunal Sonib4326f22016-03-10 13:05:51 -08009877 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9878 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009879 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
9880 status =
9881 hdd_softap_change_sta_state(pAdapter,
9882 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -08009883 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009884
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309885 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009886 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009887 return -EINVAL;
9888 }
9889 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009890 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
9891 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009892#ifdef FEATURE_WLAN_TDLS
9893 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -07009894
9895 if (cds_is_sub_20_mhz_enabled()) {
9896 hdd_err("TDLS not allowed with sub 20 MHz");
9897 return -EINVAL;
9898 }
9899
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009900 StaParams.capability = params->capability;
9901 StaParams.uapsd_queues = params->uapsd_queues;
9902 StaParams.max_sp = params->max_sp;
9903
9904 /* Convert (first channel , number of channels) tuple to
9905 * the total list of channels. This goes with the assumption
9906 * that if the first channel is < 14, then the next channels
9907 * are an incremental of 1 else an incremental of 4 till the number
9908 * of channels.
9909 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009910 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009911 if (0 != params->supported_channels_len) {
9912 int i = 0, j = 0, k = 0, no_of_channels = 0;
9913 int num_unique_channels;
9914 int next;
9915 for (i = 0;
9916 i < params->supported_channels_len
9917 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
9918 int wifi_chan_index;
9919 if (!wlan_hdd_is_duplicate_channel
9920 (StaParams.supported_channels, j,
9921 params->supported_channels[i])) {
9922 StaParams.
9923 supported_channels[j] =
9924 params->
9925 supported_channels[i];
9926 } else {
9927 continue;
9928 }
9929 wifi_chan_index =
9930 ((StaParams.supported_channels[j] <=
9931 HDD_CHANNEL_14) ? 1 : 4);
9932 no_of_channels =
9933 params->supported_channels[i + 1];
9934
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009935 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 -08009936 StaParams.
9937 supported_channels[j],
9938 wifi_chan_index,
9939 no_of_channels);
9940 for (k = 1; k <= no_of_channels &&
9941 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
9942 k++) {
9943 next =
9944 StaParams.
9945 supported_channels[j] +
9946 wifi_chan_index;
9947 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
9948 StaParams.
9949 supported_channels[j
9950 +
9951 1]
9952 = next;
9953 } else {
9954 continue;
9955 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009956 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009957 j + 1,
9958 StaParams.
9959 supported_channels[j +
9960 1]);
9961 j += 1;
9962 }
9963 }
9964 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009965 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009966 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009967 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009968 StaParams.
9969 supported_channels[i]);
9970 }
9971 if (MAX_CHANNEL < num_unique_channels)
9972 num_unique_channels = MAX_CHANNEL;
9973 StaParams.supported_channels_len =
9974 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009975 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009976 StaParams.supported_channels_len);
9977 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309978 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009979 params->supported_oper_classes,
9980 params->supported_oper_classes_len);
9981 StaParams.supported_oper_classes_len =
9982 params->supported_oper_classes_len;
9983
9984 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309985 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009986 params->ext_capab,
9987 sizeof(StaParams.extn_capability));
9988
9989 if (NULL != params->ht_capa) {
9990 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309991 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009992 sizeof(tSirHTCap));
9993 }
9994
9995 StaParams.supported_rates_len =
9996 params->supported_rates_len;
9997
9998 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
9999 * The supported_rates array , for all the structures propogating till Add Sta
10000 * to the firmware has to be modified , if the supplicant (ieee80211) is
10001 * modified to send more rates.
10002 */
10003
10004 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
10005 */
10006 if (StaParams.supported_rates_len >
10007 SIR_MAC_MAX_SUPP_RATES)
10008 StaParams.supported_rates_len =
10009 SIR_MAC_MAX_SUPP_RATES;
10010
10011 if (0 != StaParams.supported_rates_len) {
10012 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010013 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010014 params->supported_rates,
10015 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010016 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010017 StaParams.supported_rates_len);
10018 for (i = 0; i < StaParams.supported_rates_len;
10019 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010020 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010021 StaParams.supported_rates[i]);
10022 }
10023
10024 if (NULL != params->vht_capa) {
10025 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010026 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010027 params->vht_capa,
10028 sizeof(tSirVHTCap));
10029 }
10030
10031 if (0 != params->ext_capab_len) {
10032 /*Define A Macro : TODO Sunil */
10033 if ((1 << 4) & StaParams.extn_capability[3]) {
10034 isBufSta = 1;
10035 }
10036 /* TDLS Channel Switching Support */
10037 if ((1 << 6) & StaParams.extn_capability[3]) {
10038 isOffChannelSupported = 1;
10039 }
10040 }
10041
Nitesh Shah99934ac2016-09-05 15:54:08 +053010042 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053010043 (params->ht_capa || params->vht_capa ||
10044 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053010045 is_qos_wmm_sta = true;
10046
10047 hdd_notice("%s: TDLS Peer is QOS capable"
10048 " is_qos_wmm_sta= %d HTcapPresent = %d",
10049 __func__, is_qos_wmm_sta,
10050 StaParams.htcap_present);
10051
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010052 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053010053 &StaParams,
10054 isBufSta,
10055 isOffChannelSupported,
10056 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010057 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010058 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010059 return -EINVAL;
10060 }
10061
10062 status =
10063 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
10064 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010065 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010066 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010067 return -EINVAL;
10068 }
10069 }
10070#endif
10071 }
10072 EXIT();
10073 return ret;
10074}
10075
10076/**
10077 * wlan_hdd_change_station() - cfg80211 change station handler function
10078 * @wiphy: Pointer to the wiphy structure
10079 * @dev: Pointer to the net device.
10080 * @mac: bssid
10081 * @params: Pointer to station parameters
10082 *
10083 * This is the cfg80211 change station handler function which invokes
10084 * the internal function @__wlan_hdd_change_station with
10085 * SSR protection.
10086 *
10087 * Return: 0 for success, error number on failure.
10088 */
10089#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
10090static int wlan_hdd_change_station(struct wiphy *wiphy,
10091 struct net_device *dev,
10092 const u8 *mac,
10093 struct station_parameters *params)
10094#else
10095static int wlan_hdd_change_station(struct wiphy *wiphy,
10096 struct net_device *dev,
10097 u8 *mac,
10098 struct station_parameters *params)
10099#endif
10100{
10101 int ret;
10102
10103 cds_ssr_protect(__func__);
10104 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
10105 cds_ssr_unprotect(__func__);
10106
10107 return ret;
10108}
10109
10110/*
10111 * FUNCTION: __wlan_hdd_cfg80211_add_key
10112 * This function is used to initialize the key information
10113 */
10114static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10115 struct net_device *ndev,
10116 u8 key_index, bool pairwise,
10117 const u8 *mac_addr,
10118 struct key_params *params)
10119{
10120 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10121 tCsrRoamSetKey setKey;
10122 int status;
10123 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010124 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010125 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010126 hdd_context_t *pHddCtx;
10127 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10128
10129 ENTER();
10130
Anurag Chouhan6d760662016-02-20 16:05:43 +053010131 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010132 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010133 return -EINVAL;
10134 }
10135
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010136 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10137 hdd_err("invalid session id: %d", pAdapter->sessionId);
10138 return -EINVAL;
10139 }
10140
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010141 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010142 TRACE_CODE_HDD_CFG80211_ADD_KEY,
10143 pAdapter->sessionId, params->key_len));
10144 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10145 status = wlan_hdd_validate_context(pHddCtx);
10146
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010147 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010148 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010149
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010150 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010151 hdd_device_mode_to_string(pAdapter->device_mode),
10152 pAdapter->device_mode);
10153
10154 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010155 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010156
10157 return -EINVAL;
10158 }
10159
10160 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010161 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010162
10163 return -EINVAL;
10164 }
10165
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010166 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010167
10168 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010169 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010170 setKey.keyId = key_index;
10171 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010172 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010173
10174 switch (params->cipher) {
10175 case WLAN_CIPHER_SUITE_WEP40:
10176 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
10177 break;
10178
10179 case WLAN_CIPHER_SUITE_WEP104:
10180 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
10181 break;
10182
10183 case WLAN_CIPHER_SUITE_TKIP:
10184 {
10185 u8 *pKey = &setKey.Key[0];
10186 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
10187
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010188 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010189
10190 /*Supplicant sends the 32bytes key in this order
10191
10192 |--------------|----------|----------|
10193 | Tk1 |TX-MIC | RX Mic |
10194 |||--------------|----------|----------|
10195 <---16bytes---><--8bytes--><--8bytes-->
10196
10197 */
10198 /*Sme expects the 32 bytes key to be in the below order
10199
10200 |--------------|----------|----------|
10201 | Tk1 |RX-MIC | TX Mic |
10202 |||--------------|----------|----------|
10203 <---16bytes---><--8bytes--><--8bytes-->
10204 */
10205 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010206 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010207
10208 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010209 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010210
10211 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010212 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010213
10214 break;
10215 }
10216
10217 case WLAN_CIPHER_SUITE_CCMP:
10218 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
10219 break;
10220
10221#ifdef FEATURE_WLAN_WAPI
10222 case WLAN_CIPHER_SUITE_SMS4:
10223 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010224 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010225 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
10226 mac_addr, params->key,
10227 params->key_len);
10228 return 0;
10229 }
10230#endif
10231
10232#ifdef FEATURE_WLAN_ESE
10233 case WLAN_CIPHER_SUITE_KRK:
10234 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
10235 break;
10236#ifdef WLAN_FEATURE_ROAM_OFFLOAD
10237 case WLAN_CIPHER_SUITE_BTK:
10238 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
10239 break;
10240#endif
10241#endif
10242
10243#ifdef WLAN_FEATURE_11W
10244 case WLAN_CIPHER_SUITE_AES_CMAC:
10245 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
10246 break;
10247#endif
10248
10249 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010250 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010251 return -EOPNOTSUPP;
10252 }
10253
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010254 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010255
10256 if (!pairwise) {
10257 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010258 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010259 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010260 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010261 } else {
10262 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010263 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010264 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010265 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010266 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010267 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010268 /* if a key is already installed, block all subsequent ones */
10269 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010270 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010271 return 0;
10272 }
10273
10274 setKey.keyDirection = eSIR_TX_RX;
10275 /*Set the group key */
10276 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10277 pAdapter->sessionId, &setKey, &roamId);
10278
10279 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010280 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010281 return -EINVAL;
10282 }
10283 /*Save the keys here and call sme_roam_set_key for setting
10284 the PTK after peer joins the IBSS network */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010285 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010286 &setKey, sizeof(tCsrRoamSetKey));
10287
10288 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
10289 return status;
10290 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010291 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10292 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010293 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10294 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070010295 status = wlansap_set_key_sta(
10296 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010297 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010298 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010299 __LINE__, status);
10300 }
10301 }
10302
10303 /* Save the key in ap ctx for use on START_BASS and restart */
10304 if (pairwise ||
10305 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
10306 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010307 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010308 sizeof(tCsrRoamSetKey));
10309 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010310 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010311 sizeof(tCsrRoamSetKey));
10312
Krunal Sonib4326f22016-03-10 13:05:51 -080010313 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
10314 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010315 hdd_wext_state_t *pWextState =
10316 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10317 hdd_station_ctx_t *pHddStaCtx =
10318 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10319
10320 if (!pairwise) {
10321 /* set group key */
10322 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010323 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010324 __func__, __LINE__);
10325 hdd_perform_roam_set_key_complete(pAdapter);
10326 }
10327 }
10328
10329 pWextState->roamProfile.Keys.KeyLength[key_index] =
10330 (u8) params->key_len;
10331
10332 pWextState->roamProfile.Keys.defaultIndex = key_index;
10333
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010334 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010335 KeyMaterial[key_index][0], params->key,
10336 params->key_len);
10337
10338 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10339
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010340 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010341 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10342 setKey.keyDirection);
10343
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010344 /* The supplicant may attempt to set the PTK once pre-authentication
10345 is done. Save the key in the UMAC and include it in the ADD BSS
10346 request */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010347 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010348 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010349 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010350 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010351 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010352 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010353 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010354 return -EINVAL;
10355 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010356
10357 /* issue set key request to SME */
10358 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10359 pAdapter->sessionId, &setKey, &roamId);
10360
10361 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010362 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010363 pHddStaCtx->roam_info.roamingState =
10364 HDD_ROAM_STATE_NONE;
10365 return -EINVAL;
10366 }
10367
10368 /* in case of IBSS as there was no information available about WEP keys during
10369 * IBSS join, group key intialized with NULL key, so re-initialize group key
10370 * with correct value*/
10371 if ((eCSR_BSS_TYPE_START_IBSS ==
10372 pWextState->roamProfile.BSSType)
10373 &&
10374 !((IW_AUTH_KEY_MGMT_802_1X ==
10375 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
10376 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
10377 pHddStaCtx->conn_info.authType)
10378 )
10379 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
10380 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
10381 )
10382 ) {
10383 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010384 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010385
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010386 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010387 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10388 setKey.keyDirection);
10389
10390 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10391 pAdapter->sessionId, &setKey,
10392 &roamId);
10393
10394 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010395 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010396 pHddStaCtx->roam_info.roamingState =
10397 HDD_ROAM_STATE_NONE;
10398 return -EINVAL;
10399 }
10400 }
10401 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010402 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010403 return 0;
10404}
10405
10406static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10407 struct net_device *ndev,
10408 u8 key_index, bool pairwise,
10409 const u8 *mac_addr,
10410 struct key_params *params)
10411{
10412 int ret;
10413 cds_ssr_protect(__func__);
10414 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
10415 mac_addr, params);
10416 cds_ssr_unprotect(__func__);
10417
10418 return ret;
10419}
10420
10421/*
10422 * FUNCTION: __wlan_hdd_cfg80211_get_key
10423 * This function is used to get the key information
10424 */
10425static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10426 struct net_device *ndev,
10427 u8 key_index, bool pairwise,
10428 const u8 *mac_addr, void *cookie,
10429 void (*callback)(void *cookie,
10430 struct key_params *)
10431 )
10432{
10433 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10434 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10435 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
10436 struct key_params params;
10437
10438 ENTER();
10439
Anurag Chouhan6d760662016-02-20 16:05:43 +053010440 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010441 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010442 return -EINVAL;
10443 }
10444
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010445 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010446 hdd_device_mode_to_string(pAdapter->device_mode),
10447 pAdapter->device_mode);
10448
10449 memset(&params, 0, sizeof(params));
10450
10451 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010452 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010453 key_index);
10454 return -EINVAL;
10455 }
10456
10457 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
10458 case eCSR_ENCRYPT_TYPE_NONE:
10459 params.cipher = IW_AUTH_CIPHER_NONE;
10460 break;
10461
10462 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
10463 case eCSR_ENCRYPT_TYPE_WEP40:
10464 params.cipher = WLAN_CIPHER_SUITE_WEP40;
10465 break;
10466
10467 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
10468 case eCSR_ENCRYPT_TYPE_WEP104:
10469 params.cipher = WLAN_CIPHER_SUITE_WEP104;
10470 break;
10471
10472 case eCSR_ENCRYPT_TYPE_TKIP:
10473 params.cipher = WLAN_CIPHER_SUITE_TKIP;
10474 break;
10475
10476 case eCSR_ENCRYPT_TYPE_AES:
10477 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
10478 break;
10479
10480 default:
10481 params.cipher = IW_AUTH_CIPHER_NONE;
10482 break;
10483 }
10484
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010485 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010486 TRACE_CODE_HDD_CFG80211_GET_KEY,
10487 pAdapter->sessionId, params.cipher));
10488
10489 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
10490 params.seq_len = 0;
10491 params.seq = NULL;
10492 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
10493 callback(cookie, &params);
10494
10495 EXIT();
10496 return 0;
10497}
10498
10499static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10500 struct net_device *ndev,
10501 u8 key_index, bool pairwise,
10502 const u8 *mac_addr, void *cookie,
10503 void (*callback)(void *cookie,
10504 struct key_params *)
10505 )
10506{
10507 int ret;
10508
10509 cds_ssr_protect(__func__);
10510 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
10511 mac_addr, cookie, callback);
10512 cds_ssr_unprotect(__func__);
10513
10514 return ret;
10515}
10516
10517/**
10518 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
10519 * @wiphy: wiphy interface context
10520 * @ndev: pointer to net device
10521 * @key_index: Key index used in 802.11 frames
10522 * @unicast: true if it is unicast key
10523 * @multicast: true if it is multicast key
10524 *
10525 * This function is required for cfg80211_ops API.
10526 * It is used to delete the key information
10527 * Underlying hardware implementation does not have API to delete the
10528 * encryption key. It is automatically deleted when the peer is
10529 * removed. Hence this function currently does nothing.
10530 * Future implementation may interprete delete key operation to
10531 * replacing the key with a random junk value, effectively making it
10532 * useless.
10533 *
10534 * Return: status code, always 0.
10535 */
10536
10537static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10538 struct net_device *ndev,
10539 u8 key_index,
10540 bool pairwise, const u8 *mac_addr)
10541{
10542 EXIT();
10543 return 0;
10544}
10545
10546/**
10547 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
10548 * @wiphy: Pointer to wiphy structure.
10549 * @dev: Pointer to net_device structure.
10550 * @key_index: key index
10551 * @pairwise: pairwise
10552 * @mac_addr: mac address
10553 *
10554 * This is the cfg80211 delete key handler function which invokes
10555 * the internal function @__wlan_hdd_cfg80211_del_key with
10556 * SSR protection.
10557 *
10558 * Return: 0 for success, error number on failure.
10559 */
10560static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10561 struct net_device *dev,
10562 u8 key_index,
10563 bool pairwise, const u8 *mac_addr)
10564{
10565 int ret;
10566
10567 cds_ssr_protect(__func__);
10568 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
10569 pairwise, mac_addr);
10570 cds_ssr_unprotect(__func__);
10571
10572 return ret;
10573}
10574
10575/*
10576 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
10577 * This function is used to set the default tx key index
10578 */
10579static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10580 struct net_device *ndev,
10581 u8 key_index,
10582 bool unicast, bool multicast)
10583{
10584 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10585 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10586 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10587 hdd_context_t *pHddCtx;
10588 int status;
10589
10590 ENTER();
10591
Anurag Chouhan6d760662016-02-20 16:05:43 +053010592 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010593 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010594 return -EINVAL;
10595 }
10596
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010597 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10598 hdd_err("invalid session id: %d", pAdapter->sessionId);
10599 return -EINVAL;
10600 }
10601
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010602 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010603 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
10604 pAdapter->sessionId, key_index));
10605
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010606 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010607 hdd_device_mode_to_string(pAdapter->device_mode),
10608 pAdapter->device_mode, key_index);
10609
10610 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010611 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010612 return -EINVAL;
10613 }
10614
10615 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10616 status = wlan_hdd_validate_context(pHddCtx);
10617
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010618 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010619 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010620
Krunal Sonib4326f22016-03-10 13:05:51 -080010621 if ((pAdapter->device_mode == QDF_STA_MODE) ||
10622 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010623 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10624 pHddStaCtx->conn_info.ucEncryptionType) &&
10625 (eCSR_ENCRYPT_TYPE_AES !=
10626 pHddStaCtx->conn_info.ucEncryptionType)) {
10627 /* If default key index is not same as previous one,
10628 * then update the default key index */
10629
10630 tCsrRoamSetKey setKey;
10631 uint32_t roamId = 0xFF;
10632 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
10633
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010634 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010635
10636 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010637 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010638 setKey.keyId = key_index;
10639 setKey.keyLength = Keys->KeyLength[key_index];
10640
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010641 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010642 &Keys->KeyMaterial[key_index][0],
10643 Keys->KeyLength[key_index]);
10644
10645 setKey.keyDirection = eSIR_TX_RX;
10646
Anurag Chouhanc5548422016-02-24 18:33:27 +053010647 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010648 &pHddStaCtx->conn_info.bssId);
10649
10650 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
10651 pWextState->roamProfile.EncryptionType.
10652 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
10653 /* In the case of dynamic wep supplicant hardcodes DWEP type
10654 * to eCSR_ENCRYPT_TYPE_WEP104 even though ap is configured for
10655 * WEP-40 encryption. In this canse the key length is 5 but the
10656 * encryption type is 104 hence checking the key langht(5) and
10657 * encryption type(104) and switching encryption type to 40*/
10658 pWextState->roamProfile.EncryptionType.
10659 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10660 pWextState->roamProfile.mcEncryptionType.
10661 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10662 }
10663
10664 setKey.encType =
10665 pWextState->roamProfile.EncryptionType.
10666 encryptionType[0];
10667
10668 /* Issue set key request */
10669 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10670 pAdapter->sessionId, &setKey,
10671 &roamId);
10672
10673 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010674 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010675 status);
10676 return -EINVAL;
10677 }
10678 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010679 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010680 /* In SoftAp mode setting key direction for default mode */
10681 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10682 pWextState->roamProfile.EncryptionType.encryptionType[0])
10683 && (eCSR_ENCRYPT_TYPE_AES !=
10684 pWextState->roamProfile.EncryptionType.
10685 encryptionType[0])) {
10686 /* Saving key direction for default key index to TX default */
10687 hdd_ap_ctx_t *pAPCtx =
10688 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10689 pAPCtx->wepKey[key_index].keyDirection =
10690 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010691 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053010692 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010693 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010694 }
10695 }
10696
10697 EXIT();
10698 return status;
10699}
10700
10701static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10702 struct net_device *ndev,
10703 u8 key_index,
10704 bool unicast, bool multicast)
10705{
10706 int ret;
10707 cds_ssr_protect(__func__);
10708 ret =
10709 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
10710 multicast);
10711 cds_ssr_unprotect(__func__);
10712
10713 return ret;
10714}
10715
Abhishek Singhc9941602016-08-09 16:06:22 +053010716/*
10717 * wlan_hdd_cfg80211_get_bss :to get the bss from kernel cache.
10718 * @wiphy: wiphy pointer
10719 * @channel: channel of the BSS
10720 * @bssid: Bssid of BSS
10721 * @ssid: Ssid of the BSS
10722 * @ssid_len: ssid length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010723 *
Abhishek Singhc9941602016-08-09 16:06:22 +053010724 * Return: bss found in kernel cache
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010725 */
Abhishek Singhc9941602016-08-09 16:06:22 +053010726#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010727static
Abhishek Singhc9941602016-08-09 16:06:22 +053010728struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10729 struct ieee80211_channel *channel, const u8 *bssid,
10730 const u8 *ssid, size_t ssid_len)
10731{
10732 return cfg80211_get_bss(wiphy, channel, bssid,
10733 ssid,
10734 ssid_len,
10735 WLAN_CAPABILITY_ESS,
10736 WLAN_CAPABILITY_ESS);
10737}
10738#else
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010739static
Abhishek Singhc9941602016-08-09 16:06:22 +053010740struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10741 struct ieee80211_channel *channel, const u8 *bssid,
10742 const u8 *ssid, size_t ssid_len)
10743{
10744 return cfg80211_get_bss(wiphy, channel, bssid,
10745 ssid,
10746 ssid_len,
10747 IEEE80211_BSS_TYPE_ESS,
10748 IEEE80211_PRIVACY_ANY);
10749}
10750#endif
10751
10752
10753/*
10754 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
10755 * interface that BSS might have been lost.
10756 * @pAdapter: adaptor
10757 * @bssid: bssid which might have been lost
10758 *
10759 * Return: bss which is unlinked from kernel cache
10760 */
10761struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
10762 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010763{
10764 struct net_device *dev = pAdapter->dev;
10765 struct wireless_dev *wdev = dev->ieee80211_ptr;
10766 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010767 struct cfg80211_bss *bss = NULL;
10768
Abhishek Singhc9941602016-08-09 16:06:22 +053010769 bss = wlan_hdd_cfg80211_get_bss(wiphy, NULL, bssid,
10770 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010771 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010772 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010773 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053010774 hdd_info("cfg80211_unlink_bss called for BSSID "
10775 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010776 cfg80211_unlink_bss(wiphy, bss);
10777 }
10778 return bss;
10779}
10780
Abhishek Singhc9941602016-08-09 16:06:22 +053010781
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010782/**
10783 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
10784 * @pAdapter: Pointer to adapter
10785 * @bss_desc: Pointer to bss descriptor
10786 *
10787 * This function is used to inform the BSS details to nl80211 interface.
10788 *
10789 * Return: struct cfg80211_bss pointer
10790 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053010791struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
10792 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010793{
10794 /*
10795 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
10796 * already exists in bss data base of cfg80211 for that particular BSS
10797 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
10798 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
10799 * As of now there is no possibility to get the mgmt(probe response)
10800 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
10801 * and passing to cfg80211_inform_bss_frame.
10802 */
10803 struct net_device *dev = pAdapter->dev;
10804 struct wireless_dev *wdev = dev->ieee80211_ptr;
10805 struct wiphy *wiphy = wdev->wiphy;
10806 int chan_no = bss_desc->channelId;
10807#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10808 qcom_ie_age *qie_age = NULL;
10809 int ie_length =
10810 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
10811#else
10812 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
10813#endif
10814 const char *ie =
10815 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
10816 unsigned int freq;
10817 struct ieee80211_channel *chan;
10818 struct ieee80211_mgmt *mgmt = NULL;
10819 struct cfg80211_bss *bss_status = NULL;
10820 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
10821 int rssi = 0;
10822 hdd_context_t *pHddCtx;
10823 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010824 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010825 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010826
10827 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10828 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010829 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010830 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010831
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010832 cfg_param = pHddCtx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010833 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
10834 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010835 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010836 return NULL;
10837 }
10838
10839 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
10840
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010841 /* Android does not want the timestamp from the frame.
10842 Instead it wants a monotonic increasing value */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070010843 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010844 mgmt->u.probe_resp.timestamp =
10845 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010846
10847 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
10848 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
10849
10850#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10851 /* GPS Requirement: need age ie per entry. Using vendor specific. */
10852 /* Assuming this is the last IE, copy at the end */
10853 ie_length -= sizeof(qcom_ie_age);
10854 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
10855 qie_age->element_id = QCOM_VENDOR_IE_ID;
10856 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
10857 qie_age->oui_1 = QCOM_OUI1;
10858 qie_age->oui_2 = QCOM_OUI2;
10859 qie_age->oui_3 = QCOM_OUI3;
10860 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053010861 /*
10862 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
10863 * all bss related timestamp is in units of ms. Due to this when scan
10864 * results are sent to lowi the scan age is high.To address this,
10865 * send age in units of 1/10 ms.
10866 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010867 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053010868 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010869 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070010870 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
10871 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070010872 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
10873 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010874#endif
10875
10876 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
10877 if (bss_desc->fProbeRsp) {
10878 mgmt->frame_control |=
10879 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
10880 } else {
10881 mgmt->frame_control |=
10882 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
10883 }
10884
10885 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070010886 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010887 freq =
10888 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070010889 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010890 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070010891 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010892 freq =
10893 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070010894 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010895 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010896 hdd_err("Invalid chan_no %d", chan_no);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010897 kfree(mgmt);
10898 return NULL;
10899 }
10900
10901 chan = __ieee80211_get_channel(wiphy, freq);
10902 /* When the band is changed on the fly using the GUI, three things are done
10903 * 1. scan abort
10904 * 2. flush scan results from cache
10905 * 3. update the band with the new band user specified (refer to the
10906 * hdd_set_band_helper function) as part of the scan abort, message will be
10907 * queued to PE and we proceed with flushing and changinh the band.
10908 * PE will stop the scanning further and report back the results what ever
10909 * it had till now by calling the call back function.
10910 * if the time between update band and scandone call back is sufficient
10911 * enough the band change reflects in SME, SME validates the channels
10912 * and discards the channels correponding to previous band and calls back
10913 * with zero bss results. but if the time between band update and scan done
10914 * callback is very small then band change will not reflect in SME and SME
10915 * reports to HDD all the channels correponding to previous band.this is due
10916 * to race condition.but those channels are invalid to the new band and so
10917 * this function __ieee80211_get_channel will return NULL.Each time we
10918 * report scan result with this pointer null warning kernel trace is printed.
10919 * if the scan results contain large number of APs continuosly kernel
10920 * warning trace is printed and it will lead to apps watch dog bark.
10921 * So drop the bss and continue to next bss.
10922 */
10923 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053010924 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
10925 chan_no, freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010926 kfree(mgmt);
10927 return NULL;
10928 }
10929
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010930 /* Based on .ini configuration, raw rssi can be reported for bss.
10931 * Raw rssi is typically used for estimating power.
10932 */
10933
10934 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
10935 bss_desc->rssi;
10936
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010937 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053010938 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010939
SaidiReddy Yenuga1fa40972016-11-15 13:44:15 +053010940 hdd_log(LOG1, "BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010941 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070010942 (int)(rssi / 100),
10943 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010944
10945 bss_status =
10946 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
10947 GFP_KERNEL);
10948 kfree(mgmt);
10949 return bss_status;
10950}
10951
10952/**
10953 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
10954 * @pAdapter: Pointer to adapter
10955 * @pRoamInfo: Pointer to roam info
10956 *
10957 * This function is used to update the BSS data base of CFG8011
10958 *
10959 * Return: struct cfg80211_bss pointer
10960 */
10961struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
10962 tCsrRoamInfo *pRoamInfo)
10963{
10964 tCsrRoamConnectedProfile roamProfile;
10965 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10966 struct cfg80211_bss *bss = NULL;
10967
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010968 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
10969 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
10970
10971 if (NULL != roamProfile.pBssDesc) {
10972 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10973 roamProfile.pBssDesc);
10974
10975 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010976 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010977
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080010978 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010979 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010980 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010981 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010982 return bss;
10983}
10984/**
10985 * wlan_hdd_cfg80211_update_bss() - update bss
10986 * @wiphy: Pointer to wiphy
10987 * @pAdapter: Pointer to adapter
10988 * @scan_time: scan request timestamp
10989 *
10990 * Return: zero if success, non-zero otherwise
10991 */
10992int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
10993 hdd_adapter_t *pAdapter,
10994 uint32_t scan_time)
10995{
10996 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10997 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010998 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010999 tScanResultHandle pResult;
11000 struct cfg80211_bss *bss_status = NULL;
11001 hdd_context_t *pHddCtx;
11002 int ret;
11003
11004 ENTER();
11005
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011006 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11007 hdd_err("invalid session id: %d", pAdapter->sessionId);
11008 return -EINVAL;
11009 }
11010
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011011 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011012 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
11013 NO_SESSION, pAdapter->sessionId));
11014
11015 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11016 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011017 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011018 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011019
11020 /* start getting scan results and populate cgf80211 BSS database */
11021 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
11022
11023 /* no scan results */
11024 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011025 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053011026 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011027 }
11028
11029 pScanResult = sme_scan_result_get_first(hHal, pResult);
11030
11031 while (pScanResult) {
11032 /*
11033 * - cfg80211_inform_bss() is not updating ie field of bss
11034 * entry if entry already exists in bss data base of cfg80211
11035 * for that particular BSS ID. Using cfg80211_inform_bss_frame
11036 * to update thebss entry instead of cfg80211_inform_bss,
11037 * But this call expects mgmt packet as input. As of now
11038 * there is no possibility to get the mgmt(probe response)
11039 * frame from PE, converting bss_desc to
11040 * ieee80211_mgmt(probe response) and passing to c
11041 * fg80211_inform_bss_frame.
11042 * - Update BSS only if beacon timestamp is later than
11043 * scan request timestamp.
11044 */
11045 if ((scan_time == 0) ||
11046 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053011047 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011048 bss_status =
11049 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
11050 &pScanResult->BssDescriptor);
11051
11052 if (NULL == bss_status) {
11053 hdd_info("NULL returned by cfg80211_inform_bss_frame");
11054 } else {
11055 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011056 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011057 bss_status);
11058 }
11059 } else {
11060 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
11061 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
11062 }
11063 pScanResult = sme_scan_result_get_next(hHal, pResult);
11064 }
11065
11066 sme_scan_result_purge(hHal, pResult);
11067 /*
11068 * For SAP mode, scan is invoked by hostapd during SAP start
11069 * if hostapd is restarted, we need to flush previous scan
11070 * result so that it will reflect environment change
11071 */
Krunal Sonib4326f22016-03-10 13:05:51 -080011072 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011073#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
11074 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
11075#endif
11076 )
11077 sme_scan_flush_result(hHal);
11078
11079 EXIT();
11080 return 0;
11081}
11082
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011083/**
11084 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
11085 * @pAdapter: Pointer to adapter
11086 * @pRoamInfo: Pointer to roam info
11087 * @index: Index
11088 * @preauth: Preauth flag
11089 *
11090 * This function is used to notify the supplicant of a new PMKSA candidate.
11091 *
11092 * Return: 0 for success, non-zero for failure
11093 */
11094int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
11095 tCsrRoamInfo *pRoamInfo,
11096 int index, bool preauth)
11097{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011098 struct net_device *dev = pAdapter->dev;
11099 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
11100
11101 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011102 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011103
11104 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011105 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011106 return -EINVAL;
11107 }
11108
11109 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011110 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011111 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
11112 cfg80211_pmksa_candidate_notify(dev, index,
11113 pRoamInfo->bssid.bytes,
11114 preauth, GFP_KERNEL);
11115 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011116 return 0;
11117}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011118
11119#ifdef FEATURE_WLAN_LFR_METRICS
11120/**
11121 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
11122 * @pAdapter: Pointer to adapter
11123 * @pRoamInfo: Pointer to roam info
11124 *
11125 * 802.11r/LFR metrics reporting function to report preauth initiation
11126 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011127 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011128 */
11129#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011130QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011131 tCsrRoamInfo *pRoamInfo)
11132{
11133 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11134 union iwreq_data wrqu;
11135
11136 ENTER();
11137
11138 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011139 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011140 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011141 }
11142
11143 /* create the event */
11144 memset(&wrqu, 0, sizeof(wrqu));
11145 memset(metrics_notification, 0, sizeof(metrics_notification));
11146
11147 wrqu.data.pointer = metrics_notification;
11148 wrqu.data.length = scnprintf(metrics_notification,
11149 sizeof(metrics_notification),
11150 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
11151 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11152
11153 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11154 metrics_notification);
11155
11156 EXIT();
11157
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011158 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011159}
11160
11161/**
11162 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11163 * @pAdapter: Pointer to adapter
11164 * @pRoamInfo: Pointer to roam info
11165 * @preauth_status: Preauth status
11166 *
11167 * 802.11r/LFR metrics reporting function to report handover initiation
11168 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011169 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011170 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011171QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011172wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
11173 tCsrRoamInfo *pRoamInfo,
11174 bool preauth_status)
11175{
11176 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11177 union iwreq_data wrqu;
11178
11179 ENTER();
11180
11181 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011182 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011183 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011184 }
11185
11186 /* create the event */
11187 memset(&wrqu, 0, sizeof(wrqu));
11188 memset(metrics_notification, 0, sizeof(metrics_notification));
11189
11190 scnprintf(metrics_notification, sizeof(metrics_notification),
11191 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
11192 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11193
11194 if (1 == preauth_status)
11195 strlcat(metrics_notification, " true",
11196 sizeof(metrics_notification));
11197 else
11198 strlcat(metrics_notification, " false",
11199 sizeof(metrics_notification));
11200
11201 wrqu.data.pointer = metrics_notification;
11202 wrqu.data.length = strlen(metrics_notification);
11203
11204 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11205 metrics_notification);
11206
11207 EXIT();
11208
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011209 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011210}
11211
11212/**
11213 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11214 * @pAdapter: Pointer to adapter
11215 * @pRoamInfo: Pointer to roam info
11216 *
11217 * 802.11r/LFR metrics reporting function to report handover initiation
11218 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011219 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011220 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011221QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011222 tCsrRoamInfo *pRoamInfo)
11223{
11224 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11225 union iwreq_data wrqu;
11226
11227 ENTER();
11228
11229 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011230 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011231 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011232 }
11233
11234 /* create the event */
11235 memset(&wrqu, 0, sizeof(wrqu));
11236 memset(metrics_notification, 0, sizeof(metrics_notification));
11237
11238 wrqu.data.pointer = metrics_notification;
11239 wrqu.data.length = scnprintf(metrics_notification,
11240 sizeof(metrics_notification),
11241 "QCOM: LFR_PREAUTH_HANDOVER "
11242 MAC_ADDRESS_STR,
11243 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11244
11245 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11246 metrics_notification);
11247
11248 EXIT();
11249
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011250 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011251}
11252#endif
11253
11254/**
11255 * hdd_select_cbmode() - select channel bonding mode
11256 * @pAdapter: Pointer to adapter
11257 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011258 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011259 *
11260 * Return: none
11261 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011262void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
11263 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011264{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011265 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011266 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011267 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011268
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011269 /*
11270 * CDS api expects secondary channel for calculating
11271 * the channel params
11272 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011273 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011274 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
11275 if (operationChannel >= 1 && operationChannel <= 5)
11276 sec_ch = operationChannel + 4;
11277 else if (operationChannel >= 6 && operationChannel <= 13)
11278 sec_ch = operationChannel - 4;
11279 }
11280
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011281 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011282 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011283
11284 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011285 eHddDot11Mode hdd_dot11_mode;
11286 uint8_t iniDot11Mode =
11287 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
11288
11289 hdd_notice("Dot11Mode is %u", iniDot11Mode);
11290 switch (iniDot11Mode) {
11291 case eHDD_DOT11_MODE_AUTO:
11292 case eHDD_DOT11_MODE_11ac:
11293 case eHDD_DOT11_MODE_11ac_ONLY:
11294 if (sme_is_feature_supported_by_fw(DOT11AC))
11295 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
11296 else
11297 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11298 break;
11299 case eHDD_DOT11_MODE_11n:
11300 case eHDD_DOT11_MODE_11n_ONLY:
11301 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11302 break;
11303 default:
11304 hdd_dot11_mode = iniDot11Mode;
11305 break;
11306 }
11307 ch_info->channel_width = ch_params->ch_width;
11308 ch_info->phy_mode =
11309 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011310 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011311 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011312 hdd_info("ch_info width %d, phymode %d channel %d",
11313 ch_info->channel_width, ch_info->phy_mode,
11314 ch_info->channel);
11315 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011316}
11317
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011318/**
11319 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
11320 * @adapter: STA adapter
11321 * @roam_profile: STA roam profile
11322 *
11323 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
11324 *
11325 * Return: false if sta-sap conc is not allowed, else return true
11326 */
11327static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
11328 tCsrRoamProfile *roam_profile)
11329{
11330 hdd_context_t *hdd_ctx;
11331 hdd_adapter_t *ap_adapter;
11332 hdd_ap_ctx_t *hdd_ap_ctx;
11333 hdd_hostapd_state_t *hostapd_state;
11334 uint8_t channel = 0;
11335 QDF_STATUS status;
11336
11337 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11338 if (!hdd_ctx) {
11339 hdd_err("HDD context is NULL");
11340 return true;
11341 }
11342
11343 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
11344 /* probably no sap running, no handling required */
11345 if (ap_adapter == NULL)
11346 return true;
11347
11348 /*
11349 * sap is not in started state, so it is fine to go ahead with sta.
11350 * if sap is currently doing CAC then don't allow sta to go further.
11351 */
11352 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
11353 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
11354 return true;
11355
11356 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
11357 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
11358 return false;
11359 }
11360
11361 /*
11362 * log and return error, if we allow STA to go through, we don't
11363 * know what is going to happen better stop sta connection
11364 */
11365 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
11366 if (NULL == hdd_ap_ctx) {
11367 hdd_err("AP context not found");
11368 return false;
11369 }
11370
11371 /* sap is on non-dfs channel, nothing to handle */
11372 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
11373 hdd_info("sap is on non-dfs channel, sta is allowed");
11374 return true;
11375 }
11376 /*
11377 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053011378 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011379 */
11380 status = cds_get_channel_from_scan_result(adapter,
11381 roam_profile, &channel);
11382
Nitesh Shah59774522016-09-16 15:14:21 +053011383 /*
11384 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
11385 * channels for roaming case.
11386 */
11387 if (CDS_IS_CHANNEL_24GHZ(channel)) {
11388 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
11389 return true;
11390 }
11391
11392 /*
11393 * If channel is 0 or DFS then better to call pcl and find out the
11394 * best channel. If channel is non-dfs 5 GHz then better move SAP
11395 * to STA's channel to make scc, so we have room for 3port MCC
11396 * scenario.
11397 */
11398 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011399 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
11400 true);
11401
11402 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
11403 qdf_event_reset(&hostapd_state->qdf_event);
11404 status = wlansap_set_channel_change_with_csa(
11405 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
11406 hdd_ap_ctx->sapConfig.ch_width_orig);
11407
11408 if (QDF_STATUS_SUCCESS != status) {
11409 hdd_err("Set channel with CSA IE failed, can't allow STA");
11410 return false;
11411 }
11412
11413 /*
11414 * wait here for SAP to finish the channel switch. When channel
11415 * switch happens, SAP sends few beacons with CSA_IE. After
11416 * successfully Transmission of those beacons, it will move its
11417 * state from started to disconnected and move to new channel.
11418 * once it moves to new channel, sap again moves its state
11419 * machine from disconnected to started and set this event.
11420 * wait for 10 secs to finish this.
11421 */
11422 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
11423 if (!QDF_IS_STATUS_SUCCESS(status)) {
11424 hdd_err("wait for qdf_event failed, STA not allowed!!");
11425 return false;
11426 }
11427
11428 return true;
11429}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011430
Krunal Soni31949422016-07-29 17:17:53 -070011431/**
11432 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011433 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070011434 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011435 * @ssid_len: Length of ssid
11436 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070011437 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011438 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011439 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011440 *
11441 * This function is used to start the association process
11442 *
11443 * Return: 0 for success, non-zero for failure
11444 */
Krunal Soni31949422016-07-29 17:17:53 -070011445static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011446 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070011447 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011448 u8 operatingChannel,
11449 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011450{
11451 int status = 0;
11452 hdd_wext_state_t *pWextState;
11453 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011454 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011455 uint32_t roamId;
11456 tCsrRoamProfile *pRoamProfile;
11457 eCsrAuthType RSNAuthType;
11458 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053011459 uint8_t channel = 0;
11460 struct sir_hw_mode_params hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011461
11462 ENTER();
11463
11464 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11465 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011466 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011467
11468 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011469 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011470 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011471
11472 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011473 hdd_err("wrong SSID len");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011474 return -EINVAL;
11475 }
11476
11477 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053011478 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
11479 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011480
11481 if (pRoamProfile) {
11482 hdd_station_ctx_t *pHddStaCtx;
11483 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11484
11485 if (HDD_WMM_USER_MODE_NO_QOS ==
11486 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
11487 /*QoS not enabled in cfg file */
11488 pRoamProfile->uapsd_mask = 0;
11489 } else {
11490 /*QoS enabled, update uapsd mask from cfg file */
11491 pRoamProfile->uapsd_mask =
11492 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
11493 }
11494
11495 pRoamProfile->SSIDs.numOfSSIDs = 1;
11496 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011497 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011498 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011499 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011500 ssid, ssid_len);
11501
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011502 pRoamProfile->do_not_roam = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011503 if (bssid) {
11504 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011505 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011506 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011507 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011508 /*
11509 * Save BSSID in seperate variable as
11510 * pRoamProfile's BSSID is getting zeroed out in the
11511 * association process. In case of join failure
11512 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011513 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011514 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011515 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011516 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011517 } else if (bssid_hint) {
11518 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011519 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011520 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011521 /*
11522 * Save BSSID in a separate variable as
11523 * pRoamProfile's BSSID is getting zeroed out in the
11524 * association process. In case of join failure
11525 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011526 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011527 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011528 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011529 hdd_info("bssid_hint is given by upper layer %pM",
11530 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011531 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011532 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011533 QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011534 hdd_info("no bssid given by upper layer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011535 }
11536
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011537 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011538 pRoamProfile->SSIDs.SSIDList->SSID.length,
11539 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
11540 operatingChannel);
11541
11542 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
11543 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011544 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011545 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
11546 }
11547#ifdef FEATURE_WLAN_WAPI
11548 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011549 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011550 switch (pAdapter->wapi_info.wapiAuthMode) {
11551 case WAPI_AUTH_MODE_PSK:
11552 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011553 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011554 pAdapter->wapi_info.wapiAuthMode);
11555 pRoamProfile->AuthType.authType[0] =
11556 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
11557 break;
11558 }
11559 case WAPI_AUTH_MODE_CERT:
11560 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011561 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011562 pAdapter->wapi_info.wapiAuthMode);
11563 pRoamProfile->AuthType.authType[0] =
11564 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
11565 break;
11566 }
11567 } /* End of switch */
11568 if (pAdapter->wapi_info.wapiAuthMode ==
11569 WAPI_AUTH_MODE_PSK
11570 || pAdapter->wapi_info.wapiAuthMode ==
11571 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011572 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011573 pRoamProfile->AuthType.numEntries = 1;
11574 pRoamProfile->EncryptionType.numEntries = 1;
11575 pRoamProfile->EncryptionType.encryptionType[0] =
11576 eCSR_ENCRYPT_TYPE_WPI;
11577 pRoamProfile->mcEncryptionType.numEntries = 1;
11578 pRoamProfile->mcEncryptionType.
11579 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
11580 }
11581 }
Krunal Soni31949422016-07-29 17:17:53 -070011582#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011583#ifdef WLAN_FEATURE_GTK_OFFLOAD
11584 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080011585 if ((QDF_STA_MODE == pAdapter->device_mode) ||
11586 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011587 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
11588 sizeof(tSirGtkOffloadParams));
11589 pHddStaCtx->gtkOffloadReqParams.ulFlags =
11590 GTK_OFFLOAD_DISABLE;
11591 }
11592#endif
11593 pRoamProfile->csrPersona = pAdapter->device_mode;
11594
11595 if (operatingChannel) {
11596 pRoamProfile->ChannelInfo.ChannelList =
11597 &operatingChannel;
11598 pRoamProfile->ChannelInfo.numOfChannels = 1;
11599 } else {
11600 pRoamProfile->ChannelInfo.ChannelList = NULL;
11601 pRoamProfile->ChannelInfo.numOfChannels = 0;
11602 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011603 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011604 && operatingChannel) {
11605 /*
11606 * Need to post the IBSS power save parameters
11607 * to WMA. WMA will configure this parameters
11608 * to firmware if power save is enabled by the
11609 * firmware.
11610 */
11611 status = hdd_set_ibss_power_save_params(pAdapter);
11612
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011613 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011614 hdd_err("Set IBSS Power Save Params Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011615 return -EINVAL;
11616 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011617 pRoamProfile->ch_params.ch_width =
11618 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053011619 /*
11620 * In IBSS mode while operating in 2.4 GHz,
11621 * the device supports only 20 MHz.
11622 */
11623 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
11624 pRoamProfile->ch_params.ch_width =
11625 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011626 hdd_select_cbmode(pAdapter, operatingChannel,
11627 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011628 }
Abhishek Singh99bce862016-06-20 15:10:51 +053011629 /*
11630 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
11631 * or pmf=2 is an explicit configuration in the supplicant
11632 * configuration, drop the connection request.
11633 */
11634 if (pWextState->roamProfile.MFPEnabled &&
11635 !(pWextState->roamProfile.MFPRequired ||
11636 pWextState->roamProfile.MFPCapable)) {
11637 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
11638 pWextState->roamProfile.MFPEnabled,
11639 pWextState->roamProfile.MFPRequired,
11640 pWextState->roamProfile.MFPCapable);
11641 return -EINVAL;
11642 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011643
Krunal Soni3091bcc2016-06-23 12:28:21 -070011644 if (true == cds_is_connection_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011645 hdd_err("Connection refused: conn in progress");
11646 return -EINVAL;
11647 }
11648
Krunal Soni31949422016-07-29 17:17:53 -070011649 /*
11650 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011651 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070011652 * enhancements, the supplicant is not issuing the scan command
11653 * now. So the unicast frames which are sent from the host are
11654 * not having the additional IEs. If it is P2P CLIENT and there
11655 * is no additional IE present in roamProfile, then use the
11656 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011657 */
11658
Krunal Sonib4326f22016-03-10 13:05:51 -080011659 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011660 (!pRoamProfile->pAddIEScan)) {
11661 pRoamProfile->pAddIEScan =
11662 &pAdapter->scan_info.scanAddIE.addIEdata[0];
11663 pRoamProfile->nAddIEScanLength =
11664 pAdapter->scan_info.scanAddIE.length;
11665 }
11666 /*
11667 * When policy manager is enabled from ini file, we shouldn't
11668 * check for other concurrency rules.
11669 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070011670 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080011671 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011672 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011673 pAdapter, pRoamProfile, &roamId))
11674 return 0;
11675 }
11676
Krunal Soni3091bcc2016-06-23 12:28:21 -070011677 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011678 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
11679 pRoamProfile))) {
11680 hdd_err("sap-sta conc will fail, can't allow sta");
11681 hdd_conn_set_connection_state(pAdapter,
11682 eConnectionState_NotConnected);
11683 return -ENOMEM;
11684 }
11685
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011686 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011687 if (!sme_config) {
11688 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011689 hdd_conn_set_connection_state(pAdapter,
11690 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011691 return -ENOMEM;
11692 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011693 sme_get_config_param(pHddCtx->hHal, sme_config);
11694 /* These values are not sessionized. So, any change in these SME
11695 * configs on an older or parallel interface will affect the
11696 * cb mode. So, restoring the default INI params before starting
11697 * interfaces such as sta, cli etc.,
11698 */
11699 sme_config->csrConfig.channelBondingMode5GHz =
11700 pHddCtx->config->nChannelBondingMode5GHz;
11701 sme_config->csrConfig.channelBondingMode24GHz =
11702 pHddCtx->config->nChannelBondingMode24GHz;
11703 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011704 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053011705 /*
11706 * Change conn_state to connecting before sme_roam_connect(),
11707 * because sme_roam_connect() has a direct path to call
11708 * hdd_sme_roam_callback(), which will change the conn_state
11709 * If direct path, conn_state will be accordingly changed to
11710 * NotConnected or Associated by either
11711 * hdd_association_completion_handler() or
11712 * hdd_dis_connect_handler() in sme_RoamCallback()if
11713 * sme_RomConnect is to be queued,
11714 * Connecting state will remain until it is completed.
11715 *
11716 * If connection state is not changed, connection state will
11717 * remain in eConnectionState_NotConnected state.
11718 * In hdd_association_completion_handler, "hddDisconInProgress"
11719 * is set to true if conn state is
11720 * eConnectionState_NotConnected.
11721 * If "hddDisconInProgress" is set to true then cfg80211 layer
11722 * is not informed of connect result indication which
11723 * is an issue.
11724 */
11725 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053011726 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053011727 hdd_conn_set_connection_state(pAdapter,
11728 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011729
Komal Seelama89be8d2016-09-29 11:09:26 +053011730 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
11731 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011732 status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
11733 pAdapter->sessionId, pRoamProfile,
11734 &roamId);
11735
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011736 if ((QDF_STATUS_SUCCESS != status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080011737 (QDF_STA_MODE == pAdapter->device_mode ||
11738 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011739 hdd_err("sme_roam_connect (session %d) failed with "
11740 "status %d. -> NotConnected",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011741 pAdapter->sessionId, status);
11742 /* change back to NotAssociated */
11743 hdd_conn_set_connection_state(pAdapter,
11744 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053011745 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
11746 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011747 }
11748
11749 pRoamProfile->ChannelInfo.ChannelList = NULL;
11750 pRoamProfile->ChannelInfo.numOfChannels = 0;
11751
Nitesh Shah044fd672016-10-13 18:53:25 +053011752 if (!QDF_IS_STATUS_SUCCESS(
11753 wma_get_current_hw_mode(&hw_mode))) {
11754 hdd_err("wma_get_current_hw_mode failed");
11755 return status;
11756 }
11757
11758 if ((QDF_STA_MODE == pAdapter->device_mode)
11759 && hw_mode.dbs_cap) {
11760 cds_get_channel_from_scan_result(pAdapter,
11761 pRoamProfile, &channel);
11762 if (channel)
11763 cds_checkn_update_hw_mode_single_mac_mode
11764 (channel);
11765 }
11766
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011767 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011768 hdd_err("No valid Roam profile");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011769 return -EINVAL;
11770 }
11771 EXIT();
11772 return status;
11773}
11774
11775/**
11776 * wlan_hdd_cfg80211_set_auth_type() - set auth type
11777 * @pAdapter: Pointer to adapter
11778 * @auth_type: Auth type
11779 *
11780 * This function is used to set the authentication type (OPEN/SHARED).
11781 *
11782 * Return: 0 for success, non-zero for failure
11783 */
11784static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
11785 enum nl80211_auth_type auth_type)
11786{
11787 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11788 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11789
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011790 /*set authentication type */
11791 switch (auth_type) {
11792 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011793 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011794 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
11795 break;
11796
11797 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011798 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011799 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011800 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
11801 break;
11802
11803 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011804 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011805 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
11806 break;
11807#ifdef FEATURE_WLAN_ESE
11808 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011809 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011810 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
11811 break;
11812#endif
11813
11814 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011815 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011816 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
11817 return -EINVAL;
11818 }
11819
11820 pWextState->roamProfile.AuthType.authType[0] =
11821 pHddStaCtx->conn_info.authType;
11822 return 0;
11823}
11824
11825/**
11826 * wlan_hdd_set_akm_suite() - set key management type
11827 * @pAdapter: Pointer to adapter
11828 * @key_mgmt: Key management type
11829 *
11830 * This function is used to set the key mgmt type(PSK/8021x).
11831 *
11832 * Return: 0 for success, non-zero for failure
11833 */
11834static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
11835{
11836 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11837
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011838#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
11839#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
11840 /*set key mgmt type */
11841 switch (key_mgmt) {
11842 case WLAN_AKM_SUITE_PSK:
11843 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011844 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011845 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011846 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
11847 break;
11848
11849 case WLAN_AKM_SUITE_8021X_SHA256:
11850 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011851 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011852 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011853 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11854 break;
11855#ifdef FEATURE_WLAN_ESE
11856#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
11857#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
11858 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011859 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011860 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
11861 break;
11862#endif
11863#ifndef WLAN_AKM_SUITE_OSEN
11864#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
11865#endif
11866 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011867 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011868 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11869 break;
11870
11871 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011872 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011873 return -EINVAL;
11874
11875 }
11876 return 0;
11877}
11878
11879/**
11880 * wlan_hdd_cfg80211_set_cipher() - set encryption type
11881 * @pAdapter: Pointer to adapter
11882 * @cipher: Cipher type
11883 * @ucast: Unicast flag
11884 *
11885 * This function is used to set the encryption type
11886 * (NONE/WEP40/WEP104/TKIP/CCMP).
11887 *
11888 * Return: 0 for success, non-zero for failure
11889 */
11890static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
11891 u32 cipher, bool ucast)
11892{
11893 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11894 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11895 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11896
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011897 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080011898 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011899 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11900 } else {
11901
11902 /*set encryption method */
11903 switch (cipher) {
11904 case IW_AUTH_CIPHER_NONE:
11905 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11906 break;
11907
11908 case WLAN_CIPHER_SUITE_WEP40:
11909 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
11910 break;
11911
11912 case WLAN_CIPHER_SUITE_WEP104:
11913 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
11914 break;
11915
11916 case WLAN_CIPHER_SUITE_TKIP:
11917 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
11918 break;
11919
11920 case WLAN_CIPHER_SUITE_CCMP:
11921 encryptionType = eCSR_ENCRYPT_TYPE_AES;
11922 break;
11923#ifdef FEATURE_WLAN_WAPI
11924 case WLAN_CIPHER_SUITE_SMS4:
11925 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
11926 break;
11927#endif
11928
11929#ifdef FEATURE_WLAN_ESE
11930 case WLAN_CIPHER_SUITE_KRK:
11931 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
11932 break;
11933#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11934 case WLAN_CIPHER_SUITE_BTK:
11935 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
11936 break;
11937#endif
11938#endif
11939 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011940 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011941 return -EOPNOTSUPP;
11942 }
11943 }
11944
11945 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011946 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011947 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
11948 pWextState->roamProfile.EncryptionType.numEntries = 1;
11949 pWextState->roamProfile.EncryptionType.encryptionType[0] =
11950 encryptionType;
11951 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011952 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011953 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
11954 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
11955 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
11956 encryptionType;
11957 }
11958
11959 return 0;
11960}
11961
11962/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011963 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
11964 * @wext_state: Pointer to wext state
11965 * @gen_ie: Pointer to IE data
11966 * @len: length of IE data
11967 *
11968 * Return: 0 for success, non-zero for failure
11969 */
11970static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
11971 const uint8_t *gen_ie, uint16_t len)
11972{
11973 uint16_t cur_add_ie_len =
11974 wext_state->assocAddIE.length;
11975
11976 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11977 (wext_state->assocAddIE.length + len)) {
11978 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
11979 QDF_ASSERT(0);
11980 return -ENOMEM;
11981 }
11982 memcpy(wext_state->assocAddIE.addIEdata +
11983 cur_add_ie_len, gen_ie, len);
11984 wext_state->assocAddIE.length += len;
11985
11986 wext_state->roamProfile.pAddIEAssoc =
11987 wext_state->assocAddIE.addIEdata;
11988 wext_state->roamProfile.nAddIEAssocLength =
11989 wext_state->assocAddIE.length;
11990 return 0;
11991}
11992
11993/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011994 * wlan_hdd_cfg80211_set_ie() - set IEs
11995 * @pAdapter: Pointer to adapter
11996 * @ie: Pointer ot ie
11997 * @ie: IE length
11998 *
11999 * Return: 0 for success, non-zero for failure
12000 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012001static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012002 size_t ie_len)
12003{
12004 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12005 const uint8_t *genie = ie;
12006 uint16_t remLen = ie_len;
12007#ifdef FEATURE_WLAN_WAPI
12008 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
12009 u16 *tmp;
12010 uint16_t akmsuiteCount;
12011 int *akmlist;
12012#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012013 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012014
12015 /* clear previous assocAddIE */
12016 pWextState->assocAddIE.length = 0;
12017 pWextState->roamProfile.bWPSAssociation = false;
12018 pWextState->roamProfile.bOSENAssociation = false;
12019
12020 while (remLen >= 2) {
12021 uint16_t eLen = 0;
12022 uint8_t elementId;
12023 elementId = *genie++;
12024 eLen = *genie++;
12025 remLen -= 2;
12026
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012027 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012028
12029 switch (elementId) {
12030 case DOT11F_EID_WPA:
12031 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 -070012032 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012033 return -EINVAL;
12034 } else if (0 ==
12035 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
12036 uint16_t curAddIELen =
12037 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012038 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012039
12040 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12041 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012042 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012043 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012044 return -ENOMEM;
12045 }
12046 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
12047 memcpy(pWextState->assocAddIE.addIEdata +
12048 curAddIELen, genie - 2, eLen + 2);
12049 pWextState->assocAddIE.length += eLen + 2;
12050
12051 pWextState->roamProfile.bWPSAssociation = true;
12052 pWextState->roamProfile.pAddIEAssoc =
12053 pWextState->assocAddIE.addIEdata;
12054 pWextState->roamProfile.nAddIEAssocLength =
12055 pWextState->assocAddIE.length;
12056 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012057 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012058 memset(pWextState->WPARSNIE, 0,
12059 MAX_WPA_RSN_IE_LEN);
12060 memcpy(pWextState->WPARSNIE, genie - 2,
12061 (eLen + 2));
12062 pWextState->roamProfile.pWPAReqIE =
12063 pWextState->WPARSNIE;
12064 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
12065 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
12066 P2P_OUI_TYPE_SIZE))) {
12067 uint16_t curAddIELen =
12068 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012069 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012070
12071 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12072 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012073 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012074 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012075 return -ENOMEM;
12076 }
12077 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
12078 memcpy(pWextState->assocAddIE.addIEdata +
12079 curAddIELen, genie - 2, eLen + 2);
12080 pWextState->assocAddIE.length += eLen + 2;
12081
12082 pWextState->roamProfile.pAddIEAssoc =
12083 pWextState->assocAddIE.addIEdata;
12084 pWextState->roamProfile.nAddIEAssocLength =
12085 pWextState->assocAddIE.length;
12086 }
12087#ifdef WLAN_FEATURE_WFD
12088 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
12089 WFD_OUI_TYPE_SIZE)) &&
12090 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080012091 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012092 pAdapter->device_mode)) {
12093 uint16_t curAddIELen =
12094 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012095 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012096
12097 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12098 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012099 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012100 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012101 return -ENOMEM;
12102 }
12103 /* WFD IE is saved to Additional IE ; it should
12104 * be accumulated to handle WPS IE + P2P IE +
12105 * WFD IE */
12106 memcpy(pWextState->assocAddIE.addIEdata +
12107 curAddIELen, genie - 2, eLen + 2);
12108 pWextState->assocAddIE.length += eLen + 2;
12109
12110 pWextState->roamProfile.pAddIEAssoc =
12111 pWextState->assocAddIE.addIEdata;
12112 pWextState->roamProfile.nAddIEAssocLength =
12113 pWextState->assocAddIE.length;
12114 }
12115#endif
12116 /* Appending HS 2.0 Indication Element in Assiciation Request */
12117 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
12118 HS20_OUI_TYPE_SIZE))) {
12119 uint16_t curAddIELen =
12120 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012121 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012122
12123 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12124 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012125 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012126 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012127 return -ENOMEM;
12128 }
12129 memcpy(pWextState->assocAddIE.addIEdata +
12130 curAddIELen, genie - 2, eLen + 2);
12131 pWextState->assocAddIE.length += eLen + 2;
12132
12133 pWextState->roamProfile.pAddIEAssoc =
12134 pWextState->assocAddIE.addIEdata;
12135 pWextState->roamProfile.nAddIEAssocLength =
12136 pWextState->assocAddIE.length;
12137 }
12138 /* Appending OSEN Information Element in Assiciation Request */
12139 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
12140 OSEN_OUI_TYPE_SIZE))) {
12141 uint16_t curAddIELen =
12142 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012143 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012144
12145 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12146 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012147 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012148 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012149 return -ENOMEM;
12150 }
12151 memcpy(pWextState->assocAddIE.addIEdata +
12152 curAddIELen, genie - 2, eLen + 2);
12153 pWextState->assocAddIE.length += eLen + 2;
12154
12155 pWextState->roamProfile.bOSENAssociation = true;
12156 pWextState->roamProfile.pAddIEAssoc =
12157 pWextState->assocAddIE.addIEdata;
12158 pWextState->roamProfile.nAddIEAssocLength =
12159 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012160 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
12161 MBO_OUI_TYPE_SIZE))){
12162 hdd_info("Set MBO IE(len %d)", eLen + 2);
12163 status = wlan_hdd_add_assoc_ie(pWextState,
12164 genie - 2, eLen + 2);
12165 if (status)
12166 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012167 } else {
12168 uint16_t add_ie_len =
12169 pWextState->assocAddIE.length;
12170
12171 hdd_info("Set OSEN IE(len %d)", eLen + 2);
12172
12173 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12174 (pWextState->assocAddIE.length + eLen)) {
12175 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012176 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012177 return -ENOMEM;
12178 }
12179
12180 memcpy(pWextState->assocAddIE.addIEdata +
12181 add_ie_len, genie - 2, eLen + 2);
12182 pWextState->assocAddIE.length += eLen + 2;
12183
12184 pWextState->roamProfile.pAddIEAssoc =
12185 pWextState->assocAddIE.addIEdata;
12186 pWextState->roamProfile.nAddIEAssocLength =
12187 pWextState->assocAddIE.length;
12188 }
12189 break;
12190 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012191 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012192 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
12193 memcpy(pWextState->WPARSNIE, genie - 2,
12194 (eLen + 2));
12195 pWextState->roamProfile.pRSNReqIE =
12196 pWextState->WPARSNIE;
12197 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
12198 break;
12199 /*
12200 * Appending Extended Capabilities with Interworking bit set
12201 * in Assoc Req.
12202 *
12203 * In assoc req this EXT Cap will only be taken into account if
12204 * interworkingService bit is set to 1. Currently
12205 * driver is only interested in interworkingService capability
12206 * from supplicant. If in future any other EXT Cap info is
12207 * required from supplicat, it needs to be handled while
12208 * sending Assoc Req in LIM.
12209 */
12210 case DOT11F_EID_EXTCAP:
12211 {
12212 uint16_t curAddIELen =
12213 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012214 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012215
12216 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12217 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012218 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012219 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012220 return -ENOMEM;
12221 }
12222 memcpy(pWextState->assocAddIE.addIEdata +
12223 curAddIELen, genie - 2, eLen + 2);
12224 pWextState->assocAddIE.length += eLen + 2;
12225
12226 pWextState->roamProfile.pAddIEAssoc =
12227 pWextState->assocAddIE.addIEdata;
12228 pWextState->roamProfile.nAddIEAssocLength =
12229 pWextState->assocAddIE.length;
12230 break;
12231 }
12232#ifdef FEATURE_WLAN_WAPI
12233 case WLAN_EID_WAPI:
12234 /* Setting WAPI Mode to ON=1 */
12235 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012236 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012237 tmp = (u16 *) ie;
12238 tmp = tmp + 2; /* Skip element Id and Len, Version */
12239 akmsuiteCount = WPA_GET_LE16(tmp);
12240 tmp = tmp + 1;
12241 akmlist = (int *)(tmp);
12242 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
12243 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
12244 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012245 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012246 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012247 return -EINVAL;
12248 }
12249
12250 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012251 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012252 pAdapter->wapi_info.wapiAuthMode =
12253 WAPI_AUTH_MODE_PSK;
12254 }
12255 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012256 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012257 pAdapter->wapi_info.wapiAuthMode =
12258 WAPI_AUTH_MODE_CERT;
12259 }
12260 break;
12261#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012262 case DOT11F_EID_SUPPOPERATINGCLASSES:
12263 {
12264 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
12265 status = wlan_hdd_add_assoc_ie(pWextState,
12266 genie - 2, eLen + 2);
12267 if (status)
12268 return status;
12269 break;
12270 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012271 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012272 hdd_err("Set UNKNOWN IE %X", elementId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012273 /* when Unknown IE is received we should break and continue
12274 * to the next IE in the buffer instead we were returning
12275 * so changing this to break */
12276 break;
12277 }
12278 genie += eLen;
12279 remLen -= eLen;
12280 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012281 return 0;
12282}
12283
12284/**
12285 * hdd_is_wpaie_present() - check for WPA ie
12286 * @ie: Pointer to ie
12287 * @ie_len: Ie length
12288 *
12289 * Parse the received IE to find the WPA IE
12290 *
12291 * Return: true if wpa ie is found else false
12292 */
12293static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
12294{
12295 uint8_t eLen = 0;
12296 uint16_t remLen = ie_len;
12297 uint8_t elementId = 0;
12298
12299 while (remLen >= 2) {
12300 elementId = *ie++;
12301 eLen = *ie++;
12302 remLen -= 2;
12303 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012304 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012305 return false;
12306 }
12307 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
12308 /* OUI - 0x00 0X50 0XF2
12309 * WPA Information Element - 0x01
12310 * WPA version - 0x01
12311 */
12312 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
12313 return true;
12314 }
12315 ie += eLen;
12316 remLen -= eLen;
12317 }
12318 return false;
12319}
12320
12321/**
12322 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
12323 * @pAdapter: Pointer to adapter
12324 * @req: Pointer to security parameters
12325 *
12326 * Return: 0 for success, non-zero for failure
12327 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012328static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
12329 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012330{
12331 int status = 0;
12332 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12333 ENTER();
12334
12335 /*set wpa version */
12336 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
12337
12338 if (req->crypto.wpa_versions) {
12339 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
12340 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
12341 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
12342 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12343 }
12344 }
12345
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012346 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012347
12348 /*set authentication type */
12349 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
12350
12351 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012352 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012353 return status;
12354 }
12355
12356 /*set key mgmt type */
12357 if (req->crypto.n_akm_suites) {
12358 status =
12359 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
12360 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012361 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012362 return status;
12363 }
12364 }
12365
12366 /*set pairwise cipher type */
12367 if (req->crypto.n_ciphers_pairwise) {
12368 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
12369 req->crypto.
12370 ciphers_pairwise[0],
12371 true);
12372 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012373 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012374 return status;
12375 }
12376 } else {
12377 /*Reset previous cipher suite to none */
12378 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
12379 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012380 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012381 return status;
12382 }
12383 }
12384
12385 /*set group cipher type */
12386 status =
12387 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
12388 false);
12389
12390 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012391 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012392 return status;
12393 }
12394#ifdef WLAN_FEATURE_11W
12395 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
12396#endif
12397
12398 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
12399 if (req->ie_len) {
12400 status =
12401 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
12402 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012403 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012404 return status;
12405 }
12406 }
12407
12408 /*incase of WEP set default key information */
12409 if (req->key && req->key_len) {
12410 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
12411 || (WLAN_CIPHER_SUITE_WEP104 ==
12412 req->crypto.ciphers_pairwise[0])
12413 ) {
12414 if (IW_AUTH_KEY_MGMT_802_1X
12415 ==
12416 (pWextState->
12417 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012418 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012419 return -EOPNOTSUPP;
12420 } else {
12421 u8 key_len = req->key_len;
12422 u8 key_idx = req->key_idx;
12423
12424 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
12425 key_len)
12426 && (CSR_MAX_NUM_KEY > key_idx)
12427 ) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012428 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012429 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012430 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012431 Keys.
12432 KeyMaterial[key_idx][0],
12433 req->key, key_len);
12434 pWextState->roamProfile.Keys.
12435 KeyLength[key_idx] = (u8) key_len;
12436 pWextState->roamProfile.Keys.
12437 defaultIndex = (u8) key_idx;
12438 }
12439 }
12440 }
12441 }
12442
12443 return status;
12444}
12445
12446/**
12447 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
12448 * @pAdapter: Pointer to adapter
12449 *
12450 * This function is used to disconnect from previous connection
12451 *
12452 * Return: 0 for success, non-zero for failure
12453 */
12454static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
12455{
12456 unsigned long rc;
12457 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012458 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012459
12460 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12461
Jeff Johnson9edf9572016-10-03 15:24:49 -070012462 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053012463 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
12464 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
12465 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012466 hdd_conn_set_connection_state(pAdapter,
12467 eConnectionState_Disconnecting);
12468 /* Issue disconnect to CSR */
12469 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012470
12471 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12472 pAdapter->sessionId,
12473 eCSR_DISCONNECT_REASON_UNSPECIFIED);
12474 /*
12475 * Wait here instead of returning directly, this will block the
12476 * next connect command and allow processing of the scan for
12477 * ssid and the previous connect command in CSR. Else we might
12478 * hit some race conditions leading to SME and HDD out of sync.
12479 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012480 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012481 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
12482 } else if (0 != status) {
12483 hdd_err("csrRoamDisconnect failure, returned %d",
12484 (int)status);
12485 pHddStaCtx->staDebugState = status;
12486 result = -EINVAL;
12487 goto disconnected;
12488 }
12489
12490 rc = wait_for_completion_timeout(
12491 &pAdapter->disconnect_comp_var,
12492 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012493 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012494 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
12495 pAdapter->sessionId, pHddStaCtx->staDebugState);
12496 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012497 }
12498 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012499 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012500 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012501 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012502 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012503 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012504 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012505 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012506 }
12507 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012508disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012509 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12510 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012511}
12512
12513/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012514 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
12515 * @adapter: Pointer to the HDD adapter
12516 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070012517 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012518 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012519 * This function will start reassociation if prev_bssid is set and bssid/
12520 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012521 *
Naveen Rawat07332902016-07-27 09:13:17 -070012522 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012523 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053012524#if defined(CFG80211_CONNECT_PREV_BSSID) || \
12525 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070012526static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12527 struct cfg80211_connect_params *req,
12528 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012529{
Naveen Rawat07332902016-07-27 09:13:17 -070012530 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012531 const uint8_t *bssid = NULL;
12532 uint16_t channel = 0;
12533
12534 if (req->bssid)
12535 bssid = req->bssid;
12536 else if (req->bssid_hint)
12537 bssid = req->bssid_hint;
12538
12539 if (req->channel)
12540 channel = req->channel->hw_value;
12541 else if (req->channel_hint)
12542 channel = req->channel_hint->hw_value;
12543
12544 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070012545 reassoc = true;
12546 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012547 channel, MAC_ADDR_ARRAY(bssid));
12548 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012549 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070012550 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012551 }
Naveen Rawat07332902016-07-27 09:13:17 -070012552 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012553}
12554#else
Naveen Rawat07332902016-07-27 09:13:17 -070012555static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12556 struct cfg80211_connect_params *req,
12557 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012558{
Naveen Rawat07332902016-07-27 09:13:17 -070012559 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012560}
12561#endif
12562
12563/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012564 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
12565 * @wiphy: Pointer to wiphy
12566 * @dev: Pointer to network device
12567 * @req: Pointer to cfg80211 connect request
12568 *
12569 * This function is used to start the association process
12570 *
12571 * Return: 0 for success, non-zero for failure
12572 */
12573static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12574 struct net_device *ndev,
12575 struct cfg80211_connect_params *req)
12576{
12577 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012578 u16 channel;
12579#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
12580 const u8 *bssid_hint = req->bssid_hint;
12581#else
12582 const u8 *bssid_hint = NULL;
12583#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012584 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12585 hdd_context_t *pHddCtx;
12586
12587 ENTER();
12588
Anurag Chouhan6d760662016-02-20 16:05:43 +053012589 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012590 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012591 return -EINVAL;
12592 }
12593
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012594 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12595 hdd_err("invalid session id: %d", pAdapter->sessionId);
12596 return -EINVAL;
12597 }
12598
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012599 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012600 TRACE_CODE_HDD_CFG80211_CONNECT,
12601 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012602 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012603 hdd_device_mode_to_string(pAdapter->device_mode),
12604 pAdapter->device_mode);
12605
Krunal Sonib4326f22016-03-10 13:05:51 -080012606 if (pAdapter->device_mode != QDF_STA_MODE &&
12607 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012608 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012609 hdd_device_mode_to_string(pAdapter->device_mode),
12610 pAdapter->device_mode);
12611 return -EINVAL;
12612 }
12613
12614 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12615 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012616 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012617 return -EINVAL;
12618 }
12619
12620 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012621 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012622 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012623
Naveen Rawat07332902016-07-27 09:13:17 -070012624 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012625 return status;
12626
Agrawal Ashishf156e942016-08-04 14:54:47 +053012627 wlan_hdd_disable_roaming(pAdapter);
12628
12629 /* Try disconnecting if already in connected state */
12630 status = wlan_hdd_try_disconnect(pAdapter);
12631 if (0 > status) {
12632 hdd_err("Failed to disconnect the existing connection");
12633 return -EALREADY;
12634 }
12635
12636 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012637 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012638 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012639 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012640 pAdapter->device_mode),
12641 req->channel->hw_value, HW_MODE_20_MHZ)) {
12642 hdd_err("This concurrency combination is not allowed");
12643 return -ECONNREFUSED;
12644 }
12645 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012646 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012647 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012648 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
12649 hdd_err("This concurrency combination is not allowed");
12650 return -ECONNREFUSED;
12651 }
12652 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012653
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012654 /*initialise security parameters */
12655 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
12656
12657 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012658 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012659 return status;
12660 }
12661
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012662 if (req->channel)
12663 channel = req->channel->hw_value;
12664 else
12665 channel = 0;
12666 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
12667 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012668 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012669 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012670 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012671 return status;
12672 }
12673 EXIT();
12674 return status;
12675}
12676
12677/**
12678 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
12679 * @wiphy: Pointer to wiphy
12680 * @dev: Pointer to network device
12681 * @req: Pointer to cfg80211 connect request
12682 *
12683 * Return: 0 for success, non-zero for failure
12684 */
12685static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12686 struct net_device *ndev,
12687 struct cfg80211_connect_params *req)
12688{
12689 int ret;
12690 cds_ssr_protect(__func__);
12691 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
12692 cds_ssr_unprotect(__func__);
12693
12694 return ret;
12695}
12696
12697/**
12698 * wlan_hdd_disconnect() - hdd disconnect api
12699 * @pAdapter: Pointer to adapter
12700 * @reason: Disconnect reason code
12701 *
12702 * This function is used to issue a disconnect request to SME
12703 *
12704 * Return: 0 for success, non-zero for failure
12705 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012706static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012707{
12708 int status, result = 0;
12709 unsigned long rc;
12710 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12711 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12712
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012713 ENTER();
12714
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012715 status = wlan_hdd_validate_context(pHddCtx);
12716
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012717 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012718 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012719
12720 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012721 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012722 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
12723 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012724 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012725 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
12726 INIT_COMPLETION(pAdapter->disconnect_comp_var);
12727
12728 /*issue disconnect */
12729
12730 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12731 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053012732 /*
12733 * Wait here instead of returning directly, this will block the next
12734 * connect command and allow processing of the scan for ssid and
12735 * the previous connect command in CSR. Else we might hit some
12736 * race conditions leading to SME and HDD out of sync.
12737 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012738 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012739 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012740 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012741 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012742 (int)status);
12743 pHddStaCtx->staDebugState = status;
12744 result = -EINVAL;
12745 goto disconnected;
12746 }
12747 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
12748 msecs_to_jiffies
12749 (WLAN_WAIT_TIME_DISCONNECT));
12750
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012751 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012752 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012753 result = -ETIMEDOUT;
12754 }
12755disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012756 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12757#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
12758 /* Sending disconnect event to userspace for kernel version < 3.11
12759 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
12760 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012761 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053012762 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
12763 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012764#endif
12765
12766 return result;
12767}
12768
12769/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012770 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
12771 * @reason: ieee80211 reason code.
12772 *
12773 * This utility function helps log string conversion of reason code.
12774 *
12775 * Return: string conversion of reason code, if match found;
12776 * "Unknown" otherwise.
12777 */
12778static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
12779{
12780 switch (reason) {
12781 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
12782 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
12783 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
12784 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
12785 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
12786 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
12787 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
12788 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
12789 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
12790 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
12791 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
12792 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
12793 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
12794 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
12795 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
12796 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
12797 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
12798 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
12799 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
12800 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
12801 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
12802 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
12803 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
12804 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
12805 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
12806 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
12807 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
12808 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
12809 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
12810 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
12811 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
12812 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
12813 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
12814 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
12815 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
12816 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
12817 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
12818 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
12819 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
12820 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
12821 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
12822 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
12823 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
12824 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
12825 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
12826 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
12827 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
12828 default:
12829 return "Unknown";
12830 }
12831}
12832
12833/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012834 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12835 * @wiphy: Pointer to wiphy
12836 * @dev: Pointer to network device
12837 * @reason: Disconnect reason code
12838 *
12839 * This function is used to issue a disconnect request to SME
12840 *
12841 * Return: 0 for success, non-zero for failure
12842 */
12843static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12844 struct net_device *dev, u16 reason)
12845{
12846 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12847 int status;
12848 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12849 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12850#ifdef FEATURE_WLAN_TDLS
12851 uint8_t staIdx;
12852#endif
12853
12854 ENTER();
12855
Anurag Chouhan6d760662016-02-20 16:05:43 +053012856 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012857 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012858 return -EINVAL;
12859 }
12860
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012861 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12862 hdd_err("invalid session id: %d", pAdapter->sessionId);
12863 return -EINVAL;
12864 }
12865
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012866 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012867 TRACE_CODE_HDD_CFG80211_DISCONNECT,
12868 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012869 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012870 hdd_device_mode_to_string(pAdapter->device_mode),
12871 pAdapter->device_mode, reason);
12872
12873 status = wlan_hdd_validate_context(pHddCtx);
12874
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012875 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012876 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012877
12878 /* Issue disconnect request to SME, if station is in connected state */
12879 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
12880 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
12881 eCsrRoamDisconnectReason reasonCode =
12882 eCSR_DISCONNECT_REASON_UNSPECIFIED;
12883 hdd_scaninfo_t *pScanInfo;
12884
12885 switch (reason) {
12886 case WLAN_REASON_MIC_FAILURE:
12887 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
12888 break;
12889
12890 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
12891 case WLAN_REASON_DISASSOC_AP_BUSY:
12892 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
12893 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
12894 break;
12895
12896 case WLAN_REASON_PREV_AUTH_NOT_VALID:
12897 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
12898 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
12899 break;
12900
12901 case WLAN_REASON_DEAUTH_LEAVING:
12902 reasonCode =
12903 pHddCtx->config->
12904 gEnableDeauthToDisassocMap ?
12905 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
12906 eCSR_DISCONNECT_REASON_DEAUTH;
12907 break;
12908 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
12909 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
12910 break;
12911 default:
12912 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
12913 break;
12914 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012915 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012916 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012917 pScanInfo = &pAdapter->scan_info;
12918 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012919 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012920 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
12921 eCSR_SCAN_ABORT_DEFAULT);
12922 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053012923 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012924#ifdef FEATURE_WLAN_TDLS
12925 /* First clean up the tdls peers if any */
12926 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
12927 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
12928 pAdapter->sessionId)
12929 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
12930 uint8_t *mac;
12931 mac =
12932 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012933 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
12934 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012935 pHddCtx->tdlsConnInfo[staIdx].staId,
12936 pAdapter->sessionId,
12937 MAC_ADDR_ARRAY(mac));
12938 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
12939 (pAdapter),
12940 pAdapter->sessionId, mac);
12941 }
12942 }
12943#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012944 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012945 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012946 hdd_info("Disconnect request from user space with reason: %s",
12947 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012948 status = wlan_hdd_disconnect(pAdapter, reasonCode);
12949 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012950 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012951 return -EINVAL;
12952 }
12953 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012954 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012955 pHddStaCtx->conn_info.connState);
12956 }
12957
12958 return status;
12959}
12960
12961/**
12962 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12963 * @wiphy: Pointer to wiphy
12964 * @dev: Pointer to network device
12965 * @reason: Disconnect reason code
12966 *
12967 * Return: 0 for success, non-zero for failure
12968 */
12969static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12970 struct net_device *dev, u16 reason)
12971{
12972 int ret;
12973 cds_ssr_protect(__func__);
12974 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
12975 cds_ssr_unprotect(__func__);
12976
12977 return ret;
12978}
12979
12980/**
12981 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
12982 * @pAdapter: Pointer to adapter
12983 * @param: Pointer to IBSS parameters
12984 *
12985 * This function is used to initialize the security settings in IBSS mode
12986 *
12987 * Return: 0 for success, non-zero for failure
12988 */
12989static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
12990 struct cfg80211_ibss_params
12991 *params)
12992{
12993 int status = 0;
12994 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12995 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12996 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12997
12998 ENTER();
12999
13000 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013001 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013002 pHddStaCtx->ibss_enc_key_installed = 0;
13003
13004 if (params->ie_len && (NULL != params->ie)) {
13005 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
13006 params->ie_len, WLAN_EID_RSN)) {
13007 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13008 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13009 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
13010 tDot11fIEWPA dot11WPAIE;
13011 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13012 u8 *ie;
13013
13014 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
13015 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
13016 params->ie_len,
13017 DOT11F_EID_WPA);
13018 if (NULL != ie) {
13019 pWextState->wpaVersion =
13020 IW_AUTH_WPA_VERSION_WPA;
13021 /* Unpack the WPA IE */
13022 /* Skip past the EID byte and length byte - and four byte WiFi OUI */
13023 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
13024 &ie[2 + 4],
13025 ie[1] - 4, &dot11WPAIE);
13026 /*Extract the multicast cipher, the encType for unicast
13027 cipher for wpa-none is none */
13028 encryptionType =
13029 hdd_translate_wpa_to_csr_encryption_type
13030 (dot11WPAIE.multicast_cipher);
13031 }
13032 }
13033
13034 status =
13035 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
13036 params->ie_len);
13037
13038 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013039 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013040 return status;
13041 }
13042 }
13043
13044 pWextState->roamProfile.AuthType.authType[0] =
13045 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13046
13047 if (params->privacy) {
13048 /* Security enabled IBSS, At this time there is no information
13049 * available about the security paramters, so initialise the
13050 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
13051 * The correct security parameters will be updated later in
13052 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
13053 * set inorder enable privacy bit in beacons
13054 */
13055
13056 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
13057 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013058 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013059 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13060 pWextState->roamProfile.EncryptionType.numEntries = 1;
13061 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13062 encryptionType;
13063 return status;
13064}
13065
13066/**
13067 * __wlan_hdd_cfg80211_join_ibss() - join ibss
13068 * @wiphy: Pointer to wiphy
13069 * @dev: Pointer to network device
13070 * @param: Pointer to IBSS join parameters
13071 *
13072 * This function is used to create/join an IBSS network
13073 *
13074 * Return: 0 for success, non-zero for failure
13075 */
13076static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13077 struct net_device *dev,
13078 struct cfg80211_ibss_params *params)
13079{
13080 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13081 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13082 tCsrRoamProfile *pRoamProfile;
13083 int status;
13084 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13085 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053013086 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013087 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013088
13089 ENTER();
13090
Anurag Chouhan6d760662016-02-20 16:05:43 +053013091 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013092 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013093 return -EINVAL;
13094 }
13095
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013096 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13097 hdd_err("invalid session id: %d", pAdapter->sessionId);
13098 return -EINVAL;
13099 }
13100
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013101 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013102 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
13103 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013104 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013105 hdd_device_mode_to_string(pAdapter->device_mode),
13106 pAdapter->device_mode);
13107
13108 status = wlan_hdd_validate_context(pHddCtx);
13109
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013110 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013111 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013112
13113 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053013114 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013115 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
13116 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
13117 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13118 int indx;
13119
13120 /* Get channel number */
13121 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013122 params->
13123 chandef.
13124 chan->
13125 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013126
13127 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
13128 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013129 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013130 return -EOPNOTSUPP;
13131 }
13132
13133 for (indx = 0; indx < numChans; indx++) {
13134 if (channelNum == validChan[indx]) {
13135 break;
13136 }
13137 }
13138 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013139 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013140 return -EINVAL;
13141 }
13142 }
13143
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013144 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013145 HW_MODE_20_MHZ)) {
13146 hdd_err("This concurrency combination is not allowed");
13147 return -ECONNREFUSED;
13148 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013149
Krunal Soni3091bcc2016-06-23 12:28:21 -070013150 status = qdf_reset_connection_update();
13151 if (!QDF_IS_STATUS_SUCCESS(status))
13152 hdd_err("ERR: clear event failed");
13153
13154 status = cds_current_connections_update(pAdapter->sessionId,
13155 channelNum,
13156 SIR_UPDATE_REASON_JOIN_IBSS);
13157 if (QDF_STATUS_E_FAILURE == status) {
13158 hdd_err("ERROR: connections update failed!!");
13159 return -EINVAL;
13160 }
13161
13162 if (QDF_STATUS_SUCCESS == status) {
13163 status = qdf_wait_for_connection_update();
13164 if (!QDF_IS_STATUS_SUCCESS(status)) {
13165 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013166 return -EINVAL;
13167 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013168 }
13169
13170 /*Try disconnecting if already in connected state */
13171 status = wlan_hdd_try_disconnect(pAdapter);
13172 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013173 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013174 return -EALREADY;
13175 }
13176
13177 pRoamProfile = &pWextState->roamProfile;
13178
13179 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013180 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013181 return -EINVAL;
13182 }
13183
13184 /* enable selected protection checks in IBSS mode */
13185 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
13186
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013187 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013188 WNI_CFG_IBSS_ATIM_WIN_SIZE,
13189 pHddCtx->config->
13190 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013191 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013192 }
13193
13194 /* BSSID is provided by upper layers hence no need to AUTO generate */
13195 if (NULL != params->bssid) {
13196 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013197 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013198 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013199 return -EIO;
13200 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013201 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013202 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
13203 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013204 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013205 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013206 return -EIO;
13207 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053013208 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013209 }
13210 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
13211 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
13212 pRoamProfile->beaconInterval = params->beacon_interval;
13213 else {
13214 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013215 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013216 params->beacon_interval, pRoamProfile->beaconInterval);
13217 }
13218
13219 /* Set Channel */
13220 if (channelNum) {
13221 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013222 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013223 pRoamProfile->ChannelInfo.numOfChannels = 1;
13224 pHddStaCtx->conn_info.operationChannel = channelNum;
13225 pRoamProfile->ChannelInfo.ChannelList =
13226 &pHddStaCtx->conn_info.operationChannel;
13227 }
13228
13229 /* Initialize security parameters */
13230 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
13231 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013232 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013233 return status;
13234 }
13235
13236 /* Issue connect start */
13237 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
13238 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013239 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013240 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013241 operationChannel,
13242 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013243
13244 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013245 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013246 return status;
13247 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013248 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013249 return 0;
13250}
13251
13252/**
13253 * wlan_hdd_cfg80211_join_ibss() - join ibss
13254 * @wiphy: Pointer to wiphy
13255 * @dev: Pointer to network device
13256 * @param: Pointer to IBSS join parameters
13257 *
13258 * This function is used to create/join an IBSS network
13259 *
13260 * Return: 0 for success, non-zero for failure
13261 */
13262static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13263 struct net_device *dev,
13264 struct cfg80211_ibss_params *params)
13265{
13266 int ret = 0;
13267
13268 cds_ssr_protect(__func__);
13269 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
13270 cds_ssr_unprotect(__func__);
13271
13272 return ret;
13273}
13274
13275/**
13276 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
13277 * @wiphy: Pointer to wiphy
13278 * @dev: Pointer to network device
13279 *
13280 * This function is used to leave an IBSS network
13281 *
13282 * Return: 0 for success, non-zero for failure
13283 */
13284static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13285 struct net_device *dev)
13286{
13287 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13288 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13289 tCsrRoamProfile *pRoamProfile;
13290 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13291 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013292 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013293 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013294 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013295
13296 ENTER();
13297
Anurag Chouhan6d760662016-02-20 16:05:43 +053013298 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013299 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013300 return -EINVAL;
13301 }
13302
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013303 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13304 hdd_err("invalid session id: %d", pAdapter->sessionId);
13305 return -EINVAL;
13306 }
13307
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013308 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013309 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
13310 pAdapter->sessionId,
13311 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
13312 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013313 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013314 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013315
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013316 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013317 hdd_device_mode_to_string(pAdapter->device_mode),
13318 pAdapter->device_mode);
13319 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013320 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013321 return -EIO;
13322 }
13323
13324 pRoamProfile = &pWextState->roamProfile;
13325
13326 /* Issue disconnect only if interface type is set to IBSS */
13327 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013328 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013329 return -EINVAL;
13330 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013331 /* Clearing add IE of beacon */
13332 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
13333 sizeof(tSirMacAddr));
13334 updateIE.smeSessionId = pAdapter->sessionId;
13335 updateIE.ieBufferlength = 0;
13336 updateIE.pAdditionIEBuffer = NULL;
13337 updateIE.append = true;
13338 updateIE.notify = true;
13339 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
13340 &updateIE,
13341 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013342 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013343 }
13344
13345 /* Reset WNI_CFG_PROBE_RSP Flags */
13346 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013347
13348 /* Issue Disconnect request */
13349 INIT_COMPLETION(pAdapter->disconnect_comp_var);
13350 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13351 pAdapter->sessionId,
13352 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013353 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013354 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013355 hal_status);
13356 return -EAGAIN;
13357 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013358
13359 /* wait for mc thread to cleanup and then return to upper stack
13360 * so by the time upper layer calls the change interface, we are
13361 * all set to proceed further
13362 */
13363 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
13364 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
13365 if (!rc) {
13366 hdd_err("Failed to disconnect, timed out");
13367 return -ETIMEDOUT;
13368 }
13369
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013370 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013371 return 0;
13372}
13373
13374/**
13375 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
13376 * @wiphy: Pointer to wiphy
13377 * @dev: Pointer to network device
13378 *
13379 * This function is used to leave an IBSS network
13380 *
13381 * Return: 0 for success, non-zero for failure
13382 */
13383static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13384 struct net_device *dev)
13385{
13386 int ret = 0;
13387
13388 cds_ssr_protect(__func__);
13389 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
13390 cds_ssr_unprotect(__func__);
13391
13392 return ret;
13393}
13394
13395/**
13396 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13397 * @wiphy: Pointer to wiphy
13398 * @changed: Parameters changed
13399 *
13400 * This function is used to set the phy parameters. RTS Threshold/FRAG
13401 * Threshold/Retry Count etc.
13402 *
13403 * Return: 0 for success, non-zero for failure
13404 */
13405static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
13406 u32 changed)
13407{
13408 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13409 tHalHandle hHal = pHddCtx->hHal;
13410 int status;
13411
13412 ENTER();
13413
Anurag Chouhan6d760662016-02-20 16:05:43 +053013414 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013415 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013416 return -EINVAL;
13417 }
13418
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013419 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013420 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
13421 NO_SESSION, wiphy->rts_threshold));
13422 status = wlan_hdd_validate_context(pHddCtx);
13423
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013424 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013425 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013426
13427 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
13428 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
13429 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
13430
13431 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
13432 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013433 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013434 rts_threshold);
13435 return -EINVAL;
13436 }
13437
13438 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
13439 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013440 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013441 rts_threshold);
13442 return -EIO;
13443 }
13444
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013445 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013446 }
13447
13448 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
13449 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
13450 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
13451 wiphy->frag_threshold;
13452
13453 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
13454 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013455 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013456 frag_threshold);
13457 return -EINVAL;
13458 }
13459
13460 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
13461 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013462 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013463 frag_threshold);
13464 return -EIO;
13465 }
13466
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013467 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013468 }
13469
13470 if ((changed & WIPHY_PARAM_RETRY_SHORT)
13471 || (changed & WIPHY_PARAM_RETRY_LONG)) {
13472 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
13473 wiphy->retry_short : wiphy->retry_long;
13474
13475 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
13476 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013477 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013478 return -EINVAL;
13479 }
13480
13481 if (changed & WIPHY_PARAM_RETRY_SHORT) {
13482 if (0 != sme_cfg_set_int(hHal,
13483 WNI_CFG_LONG_RETRY_LIMIT,
13484 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013485 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013486 retry_value);
13487 return -EIO;
13488 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013489 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013490 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
13491 if (0 != sme_cfg_set_int(hHal,
13492 WNI_CFG_SHORT_RETRY_LIMIT,
13493 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013494 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013495 retry_value);
13496 return -EIO;
13497 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013498 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013499 }
13500 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013501 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013502 return 0;
13503}
13504
13505/**
13506 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13507 * @wiphy: Pointer to wiphy
13508 * @changed: Parameters changed
13509 *
13510 * Return: 0 for success, non-zero for failure
13511 */
13512static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
13513{
13514 int ret;
13515
13516 cds_ssr_protect(__func__);
13517 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
13518 cds_ssr_unprotect(__func__);
13519
13520 return ret;
13521}
13522
13523/**
13524 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
13525 * key
13526 * @wiphy: Pointer to wiphy
13527 * @dev: Pointer to network device
13528 * @key_index: Key index
13529 *
13530 * Return: 0
13531 */
13532static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13533 struct net_device *netdev,
13534 u8 key_index)
13535{
13536 ENTER();
13537 return 0;
13538}
13539
13540/**
13541 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
13542 * wlan_hdd_set_default_mgmt_key
13543 * @wiphy: pointer to wiphy
13544 * @netdev: pointer to net_device structure
13545 * @key_index: key index
13546 *
13547 * Return: 0 on success, error number on failure
13548 */
13549static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13550 struct net_device *netdev,
13551 u8 key_index)
13552{
13553 int ret;
13554
13555 cds_ssr_protect(__func__);
13556 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
13557 cds_ssr_unprotect(__func__);
13558
13559 return ret;
13560}
13561
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013562/**
13563 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
13564 * @wiphy: Pointer to wiphy
13565 * @dev: Pointer to network device
13566 * @params: Pointer to tx queue parameters
13567 *
13568 * Return: 0
13569 */
13570static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
13571 struct net_device *dev,
13572 struct ieee80211_txq_params *params)
13573{
13574 ENTER();
13575 return 0;
13576}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013577
13578/**
13579 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
13580 * @wiphy: pointer to wiphy
13581 * @netdev: pointer to net_device structure
13582 * @params: pointer to ieee80211_txq_params
13583 *
13584 * Return: 0 on success, error number on failure
13585 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013586static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
13587 struct net_device *dev,
13588 struct ieee80211_txq_params *params)
13589{
13590 int ret;
13591
13592 cds_ssr_protect(__func__);
13593 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
13594 cds_ssr_unprotect(__func__);
13595
13596 return ret;
13597}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013598
13599/**
13600 * __wlan_hdd_cfg80211_del_station() - delete station v2
13601 * @wiphy: Pointer to wiphy
13602 * @param: Pointer to delete station parameter
13603 *
13604 * Return: 0 for success, non-zero for failure
13605 */
13606static
13607int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13608 struct net_device *dev,
13609 struct tagCsrDelStaParams *pDelStaParams)
13610{
13611 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13612 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013613 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013614 hdd_hostapd_state_t *hapd_state;
13615 int status;
13616 uint8_t staId;
13617 uint8_t *mac;
13618
13619 ENTER();
13620
Anurag Chouhan6d760662016-02-20 16:05:43 +053013621 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013622 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013623 return -EINVAL;
13624 }
13625
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013626 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13627 hdd_err("invalid session id: %d", pAdapter->sessionId);
13628 return -EINVAL;
13629 }
13630
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013631 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013632 TRACE_CODE_HDD_CFG80211_DEL_STA,
13633 pAdapter->sessionId, pAdapter->device_mode));
13634
13635 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13636 status = wlan_hdd_validate_context(pHddCtx);
13637
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013638 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013639 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013640
13641 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
13642
Krunal Sonib4326f22016-03-10 13:05:51 -080013643 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
13644 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013645
13646 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
13647 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013648 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013649 return 0;
13650 }
13651
Anurag Chouhanc5548422016-02-24 18:33:27 +053013652 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013653 uint16_t i;
13654 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
13655 if ((pAdapter->aStaInfo[i].isUsed) &&
13656 (!pAdapter->aStaInfo[i].
13657 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013658 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013659 mac,
13660 pAdapter->aStaInfo[i].
13661 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013662 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013663 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13664 hdd_ipa_wlan_evt(pAdapter,
13665 pAdapter->
13666 aStaInfo[i].
13667 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013668 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013669 mac);
13670 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013671 hdd_notice("Delete STA with MAC::"
13672 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013673 MAC_ADDR_ARRAY(mac));
13674
13675 if (pHddCtx->dev_dfs_cac_status ==
13676 DFS_CAC_IN_PROGRESS)
13677 goto fn_end;
13678
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013679 qdf_event_reset(&hapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013680 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053013681 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013682 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013683 hdd_softap_sta_deauth(pAdapter,
13684 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013685 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013686 pAdapter->aStaInfo[i].
13687 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013688 qdf_status =
13689 qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013690 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013691 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013692 if (!QDF_IS_STATUS_SUCCESS(
13693 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013694 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013695 }
13696 }
13697 }
13698 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013699 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013700 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013701 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013702 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013703 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013704 hdd_notice("Skip DEL STA as this is not used::"
13705 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013706 MAC_ADDR_ARRAY(mac));
13707 return -ENOENT;
13708 }
13709
13710 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13711 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013712 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013713 }
13714
13715 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
13716 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013717 hdd_notice("Skip DEL STA as deauth is in progress::"
13718 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013719 MAC_ADDR_ARRAY(mac));
13720 return -ENOENT;
13721 }
13722
13723 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
13724
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013725 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013726 MAC_ADDR_ARRAY(mac));
13727
13728 /* Case: SAP in ACS selected DFS ch and client connected
13729 * Now Radar detected. Then if random channel is another
13730 * DFS ch then new CAC is initiated and no TX allowed.
13731 * So do not send any mgmt frames as it will timeout
13732 * during CAC.
13733 */
13734
13735 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
13736 goto fn_end;
13737
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013738 qdf_event_reset(&hapd_state->qdf_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053013739 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
13740 (pAdapter), pAdapter->sessionId,
13741 (uint8_t *)&pDelStaParams->peerMacAddr,
13742 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013743 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013744 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013745 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013746 pAdapter->aStaInfo[staId].isDeauthInProgress =
13747 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013748 hdd_notice("STA removal failed for ::"
13749 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013750 MAC_ADDR_ARRAY(mac));
13751 return -ENOENT;
13752 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053013753 qdf_status = qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013754 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013755 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013756 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013757 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013758 }
13759 }
13760 }
13761
13762fn_end:
13763 EXIT();
13764 return 0;
13765}
13766
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013767#if defined(USE_CFG80211_DEL_STA_V2)
13768/**
13769 * wlan_hdd_del_station() - delete station wrapper
13770 * @adapter: pointer to the hdd adapter
13771 *
13772 * Return: None
13773 */
13774void wlan_hdd_del_station(hdd_adapter_t *adapter)
13775{
13776 struct station_del_parameters del_sta;
13777 del_sta.mac = NULL;
13778 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
13779 del_sta.reason_code = eCsrForcedDeauthSta;
13780
13781 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
13782 &del_sta);
13783}
13784#else
13785void wlan_hdd_del_station(hdd_adapter_t *adapter)
13786{
13787 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
13788}
13789#endif
13790
13791#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013792/**
13793 * wlan_hdd_cfg80211_del_station() - delete station v2
13794 * @wiphy: Pointer to wiphy
13795 * @param: Pointer to delete station parameter
13796 *
13797 * Return: 0 for success, non-zero for failure
13798 */
13799int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13800 struct net_device *dev,
13801 struct station_del_parameters *param)
13802#else
13803/**
13804 * wlan_hdd_cfg80211_del_station() - delete station
13805 * @wiphy: Pointer to wiphy
13806 * @mac: Pointer to station mac address
13807 *
13808 * Return: 0 for success, non-zero for failure
13809 */
13810#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13811int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13812 struct net_device *dev,
13813 const uint8_t *mac)
13814#else
13815int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13816 struct net_device *dev,
13817 uint8_t *mac)
13818#endif
13819#endif
13820{
13821 int ret;
13822 struct tagCsrDelStaParams delStaParams;
13823
13824 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013825#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013826 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013827 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013828 return -EINVAL;
13829 }
13830 wlansap_populate_del_sta_params(param->mac, param->reason_code,
13831 param->subtype, &delStaParams);
13832#else
13833 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
13834 (SIR_MAC_MGMT_DEAUTH >> 4),
13835 &delStaParams);
13836#endif
13837 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
13838 cds_ssr_unprotect(__func__);
13839
13840 return ret;
13841}
13842
13843/**
13844 * __wlan_hdd_cfg80211_add_station() - add station
13845 * @wiphy: Pointer to wiphy
13846 * @mac: Pointer to station mac address
13847 * @pmksa: Pointer to add station parameter
13848 *
13849 * Return: 0 for success, non-zero for failure
13850 */
13851static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13852 struct net_device *dev,
13853 const uint8_t *mac,
13854 struct station_parameters *params)
13855{
13856 int status = -EPERM;
13857#ifdef FEATURE_WLAN_TDLS
13858 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13859 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13860 u32 mask, set;
13861
13862 ENTER();
13863
Anurag Chouhan6d760662016-02-20 16:05:43 +053013864 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013865 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013866 return -EINVAL;
13867 }
13868
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013869 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13870 hdd_err("invalid session id: %d", pAdapter->sessionId);
13871 return -EINVAL;
13872 }
13873
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013874 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013875 TRACE_CODE_HDD_CFG80211_ADD_STA,
13876 pAdapter->sessionId, params->listen_interval));
13877
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013878 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013879 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013880
13881 mask = params->sta_flags_mask;
13882
13883 set = params->sta_flags_set;
13884
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013885 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013886 MAC_ADDR_ARRAY(mac));
13887
13888 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13889 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13890 status =
13891 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
13892 }
13893 }
13894#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013895 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013896 return status;
13897}
13898
13899/**
13900 * wlan_hdd_cfg80211_add_station() - add station
13901 * @wiphy: Pointer to wiphy
13902 * @mac: Pointer to station mac address
13903 * @pmksa: Pointer to add station parameter
13904 *
13905 * Return: 0 for success, non-zero for failure
13906 */
13907#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13908static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13909 struct net_device *dev,
13910 const uint8_t *mac,
13911 struct station_parameters *params)
13912#else
13913static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13914 struct net_device *dev, uint8_t *mac,
13915 struct station_parameters *params)
13916#endif
13917{
13918 int ret;
13919
13920 cds_ssr_protect(__func__);
13921 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
13922 cds_ssr_unprotect(__func__);
13923
13924 return ret;
13925}
13926
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013927/**
13928 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
13929 * @wiphy: Pointer to wiphy
13930 * @dev: Pointer to network device
13931 * @pmksa: Pointer to set pmksa parameter
13932 *
13933 * Return: 0 for success, non-zero for failure
13934 */
13935static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13936 struct net_device *dev,
13937 struct cfg80211_pmksa *pmksa)
13938{
13939 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13940 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13941 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013942 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013943 int status;
13944 tPmkidCacheInfo pmk_id;
13945
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013946 ENTER();
13947
Anurag Chouhan6d760662016-02-20 16:05:43 +053013948 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013949 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013950 return -EINVAL;
13951 }
13952
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013953 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13954 hdd_err("invalid session id: %d", pAdapter->sessionId);
13955 return -EINVAL;
13956 }
13957
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013958 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013959 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013960 return -EINVAL;
13961 }
13962
13963 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013964 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013965 pmksa->bssid, pmksa->pmkid);
13966 return -EINVAL;
13967 }
13968
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013969 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013970 MAC_ADDR_ARRAY(pmksa->bssid));
13971
13972 status = wlan_hdd_validate_context(pHddCtx);
13973
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013974 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013975 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013976
13977 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13978
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013979 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
13980 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013981
13982 /* Add to the PMKSA ID Cache in CSR */
13983 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
13984 &pmk_id, 1, false);
13985
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013986 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013987 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
13988 pAdapter->sessionId, result));
13989
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013990 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013991 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013992}
13993
13994/**
13995 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
13996 * @wiphy: Pointer to wiphy
13997 * @dev: Pointer to network device
13998 * @pmksa: Pointer to set pmksa parameter
13999 *
14000 * Return: 0 for success, non-zero for failure
14001 */
14002static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
14003 struct net_device *dev,
14004 struct cfg80211_pmksa *pmksa)
14005{
14006 int ret;
14007
14008 cds_ssr_protect(__func__);
14009 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
14010 cds_ssr_unprotect(__func__);
14011
14012 return ret;
14013}
14014
14015/**
14016 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
14017 * @wiphy: Pointer to wiphy
14018 * @dev: Pointer to network device
14019 * @pmksa: Pointer to pmksa parameter
14020 *
14021 * Return: 0 for success, non-zero for failure
14022 */
14023static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
14024 struct net_device *dev,
14025 struct cfg80211_pmksa *pmksa)
14026{
14027 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14028 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14029 tHalHandle halHandle;
14030 int status = 0;
14031
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014032 ENTER();
14033
Anurag Chouhan6d760662016-02-20 16:05:43 +053014034 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014035 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014036 return -EINVAL;
14037 }
14038
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014039 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14040 hdd_err("invalid session id: %d", pAdapter->sessionId);
14041 return -EINVAL;
14042 }
14043
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014044 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014045 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014046 return -EINVAL;
14047 }
14048
14049 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014050 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014051 return -EINVAL;
14052 }
14053
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014054 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014055 MAC_ADDR_ARRAY(pmksa->bssid));
14056
14057 status = wlan_hdd_validate_context(pHddCtx);
14058
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014059 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014060 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014061
14062 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14063
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014064 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014065 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
14066 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014067 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014068 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014069 sme_roam_del_pmkid_from_cache(halHandle,
14070 pAdapter->sessionId, pmksa->bssid,
14071 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014072 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014073 MAC_ADDR_ARRAY(pmksa->bssid));
14074 status = -EINVAL;
14075 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014076 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014077 return status;
14078}
14079
14080/**
14081 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
14082 * @wiphy: Pointer to wiphy
14083 * @dev: Pointer to network device
14084 * @pmksa: Pointer to pmksa parameter
14085 *
14086 * Return: 0 for success, non-zero for failure
14087 */
14088static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
14089 struct net_device *dev,
14090 struct cfg80211_pmksa *pmksa)
14091{
14092 int ret;
14093
14094 cds_ssr_protect(__func__);
14095 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
14096 cds_ssr_unprotect(__func__);
14097
14098 return ret;
14099
14100}
14101
14102/**
14103 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
14104 * @wiphy: Pointer to wiphy
14105 * @dev: Pointer to network device
14106 *
14107 * Return: 0 for success, non-zero for failure
14108 */
14109static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
14110 struct net_device *dev)
14111{
14112 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14113 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14114 tHalHandle halHandle;
14115 int status = 0;
14116
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014117 ENTER();
14118
Anurag Chouhan6d760662016-02-20 16:05:43 +053014119 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014120 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014121 return -EINVAL;
14122 }
14123
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014124 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14125 hdd_err("invalid session id: %d", pAdapter->sessionId);
14126 return -EINVAL;
14127 }
14128
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014129 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014130
14131 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14132 status = wlan_hdd_validate_context(pHddCtx);
14133
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014134 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014135 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014136
14137 /* Retrieve halHandle */
14138 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14139
14140 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014141 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014142 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
14143 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014144 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014145 status = -EINVAL;
14146 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014147 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014148 return status;
14149}
14150
14151/**
14152 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
14153 * @wiphy: Pointer to wiphy
14154 * @dev: Pointer to network device
14155 *
14156 * Return: 0 for success, non-zero for failure
14157 */
14158static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
14159 struct net_device *dev)
14160{
14161 int ret;
14162
14163 cds_ssr_protect(__func__);
14164 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
14165 cds_ssr_unprotect(__func__);
14166
14167 return ret;
14168}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014169
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080014170#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014171/**
14172 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
14173 * @wiphy: Pointer to wiphy
14174 * @dev: Pointer to network device
14175 * @ftie: Pointer to fast transition ie parameter
14176 *
14177 * Return: 0 for success, non-zero for failure
14178 */
14179static int
14180__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14181 struct net_device *dev,
14182 struct cfg80211_update_ft_ies_params *ftie)
14183{
14184 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
14185 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14186 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14187 int status;
14188
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014189 ENTER();
14190
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014191 status = wlan_hdd_validate_context(hdd_ctx);
14192 if (status)
14193 return status;
14194
Anurag Chouhan6d760662016-02-20 16:05:43 +053014195 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014196 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014197 return -EINVAL;
14198 }
14199
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014200 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14201 hdd_err("invalid session id: %d", pAdapter->sessionId);
14202 return -EINVAL;
14203 }
14204
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014205 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014206 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
14207 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
14208 /* Added for debug on reception of Re-assoc Req. */
14209 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014210 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014211 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014212 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014213 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014214 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014215 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014216
14217 /* Pass the received FT IEs to SME */
14218 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
14219 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014220 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014221 return 0;
14222}
14223
14224/**
14225 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
14226 * @wiphy: Pointer to wiphy
14227 * @dev: Pointer to network device
14228 * @ftie: Pointer to fast transition ie parameter
14229 *
14230 * Return: 0 for success, non-zero for failure
14231 */
14232static int
14233wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14234 struct net_device *dev,
14235 struct cfg80211_update_ft_ies_params *ftie)
14236{
14237 int ret;
14238
14239 cds_ssr_protect(__func__);
14240 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
14241 cds_ssr_unprotect(__func__);
14242
14243 return ret;
14244}
14245#endif
14246
14247#ifdef WLAN_FEATURE_GTK_OFFLOAD
14248/**
14249 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
14250 * @callbackContext: Callback context
14251 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
14252 *
14253 * Callback rountine called upon receiving response for get offload info
14254 *
14255 * Return: none
14256 */
14257void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
14258 tpSirGtkOffloadGetInfoRspParams
14259 pGtkOffloadGetInfoRsp)
14260{
14261 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
14262 uint8_t tempReplayCounter[8];
14263 hdd_station_ctx_t *pHddStaCtx;
14264
14265 ENTER();
14266
14267 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014268 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014269 return;
14270 }
14271
14272 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014273 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014274 return;
14275 }
14276
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014277 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014278 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014279 return;
14280 }
14281
14282 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14283 /* Update replay counter */
14284 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
14285 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14286
14287 {
14288 /* changing from little to big endian since supplicant
14289 * works on big endian format
14290 */
14291 int i;
14292 uint8_t *p =
14293 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14294
14295 for (i = 0; i < 8; i++) {
14296 tempReplayCounter[7 - i] = (uint8_t) p[i];
14297 }
14298 }
14299
14300 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014301 cfg80211_gtk_rekey_notify(pAdapter->dev,
14302 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014303 tempReplayCounter, GFP_KERNEL);
14304}
14305
14306/**
14307 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14308 * @wiphy: Pointer to wiphy
14309 * @dev: Pointer to network device
14310 * @data: Pointer to rekey data
14311 *
14312 * This function is used to offload GTK rekeying job to the firmware.
14313 *
14314 * Return: 0 for success, non-zero for failure
14315 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014316static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014317int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14318 struct net_device *dev,
14319 struct cfg80211_gtk_rekey_data *data)
14320{
14321 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14322 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14323 hdd_station_ctx_t *pHddStaCtx;
14324 tHalHandle hHal;
14325 int result;
14326 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014327 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014328
14329 ENTER();
14330
Anurag Chouhan6d760662016-02-20 16:05:43 +053014331 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014332 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014333 return -EINVAL;
14334 }
14335
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014336 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14337 hdd_err("invalid session id: %d", pAdapter->sessionId);
14338 return -EINVAL;
14339 }
14340
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014341 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014342 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
14343 pAdapter->sessionId, pAdapter->device_mode));
14344
14345 result = wlan_hdd_validate_context(pHddCtx);
14346
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014347 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014348 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014349
14350 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14351 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14352 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014353 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014354 return -EAGAIN;
14355 }
14356
14357 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
14358 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
14359 NL80211_KCK_LEN);
14360 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
14361 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053014362 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014363 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014364 {
14365 /* changing from big to little endian since driver
14366 * works on little endian format
14367 */
14368 uint8_t *p =
14369 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
14370 ullKeyReplayCounter;
14371 int i;
14372
14373 for (i = 0; i < 8; i++) {
14374 p[7 - i] = data->replay_ctr[i];
14375 }
14376 }
14377
14378 if (true == pHddCtx->hdd_wlan_suspended) {
14379 /* if wlan is suspended, enable GTK offload directly from here */
14380 memcpy(&hddGtkOffloadReqParams,
14381 &pHddStaCtx->gtkOffloadReqParams,
14382 sizeof(tSirGtkOffloadParams));
14383 status =
14384 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
14385 pAdapter->sessionId);
14386
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014387 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014388 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014389 status);
14390 return -EINVAL;
14391 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014392 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014393 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014394 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014395 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014396 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014397 return result;
14398}
14399
14400/**
14401 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14402 * @wiphy: Pointer to wiphy
14403 * @dev: Pointer to network device
14404 * @data: Pointer to rekey data
14405 *
14406 * This function is used to offload GTK rekeying job to the firmware.
14407 *
14408 * Return: 0 for success, non-zero for failure
14409 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014410static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014411int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14412 struct net_device *dev,
14413 struct cfg80211_gtk_rekey_data *data)
14414{
14415 int ret;
14416
14417 cds_ssr_protect(__func__);
14418 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
14419 cds_ssr_unprotect(__func__);
14420
14421 return ret;
14422}
14423#endif /*WLAN_FEATURE_GTK_OFFLOAD */
14424
14425/**
14426 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
14427 * @wiphy: Pointer to wiphy
14428 * @dev: Pointer to network device
14429 * @param: Pointer to access control parameter
14430 *
14431 * Return: 0 for success, non-zero for failure
14432 */
14433static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14434 struct net_device *dev,
14435 const struct cfg80211_acl_data *params)
14436{
14437 int i;
14438 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14439 hdd_hostapd_state_t *pHostapdState;
14440 tsap_Config_t *pConfig;
14441 v_CONTEXT_t p_cds_context = NULL;
14442 hdd_context_t *pHddCtx;
14443 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014444 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014445
14446 ENTER();
14447
Anurag Chouhan6d760662016-02-20 16:05:43 +053014448 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014449 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014450 return -EINVAL;
14451 }
14452
14453 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014454 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014455 return -EINVAL;
14456 }
14457
14458 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14459 status = wlan_hdd_validate_context(pHddCtx);
14460
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014461 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014462 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014463
14464 p_cds_context = pHddCtx->pcds_context;
14465 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14466
14467 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014468 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014469 return -EINVAL;
14470 }
14471
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014472 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014473 params->n_acl_entries);
14474
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014475 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014476 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
14477 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080014478 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014479 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
14480
14481 /* default value */
14482 pConfig->num_accept_mac = 0;
14483 pConfig->num_deny_mac = 0;
14484
14485 /**
14486 * access control policy
14487 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
14488 * listed in hostapd.deny file.
14489 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
14490 * listed in hostapd.accept file.
14491 */
14492 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
14493 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
14494 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
14495 params->acl_policy) {
14496 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
14497 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014498 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014499 params->acl_policy);
14500 return -ENOTSUPP;
14501 }
14502
14503 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
14504 pConfig->num_accept_mac = params->n_acl_entries;
14505 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014506 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
14507 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014508 MAC_ADDR_ARRAY(
14509 params->mac_addrs[i].addr));
14510
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014511 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014512 params->mac_addrs[i].addr,
14513 sizeof(qcmacaddr));
14514 }
14515 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
14516 pConfig->num_deny_mac = params->n_acl_entries;
14517 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014518 hdd_notice("** Add ACL MAC entry %i in BlackList :"
14519 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014520 MAC_ADDR_ARRAY(
14521 params->mac_addrs[i].addr));
14522
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014523 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014524 params->mac_addrs[i].addr,
14525 sizeof(qcmacaddr));
14526 }
14527 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070014528 qdf_status = wlansap_set_mac_acl(
14529 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014530 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014531 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014532 return -EINVAL;
14533 }
14534 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014535 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014536 hdd_device_mode_to_string(pAdapter->device_mode),
14537 pAdapter->device_mode);
14538 return -EINVAL;
14539 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014540 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014541 return 0;
14542}
14543
14544/**
14545 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
14546 * __wlan_hdd_cfg80211_set_mac_acl
14547 * @wiphy: pointer to wiphy structure
14548 * @dev: pointer to net_device
14549 * @params: pointer to cfg80211_acl_data
14550 *
14551 * Return; 0 on success, error number otherwise
14552 */
14553static int
14554wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14555 struct net_device *dev,
14556 const struct cfg80211_acl_data *params)
14557{
14558 int ret;
14559
14560 cds_ssr_protect(__func__);
14561 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
14562 cds_ssr_unprotect(__func__);
14563
14564 return ret;
14565}
14566
14567#ifdef WLAN_NL80211_TESTMODE
14568#ifdef FEATURE_WLAN_LPHB
14569/**
14570 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
14571 * @pHddCtx: Pointer to hdd context
14572 * @lphbInd: Pointer to low power heart beat indication parameter
14573 *
14574 * Return: none
14575 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014576static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
14577 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014578{
14579 struct sk_buff *skb;
14580
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014581 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014582
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014583 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014584 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014585
14586 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014587 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014588 return;
14589 }
14590
14591 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
14592 wiphy, sizeof(tSirLPHBInd),
14593 GFP_ATOMIC);
14594 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014595 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014596 return;
14597 }
14598
14599 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014600 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014601 goto nla_put_failure;
14602 }
14603 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014604 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014605 goto nla_put_failure;
14606 }
14607 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014608 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014609 goto nla_put_failure;
14610 }
14611 cfg80211_testmode_event(skb, GFP_ATOMIC);
14612 return;
14613
14614nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014615 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014616 kfree_skb(skb);
14617
14618 return;
14619}
14620#endif /* FEATURE_WLAN_LPHB */
14621
14622/**
14623 * __wlan_hdd_cfg80211_testmode() - test mode
14624 * @wiphy: Pointer to wiphy
14625 * @data: Data pointer
14626 * @len: Data length
14627 *
14628 * Return: 0 for success, non-zero for failure
14629 */
14630static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14631 void *data, int len)
14632{
14633 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
14634 int err;
14635 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14636
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014637 ENTER();
14638
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014639 err = wlan_hdd_validate_context(pHddCtx);
14640 if (err)
14641 return err;
14642
14643 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
14644 len, wlan_hdd_tm_policy);
14645 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014646 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014647 return err;
14648 }
14649
14650 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014651 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014652 return -EINVAL;
14653 }
14654
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014655 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014656 TRACE_CODE_HDD_CFG80211_TESTMODE,
14657 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014658 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
14659#ifdef FEATURE_WLAN_LPHB
14660 /* Low Power Heartbeat configuration request */
14661 case WLAN_HDD_TM_CMD_WLAN_HB:
14662 {
14663 int buf_len;
14664 void *buf;
14665 tSirLPHBReq *hb_params = NULL;
14666 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014667 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014668
14669 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014670 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014671 return -EINVAL;
14672 }
14673
14674 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14675 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14676
14677 hb_params_temp = (tSirLPHBReq *) buf;
14678 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
14679 && (hb_params_temp->params.lphbTcpParamReq.
14680 timePeriodSec == 0))
14681 return -EINVAL;
14682
14683 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014684 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014685 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014686 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014687 return -ENOMEM;
14688 }
14689
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014690 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014691 smeStatus =
14692 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
14693 hb_params,
14694 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014695 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014696 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014697 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014698 }
14699 return 0;
14700 }
14701#endif /* FEATURE_WLAN_LPHB */
14702
14703#if defined(QCA_WIFI_FTM)
14704 case WLAN_HDD_TM_CMD_WLAN_FTM:
14705 {
14706 int buf_len;
14707 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014708 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014709 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014710 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014711 return -EINVAL;
14712 }
14713
14714 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14715 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14716
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014717 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014718
14719 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
14720
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014721 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014722 err = -EBUSY;
14723 break;
14724 }
14725#endif
14726
14727 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014728 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014729 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
14730 return -EOPNOTSUPP;
14731 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014732 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014733 return err;
14734}
14735
14736/**
14737 * wlan_hdd_cfg80211_testmode() - test mode
14738 * @wiphy: Pointer to wiphy
14739 * @dev: Pointer to network device
14740 * @data: Data pointer
14741 * @len: Data length
14742 *
14743 * Return: 0 for success, non-zero for failure
14744 */
14745static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14746#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
14747 struct wireless_dev *wdev,
14748#endif
14749 void *data, int len)
14750{
14751 int ret;
14752
14753 cds_ssr_protect(__func__);
14754 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
14755 cds_ssr_unprotect(__func__);
14756
14757 return ret;
14758}
14759
14760#if defined(QCA_WIFI_FTM)
14761/**
14762 * wlan_hdd_testmode_rx_event() - test mode rx event handler
14763 * @buf: Pointer to buffer
14764 * @buf_len: Buffer length
14765 *
14766 * Return: none
14767 */
14768void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
14769{
14770 struct sk_buff *skb;
14771 hdd_context_t *hdd_ctx;
14772
14773 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014774 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014775 return;
14776 }
14777
Anurag Chouhan6d760662016-02-20 16:05:43 +053014778 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014779 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014780 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014781 return;
14782 }
14783
14784 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
14785 buf_len, GFP_KERNEL);
14786 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014787 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014788 return;
14789 }
14790
14791 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
14792 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
14793 goto nla_put_failure;
14794
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014795 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014796
14797 cfg80211_testmode_event(skb, GFP_KERNEL);
14798 return;
14799
14800nla_put_failure:
14801 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014802 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014803}
14804#endif
14805#endif /* CONFIG_NL80211_TESTMODE */
14806
14807#ifdef QCA_HT_2040_COEX
14808/**
14809 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14810 * @wiphy: Pointer to wiphy
14811 * @dev: Pointer to network device
14812 * @chandef: Pointer to channel definition parameter
14813 *
14814 * Return: 0 for success, non-zero for failure
14815 */
14816static int
14817__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14818 struct net_device *dev,
14819 struct cfg80211_chan_def *chandef)
14820{
14821 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14822 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014823 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014824 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053014825 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014826
Anurag Chouhan6d760662016-02-20 16:05:43 +053014827 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014828 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014829 return -EINVAL;
14830 }
14831
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014832 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14833 hdd_err("invalid session id: %d", pAdapter->sessionId);
14834 return -EINVAL;
14835 }
14836
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014837 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14838 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053014839 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014840 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014841
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014842 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014843 sme_get_config_param(pHddCtx->hHal, &sme_config);
14844 switch (chandef->width) {
14845 case NL80211_CHAN_WIDTH_20:
14846 if (sme_config.csrConfig.channelBondingMode24GHz !=
14847 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14848 sme_config.csrConfig.channelBondingMode24GHz =
14849 eCSR_INI_SINGLE_CHANNEL_CENTERED;
14850 sme_update_config(pHddCtx->hHal, &sme_config);
14851 cbModeChange = true;
14852 }
14853 break;
14854
14855 case NL80211_CHAN_WIDTH_40:
14856 if (sme_config.csrConfig.channelBondingMode24GHz ==
14857 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14858 if (NL80211_CHAN_HT40MINUS ==
14859 cfg80211_get_chandef_type(chandef))
14860 sme_config.csrConfig.channelBondingMode24GHz =
14861 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
14862 else
14863 sme_config.csrConfig.channelBondingMode24GHz =
14864 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
14865 sme_update_config(pHddCtx->hHal, &sme_config);
14866 cbModeChange = true;
14867 }
14868 break;
14869
14870 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014871 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014872 return -EINVAL;
14873 }
14874
14875 if (!cbModeChange)
14876 return 0;
14877
Krunal Sonib4326f22016-03-10 13:05:51 -080014878 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014879 return 0;
14880
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014881 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014882 sme_config.csrConfig.channelBondingMode24GHz);
14883
14884 /* Change SAP ht2040 mode */
14885 status = hdd_set_sap_ht2040_mode(pAdapter,
14886 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014887 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014888 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014889 return -EINVAL;
14890 }
14891
14892 return 0;
14893}
14894
14895/**
14896 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14897 * @wiphy: Pointer to wiphy
14898 * @dev: Pointer to network device
14899 * @chandef: Pointer to channel definition parameter
14900 *
14901 * Return: 0 for success, non-zero for failure
14902 */
14903static int
14904wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14905 struct net_device *dev,
14906 struct cfg80211_chan_def *chandef)
14907{
14908 int ret;
14909
14910 cds_ssr_protect(__func__);
14911 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
14912 cds_ssr_unprotect(__func__);
14913
14914 return ret;
14915}
14916#endif
14917
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014918#ifdef CHANNEL_SWITCH_SUPPORTED
14919/**
14920 * __wlan_hdd_cfg80211_channel_switch()- function to switch
14921 * channel in SAP/GO
14922 * @wiphy: wiphy pointer
14923 * @dev: dev pointer.
14924 * @csa_params: Change channel params
14925 *
14926 * This function is called to switch channel in SAP/GO
14927 *
14928 * Return: 0 if success else return non zero
14929 */
14930static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14931 struct net_device *dev,
14932 struct cfg80211_csa_settings *csa_params)
14933{
14934 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
14935 hdd_context_t *hdd_ctx;
14936 uint8_t channel;
14937 uint16_t freq;
14938 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080014939 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014940
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014941 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014942 csa_params->chandef.chan->center_freq);
14943
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014944 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
14945 hdd_err("invalid session id: %d", adapter->sessionId);
14946 return -EINVAL;
14947 }
14948
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014949 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
14950 ret = wlan_hdd_validate_context(hdd_ctx);
14951
14952 if (0 != ret)
14953 return ret;
14954
Krunal Sonib4326f22016-03-10 13:05:51 -080014955 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
14956 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014957 return -ENOTSUPP;
14958
14959 freq = csa_params->chandef.chan->center_freq;
14960 channel = cds_freq_to_chan(freq);
14961
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053014962 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
14963
14964 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014965 return ret;
14966}
14967
14968/**
14969 * wlan_hdd_cfg80211_channel_switch()- function to switch
14970 * channel in SAP/GO
14971 * @wiphy: wiphy pointer
14972 * @dev: dev pointer.
14973 * @csa_params: Change channel params
14974 *
14975 * This function is called to switch channel in SAP/GO
14976 *
14977 * Return: 0 if success else return non zero
14978 */
14979static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14980 struct net_device *dev,
14981 struct cfg80211_csa_settings *csa_params)
14982{
14983 int ret;
14984
14985 cds_ssr_protect(__func__);
14986 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
14987 cds_ssr_unprotect(__func__);
14988 return ret;
14989}
14990#endif
14991
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014992/**
14993 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
14994 * translation from NL to policy manager type
14995 * @type: Generic connection mode type defined in NL
14996 *
14997 *
14998 * This function provides the type translation
14999 *
15000 * Return: cds_con_mode enum
15001 */
15002enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
15003 enum nl80211_iftype type)
15004{
15005 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
15006 switch (type) {
15007 case NL80211_IFTYPE_STATION:
15008 mode = CDS_STA_MODE;
15009 break;
15010 case NL80211_IFTYPE_P2P_CLIENT:
15011 mode = CDS_P2P_CLIENT_MODE;
15012 break;
15013 case NL80211_IFTYPE_P2P_GO:
15014 mode = CDS_P2P_GO_MODE;
15015 break;
15016 case NL80211_IFTYPE_AP:
15017 mode = CDS_SAP_MODE;
15018 break;
15019 case NL80211_IFTYPE_ADHOC:
15020 mode = CDS_IBSS_MODE;
15021 break;
15022 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015023 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015024 type);
15025 }
15026 return mode;
15027}
15028
15029/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015030 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
15031 * @wiphy: Handle to struct wiphy to get handle to module context.
15032 * @chandef: Contains information about the capture channel to be set.
15033 *
15034 * This interface is called if and only if monitor mode interface alone is
15035 * active.
15036 *
15037 * Return: 0 success or error code on failure.
15038 */
15039static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
15040 struct cfg80211_chan_def *chandef)
15041{
15042 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15043 hdd_adapter_t *adapter;
15044 hdd_station_ctx_t *sta_ctx;
15045 struct hdd_mon_set_ch_info *ch_info;
15046 QDF_STATUS status;
15047 tHalHandle hal_hdl;
15048 struct qdf_mac_addr bssid;
15049 tCsrRoamProfile roam_profile;
15050 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070015051 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015052 int ret;
15053 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
15054
15055 ENTER();
15056
15057 ret = wlan_hdd_validate_context(hdd_ctx);
15058 if (ret)
15059 return ret;
15060
15061 hal_hdl = hdd_ctx->hHal;
15062
15063 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
15064 if (!adapter)
15065 return -EIO;
15066
15067 hdd_info("%s: set monitor mode Channel %d and freq %d",
15068 adapter->dev->name, chan_num, chandef->chan->center_freq);
15069
15070 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
15071 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015072 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
15073 roam_profile.ChannelInfo.numOfChannels = 1;
15074 roam_profile.phyMode = ch_info->phy_mode;
15075 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015076 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015077
15078 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
15079 QDF_MAC_ADDR_SIZE);
15080
15081 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070015082 /*
15083 * CDS api expects secondary channel for calculating
15084 * the channel params
15085 */
15086 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
15087 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
15088 if (chan_num >= 1 && chan_num <= 5)
15089 sec_ch = chan_num + 4;
15090 else if (chan_num >= 6 && chan_num <= 13)
15091 sec_ch = chan_num - 4;
15092 }
15093 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015094 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
15095 &roam_profile);
15096 if (status) {
15097 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
15098 status);
15099 ret = qdf_status_to_os_return(status);
15100 return ret;
15101 }
15102 EXIT();
15103 return 0;
15104}
15105
15106/**
15107 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
15108 * @wiphy: Handle to struct wiphy to get handle to module context.
15109 * @chandef: Contains information about the capture channel to be set.
15110 *
15111 * This interface is called if and only if monitor mode interface alone is
15112 * active.
15113 *
15114 * Return: 0 success or error code on failure.
15115 */
15116static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
15117 struct cfg80211_chan_def *chandef)
15118{
15119 int ret;
15120
15121 cds_ssr_protect(__func__);
15122 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
15123 cds_ssr_unprotect(__func__);
15124 return ret;
15125}
15126
15127/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053015128 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
15129 * @adapter: pointer to adapter
15130 *
15131 * Wrapper function to clear link layer stats.
15132 * return - void
15133 */
15134void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
15135{
15136 tSirLLStatsClearReq link_layer_stats_clear_req;
15137 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
15138
Mukul Sharma491021c2016-09-29 21:39:19 +053015139 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
15140 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053015141 link_layer_stats_clear_req.stopReq = 0;
15142 link_layer_stats_clear_req.reqId = 1;
15143 link_layer_stats_clear_req.staId = adapter->sessionId;
15144 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
15145
15146 return;
15147}
15148
15149/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015150 * struct cfg80211_ops - cfg80211_ops
15151 *
15152 * @add_virtual_intf: Add virtual interface
15153 * @del_virtual_intf: Delete virtual interface
15154 * @change_virtual_intf: Change virtual interface
15155 * @change_station: Change station
15156 * @add_beacon: Add beacon in sap mode
15157 * @del_beacon: Delete beacon in sap mode
15158 * @set_beacon: Set beacon in sap mode
15159 * @start_ap: Start ap
15160 * @change_beacon: Change beacon
15161 * @stop_ap: Stop ap
15162 * @change_bss: Change bss
15163 * @add_key: Add key
15164 * @get_key: Get key
15165 * @del_key: Delete key
15166 * @set_default_key: Set default key
15167 * @set_channel: Set channel
15168 * @scan: Scan
15169 * @connect: Connect
15170 * @disconnect: Disconnect
15171 * @join_ibss = Join ibss
15172 * @leave_ibss = Leave ibss
15173 * @set_wiphy_params = Set wiphy params
15174 * @set_tx_power = Set tx power
15175 * @get_tx_power = get tx power
15176 * @remain_on_channel = Remain on channel
15177 * @cancel_remain_on_channel = Cancel remain on channel
15178 * @mgmt_tx = Tx management frame
15179 * @mgmt_tx_cancel_wait = Cancel management tx wait
15180 * @set_default_mgmt_key = Set default management key
15181 * @set_txq_params = Set tx queue parameters
15182 * @get_station = Get station
15183 * @set_power_mgmt = Set power management
15184 * @del_station = Delete station
15185 * @add_station = Add station
15186 * @set_pmksa = Set pmksa
15187 * @del_pmksa = Delete pmksa
15188 * @flush_pmksa = Flush pmksa
15189 * @update_ft_ies = Update FT IEs
15190 * @tdls_mgmt = Tdls management
15191 * @tdls_oper = Tdls operation
15192 * @set_rekey_data = Set rekey data
15193 * @sched_scan_start = Scheduled scan start
15194 * @sched_scan_stop = Scheduled scan stop
15195 * @resume = Resume wlan
15196 * @suspend = Suspend wlan
15197 * @set_mac_acl = Set mac acl
15198 * @testmode_cmd = Test mode command
15199 * @set_ap_chanwidth = Set AP channel bandwidth
15200 * @dump_survey = Dump survey
15201 * @key_mgmt_set_pmk = Set pmk key management
15202 */
15203static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
15204 .add_virtual_intf = wlan_hdd_add_virtual_intf,
15205 .del_virtual_intf = wlan_hdd_del_virtual_intf,
15206 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
15207 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015208 .start_ap = wlan_hdd_cfg80211_start_ap,
15209 .change_beacon = wlan_hdd_cfg80211_change_beacon,
15210 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015211 .change_bss = wlan_hdd_cfg80211_change_bss,
15212 .add_key = wlan_hdd_cfg80211_add_key,
15213 .get_key = wlan_hdd_cfg80211_get_key,
15214 .del_key = wlan_hdd_cfg80211_del_key,
15215 .set_default_key = wlan_hdd_cfg80211_set_default_key,
15216 .scan = wlan_hdd_cfg80211_scan,
15217 .connect = wlan_hdd_cfg80211_connect,
15218 .disconnect = wlan_hdd_cfg80211_disconnect,
15219 .join_ibss = wlan_hdd_cfg80211_join_ibss,
15220 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
15221 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
15222 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
15223 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
15224 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
15225 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
15226 .mgmt_tx = wlan_hdd_mgmt_tx,
15227 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
15228 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
15229 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053015230 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015231 .get_station = wlan_hdd_cfg80211_get_station,
15232 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
15233 .del_station = wlan_hdd_cfg80211_del_station,
15234 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015235 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
15236 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
15237 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015238#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015239 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
15240#endif
15241#ifdef FEATURE_WLAN_TDLS
15242 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
15243 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
15244#endif
15245#ifdef WLAN_FEATURE_GTK_OFFLOAD
15246 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
15247#endif /* WLAN_FEATURE_GTK_OFFLOAD */
15248#ifdef FEATURE_WLAN_SCAN_PNO
15249 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
15250 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
15251#endif /*FEATURE_WLAN_SCAN_PNO */
15252 .resume = wlan_hdd_cfg80211_resume_wlan,
15253 .suspend = wlan_hdd_cfg80211_suspend_wlan,
15254 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
15255#ifdef WLAN_NL80211_TESTMODE
15256 .testmode_cmd = wlan_hdd_cfg80211_testmode,
15257#endif
15258#ifdef QCA_HT_2040_COEX
15259 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
15260#endif
15261 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015262#ifdef CHANNEL_SWITCH_SUPPORTED
15263 .channel_switch = wlan_hdd_cfg80211_channel_switch,
15264#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015265 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053015266#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
15267 defined(CFG80211_ABORT_SCAN)
15268 .abort_scan = wlan_hdd_cfg80211_abort_scan,
15269#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015270};