blob: d90a75cbd874c593ab16312c4f61f3d8f52cfb6e [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
Prakash Dhavali989127d2016-11-29 14:56:44 +05303785 * @adapter: Pointer to adapter struct
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003786 * @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 */
Prakash Dhavali989127d2016-11-29 14:56:44 +05303810int wlan_hdd_send_roam_auth_event(hdd_adapter_t *adapter, uint8_t *bssid,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003811 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{
Prakash Dhavali989127d2016-11-29 14:56:44 +05303814 hdd_context_t *hdd_ctx_ptr = WLAN_HDD_GET_CTX(adapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003815 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003816 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003817 ENTER();
3818
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303819 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003820 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003821
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07003822 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08003823 !roam_info_ptr->roamSynchInProgress)
3824 return 0;
3825
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003826 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
Prakash Dhavali989127d2016-11-29 14:56:44 +05303827 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003828 ETH_ALEN + req_rsn_len + rsp_rsn_len +
3829 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
3830 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003831 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003832 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
3833 GFP_KERNEL);
3834
3835 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003836 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003837 return -EINVAL;
3838 }
3839
3840 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
3841 ETH_ALEN, bssid) ||
3842 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
3843 req_rsn_len, req_rsn_ie) ||
3844 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
3845 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003846 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003847 goto nla_put_failure;
3848 }
Jeff Johnson020db452016-06-29 14:37:26 -07003849 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003850 if (roam_info_ptr->synchAuthStatus ==
3851 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07003852 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08003853 if (nla_put_u8(skb,
3854 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
3855 hdd_err("nla put fail");
3856 goto nla_put_failure;
3857 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003858 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
3859 /* if FT or CCKM connection: dont send replay counter */
3860 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
3861 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
3862 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
3863 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
3864 nla_put(skb,
3865 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
3866 SIR_REPLAY_CTR_LEN,
3867 roam_info_ptr->replay_ctr)) {
3868 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08003869 hdd_err("failed to send replay counter.");
3870 goto nla_put_failure;
3871 }
3872 if (nla_put(skb,
3873 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
3874 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
3875 nla_put(skb,
3876 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
3877 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
3878 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003879 goto nla_put_failure;
3880 }
3881 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07003882 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003883 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
3884 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003885 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003886 goto nla_put_failure;
3887 }
3888 }
3889
Jeff Johnson020db452016-06-29 14:37:26 -07003890 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003891 roam_info_ptr->subnet_change_status);
3892
3893 /*
3894 * Add subnet change status if subnet has changed
3895 * 0 = unchanged
3896 * 1 = changed
3897 * 2 = unknown
3898 */
3899 if (roam_info_ptr->subnet_change_status) {
3900 if (nla_put_u8(skb,
3901 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
3902 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003903 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003904 goto nla_put_failure;
3905 }
3906 }
3907
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003908 cfg80211_vendor_event(skb, GFP_KERNEL);
3909 return 0;
3910
3911nla_put_failure:
3912 kfree_skb(skb);
3913 return -EINVAL;
3914}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003915#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003916
3917static const struct nla_policy
3918wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
3919
3920 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
3921 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
3922 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303923 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303924 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
3925 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08003926 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
3927 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
3928 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
3929 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
3930 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05303931 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003932};
3933
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003934/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303935 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
3936 *
3937 * @adapter: Pointer to HDD adapter
3938 * @ie_data: Pointer to Scan IEs buffer
3939 * @ie_len: Length of Scan IEs
3940 *
3941 * Return: 0 on success; error number otherwise
3942 */
3943static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
3944 uint8_t *ie_data, uint8_t ie_len)
3945{
3946 hdd_scaninfo_t *scan_info = NULL;
3947 scan_info = &adapter->scan_info;
3948
3949 if (scan_info->default_scan_ies) {
3950 qdf_mem_free(scan_info->default_scan_ies);
3951 scan_info->default_scan_ies = NULL;
3952 }
3953
3954 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
3955 if (!scan_info->default_scan_ies)
3956 return -ENOMEM;
3957
3958 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
3959 scan_info->default_scan_ies_len = ie_len;
3960 return 0;
3961}
3962
3963/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003964 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3965 * vendor command
3966 *
3967 * @wiphy: wiphy device pointer
3968 * @wdev: wireless device pointer
3969 * @data: Vendor command data buffer
3970 * @data_len: Buffer length
3971 *
3972 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3973 *
3974 * Return: Error code.
3975 */
3976static int
3977__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3978 struct wireless_dev *wdev,
3979 const void *data,
3980 int data_len)
3981{
3982 struct net_device *dev = wdev->netdev;
3983 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3984 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3985 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
3986 int ret_val = 0;
3987 u32 modulated_dtim;
3988 u16 stats_avg_factor;
3989 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303990 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07003991 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07003992 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303993 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05303994 int attr_len;
3995 int access_policy = 0;
3996 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
3997 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05303998 uint16_t scan_ie_len = 0;
3999 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304000 struct sir_set_tx_rx_aggregation_size request;
4001 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004002 uint8_t retry, delay;
4003 int param_id;
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304004 uint32_t tx_fail_count;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304005
Jeff Johnson1f61b612016-02-12 16:28:33 -08004006 ENTER_DEV(dev);
4007
Anurag Chouhan6d760662016-02-20 16:05:43 +05304008 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004009 hdd_err("Command not allowed in FTM mode");
4010 return -EPERM;
4011 }
4012
4013 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304014 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004015 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004016
4017 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
4018 data, data_len,
4019 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004020 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004021 return -EINVAL;
4022 }
4023
Krunal Sonie3531942016-04-12 17:43:53 -07004024 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
4025 ftm_capab = nla_get_u32(tb[
4026 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
4027 hdd_ctx->config->fine_time_meas_cap =
4028 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
4029 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05304030 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07004031 hdd_ctx->config->fine_time_meas_cap);
4032 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
4033 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
4034 hdd_ctx->config->fine_time_meas_cap);
4035 }
4036
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004037 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4038 modulated_dtim = nla_get_u32(
4039 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4040
4041 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4042 adapter->sessionId,
4043 modulated_dtim);
4044
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304045 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004046 ret_val = -EPERM;
4047 }
4048
Kapil Gupta6213c012016-09-02 19:39:09 +05304049 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4050 qpower = nla_get_u8(
4051 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4052 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4053 ret_val = -EINVAL;
4054 }
4055
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004056 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4057 stats_avg_factor = nla_get_u16(
4058 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4059 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4060 adapter->sessionId,
4061 stats_avg_factor);
4062
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304063 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004064 ret_val = -EPERM;
4065 }
4066
4067
4068 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4069 guard_time = nla_get_u32(
4070 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4071 status = sme_configure_guard_time(hdd_ctx->hHal,
4072 adapter->sessionId,
4073 guard_time);
4074
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304075 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004076 ret_val = -EPERM;
4077 }
4078
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304079 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4080 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4081 attr_len = nla_len(
4082 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4083 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4084 hdd_info("Invalid value. attr_len %d",
4085 attr_len);
4086 return -EINVAL;
4087 }
4088
4089 nla_memcpy(&vendor_ie,
4090 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4091 attr_len);
4092 vendor_ie_present = true;
4093 hdd_info("Access policy vendor ie present.attr_len %d",
4094 attr_len);
4095 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4096 &vendor_ie[0], attr_len);
4097 }
4098
4099 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4100 access_policy = (int) nla_get_u32(
4101 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4102 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4103 (access_policy >
4104 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4105 hdd_info("Invalid value. access_policy %d",
4106 access_policy);
4107 return -EINVAL;
4108 }
4109 access_policy_present = true;
4110 hdd_info("Access policy present. access_policy %d",
4111 access_policy);
4112 }
4113
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004114 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4115 retry = nla_get_u8(tb[
4116 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4117 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4118 CFG_NON_AGG_RETRY_MAX : retry;
4119 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4120 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4121 retry, PDEV_CMD);
4122 }
4123
4124 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4125 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4126 retry = retry > CFG_AGG_RETRY_MAX ?
4127 CFG_AGG_RETRY_MAX : retry;
4128
4129 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4130 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4131 CFG_AGG_RETRY_MIN : retry;
4132 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4133 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4134 retry, PDEV_CMD);
4135 }
4136
4137 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4138 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4139 retry = retry > CFG_MGMT_RETRY_MAX ?
4140 CFG_MGMT_RETRY_MAX : retry;
4141 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4142 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4143 retry, PDEV_CMD);
4144 }
4145
4146 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4147 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4148 retry = retry > CFG_CTRL_RETRY_MAX ?
4149 CFG_CTRL_RETRY_MAX : retry;
4150 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4151 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4152 retry, PDEV_CMD);
4153 }
4154
4155 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4156 delay = nla_get_u8(tb[
4157 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4158 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4159 CFG_PROPAGATION_DELAY_MAX : delay;
4160 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4161 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4162 delay, PDEV_CMD);
4163 }
4164
Agrawal, Ashishb45599a2016-10-27 14:55:30 +05304165 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]) {
4166 tx_fail_count = nla_get_u32(
4167 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT]);
4168 if (tx_fail_count) {
4169 status = sme_update_tx_fail_cnt_threshold(hdd_ctx->hHal,
4170 adapter->sessionId, tx_fail_count);
4171 if (QDF_STATUS_SUCCESS != status) {
4172 hdd_info("sme_update_tx_fail_cnt_threshold (err=%d)",
4173 status);
4174 return -EINVAL;
4175 }
4176 }
4177 }
4178
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304179 if (vendor_ie_present && access_policy_present) {
4180 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4181 access_policy =
4182 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304183 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304184 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304185 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304186
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304187 hdd_info("calling sme_update_access_policy_vendor_ie");
4188 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4189 adapter->sessionId, &vendor_ie[0],
4190 access_policy);
4191 if (QDF_STATUS_SUCCESS != status) {
4192 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304193 return -EINVAL;
4194 }
4195 }
4196
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304197 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4198 set_value = nla_get_u8(
4199 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4200 hdd_info("set_value: %d", set_value);
4201 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4202 }
4203
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304204 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4205 scan_ie_len = nla_len(
4206 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4207 hdd_info("Received default scan IE of len %d session %d device mode %d",
4208 scan_ie_len, adapter->sessionId,
4209 adapter->device_mode);
4210 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4211 scan_ie = (uint8_t *) nla_data(tb
4212 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304213
4214 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4215 scan_ie_len))
4216 hdd_err("Failed to save default scan IEs");
4217
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304218 if (adapter->device_mode == QDF_STA_MODE) {
4219 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4220 adapter->sessionId, scan_ie,
4221 scan_ie_len);
4222 if (QDF_STATUS_SUCCESS != status)
4223 ret_val = -EPERM;
4224 }
4225 } else
4226 ret_val = -EPERM;
4227 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304228
4229 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4230 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4231 /* if one is specified, both must be specified */
4232 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4233 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4234 hdd_err("Both TX and RX MPDU Aggregation required");
4235 return -EINVAL;
4236 }
4237
4238 request.tx_aggregation_size = nla_get_u8(
4239 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4240 request.rx_aggregation_size = nla_get_u8(
4241 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4242 request.vdev_id = adapter->sessionId;
4243
4244 if (request.tx_aggregation_size >=
4245 CFG_TX_AGGREGATION_SIZE_MIN &&
4246 request.tx_aggregation_size <=
4247 CFG_TX_AGGREGATION_SIZE_MAX &&
4248 request.rx_aggregation_size >=
4249 CFG_RX_AGGREGATION_SIZE_MIN &&
4250 request.rx_aggregation_size <=
4251 CFG_RX_AGGREGATION_SIZE_MAX) {
4252 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4253 if (qdf_status != QDF_STATUS_SUCCESS) {
4254 hdd_err("failed to set aggr sizes err %d",
4255 qdf_status);
4256 ret_val = -EPERM;
4257 }
4258 } else {
4259 hdd_err("TX %d RX %d MPDU aggr size not in range",
4260 request.tx_aggregation_size,
4261 request.rx_aggregation_size);
4262 ret_val = -EINVAL;
4263 }
4264 }
4265
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304266 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4267 uint8_t ignore_assoc_disallowed;
4268
4269 ignore_assoc_disallowed
4270 = nla_get_u8(tb[
4271 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4272 hdd_info("Set ignore_assoc_disallowed value - %d",
4273 ignore_assoc_disallowed);
4274 if ((ignore_assoc_disallowed <
4275 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4276 (ignore_assoc_disallowed >
4277 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4278 return -EPERM;
4279
4280 sme_update_session_param(hdd_ctx->hHal,
4281 adapter->sessionId,
4282 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4283 ignore_assoc_disallowed);
4284 }
4285
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004286 return ret_val;
4287}
4288
4289/**
4290 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4291 * vendor command
4292 *
4293 * @wiphy: wiphy device pointer
4294 * @wdev: wireless device pointer
4295 * @data: Vendor command data buffer
4296 * @data_len: Buffer length
4297 *
4298 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4299 *
4300 * Return: EOK or other error codes.
4301 */
4302static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4303 struct wireless_dev *wdev,
4304 const void *data,
4305 int data_len)
4306{
4307 int ret;
4308
4309 cds_ssr_protect(__func__);
4310 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4311 data, data_len);
4312 cds_ssr_unprotect(__func__);
4313
4314 return ret;
4315}
4316
4317static const struct
4318nla_policy
4319qca_wlan_vendor_wifi_logger_start_policy
4320[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4321 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4322 = {.type = NLA_U32 },
4323 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4324 = {.type = NLA_U32 },
4325 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4326 = {.type = NLA_U32 },
4327};
4328
4329/**
4330 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4331 * or disable the collection of packet statistics from the firmware
4332 * @wiphy: WIPHY structure pointer
4333 * @wdev: Wireless device structure pointer
4334 * @data: Pointer to the data received
4335 * @data_len: Length of the data received
4336 *
4337 * This function enables or disables the collection of packet statistics from
4338 * the firmware
4339 *
4340 * Return: 0 on success and errno on failure
4341 */
4342static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4343 struct wireless_dev *wdev,
4344 const void *data,
4345 int data_len)
4346{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304347 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004348 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4349 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4350 struct sir_wifi_start_log start_log;
4351
Jeff Johnson1f61b612016-02-12 16:28:33 -08004352 ENTER_DEV(wdev->netdev);
4353
Anurag Chouhan6d760662016-02-20 16:05:43 +05304354 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004355 hdd_err("Command not allowed in FTM mode");
4356 return -EPERM;
4357 }
4358
4359 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304360 if (status)
4361 return status;
4362
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004363
4364 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4365 data, data_len,
4366 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004367 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004368 return -EINVAL;
4369 }
4370
4371 /* Parse and fetch ring id */
4372 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004373 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004374 return -EINVAL;
4375 }
4376 start_log.ring_id = nla_get_u32(
4377 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004378 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004379
4380 /* Parse and fetch verbose level */
4381 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004382 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004383 return -EINVAL;
4384 }
4385 start_log.verbose_level = nla_get_u32(
4386 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004387 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004388
4389 /* Parse and fetch flag */
4390 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004391 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004392 return -EINVAL;
4393 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304394 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004395 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304396 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004397
Poddar, Siddarth176c4362016-10-03 12:25:00 +05304398 /* size is buff size which can be set using iwpriv command*/
4399 start_log.size = 0;
4400
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004401 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4402
4403 if (start_log.ring_id == RING_ID_WAKELOCK) {
4404 /* Start/stop wakelock events */
4405 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4406 cds_set_wakelock_logging(true);
4407 else
4408 cds_set_wakelock_logging(false);
4409 return 0;
4410 }
4411
4412 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304413 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004414 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004415 status);
4416 return -EINVAL;
4417 }
4418 return 0;
4419}
4420
4421/**
4422 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4423 * or disable the collection of packet statistics from the firmware
4424 * @wiphy: WIPHY structure pointer
4425 * @wdev: Wireless device structure pointer
4426 * @data: Pointer to the data received
4427 * @data_len: Length of the data received
4428 *
4429 * This function is used to enable or disable the collection of packet
4430 * statistics from the firmware
4431 *
4432 * Return: 0 on success and errno on failure
4433 */
4434static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4435 struct wireless_dev *wdev,
4436 const void *data,
4437 int data_len)
4438{
4439 int ret = 0;
4440
4441 cds_ssr_protect(__func__);
4442 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4443 wdev, data, data_len);
4444 cds_ssr_unprotect(__func__);
4445
4446 return ret;
4447}
4448
4449static const struct
4450nla_policy
4451qca_wlan_vendor_wifi_logger_get_ring_data_policy
4452[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4453 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4454 = {.type = NLA_U32 },
4455};
4456
4457/**
4458 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4459 * @wiphy: WIPHY structure pointer
4460 * @wdev: Wireless device structure pointer
4461 * @data: Pointer to the data received
4462 * @data_len: Length of the data received
4463 *
4464 * This function is used to flush or retrieve the per packet statistics from
4465 * the driver
4466 *
4467 * Return: 0 on success and errno on failure
4468 */
4469static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4470 struct wireless_dev *wdev,
4471 const void *data,
4472 int data_len)
4473{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304474 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004475 uint32_t ring_id;
4476 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4477 struct nlattr *tb
4478 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4479
Jeff Johnson1f61b612016-02-12 16:28:33 -08004480 ENTER_DEV(wdev->netdev);
4481
Anurag Chouhan6d760662016-02-20 16:05:43 +05304482 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004483 hdd_err("Command not allowed in FTM mode");
4484 return -EPERM;
4485 }
4486
4487 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304488 if (status)
4489 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004490
4491 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
4492 data, data_len,
4493 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004494 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004495 return -EINVAL;
4496 }
4497
4498 /* Parse and fetch ring id */
4499 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004500 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004501 return -EINVAL;
4502 }
4503
4504 ring_id = nla_get_u32(
4505 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
4506
4507 if (ring_id == RING_ID_PER_PACKET_STATS) {
4508 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07004509 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05304510 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
4511 /*
4512 * As part of DRIVER ring ID, flush both driver and fw logs.
4513 * For other Ring ID's driver doesn't have any rings to flush
4514 */
4515 hdd_notice("Bug report triggered by framework");
4516
4517 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
4518 WLAN_LOG_INDICATOR_FRAMEWORK,
4519 WLAN_LOG_REASON_CODE_UNUSED,
4520 true, false);
4521 if (QDF_STATUS_SUCCESS != status) {
4522 hdd_err("Failed to trigger bug report");
4523 return -EINVAL;
4524 }
4525 } else {
4526 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
4527 WLAN_LOG_INDICATOR_FRAMEWORK,
4528 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004529 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004530 return 0;
4531}
4532
4533/**
4534 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
4535 * @wiphy: WIPHY structure pointer
4536 * @wdev: Wireless device structure pointer
4537 * @data: Pointer to the data received
4538 * @data_len: Length of the data received
4539 *
4540 * This function is used to flush or retrieve the per packet statistics from
4541 * the driver
4542 *
4543 * Return: 0 on success and errno on failure
4544 */
4545static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4546 struct wireless_dev *wdev,
4547 const void *data,
4548 int data_len)
4549{
4550 int ret = 0;
4551
4552 cds_ssr_protect(__func__);
4553 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
4554 wdev, data, data_len);
4555 cds_ssr_unprotect(__func__);
4556
4557 return ret;
4558}
4559
4560#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4561/**
4562 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
4563 * @hdd_ctx: HDD context
4564 * @request_id: [input] request id
4565 * @pattern_id: [output] pattern id
4566 *
4567 * This function loops through request id to pattern id array
4568 * if the slot is available, store the request id and return pattern id
4569 * if entry exists, return the pattern id
4570 *
4571 * Return: 0 on success and errno on failure
4572 */
4573static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4574 uint32_t request_id,
4575 uint8_t *pattern_id)
4576{
4577 uint32_t i;
4578
4579 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4580 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4581 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
4582 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
4583 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4584 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4585 return 0;
4586 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
4587 request_id) {
4588 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4589 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4590 return 0;
4591 }
4592 }
4593 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4594 return -EINVAL;
4595}
4596
4597/**
4598 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
4599 * @hdd_ctx: HDD context
4600 * @request_id: [input] request id
4601 * @pattern_id: [output] pattern id
4602 *
4603 * This function loops through request id to pattern id array
4604 * reset request id to 0 (slot available again) and
4605 * return pattern id
4606 *
4607 * Return: 0 on success and errno on failure
4608 */
4609static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4610 uint32_t request_id,
4611 uint8_t *pattern_id)
4612{
4613 uint32_t i;
4614
4615 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4616 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4617 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
4618 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4619 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4620 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4621 return 0;
4622 }
4623 }
4624 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4625 return -EINVAL;
4626}
4627
4628
4629/*
4630 * define short names for the global vendor params
4631 * used by __wlan_hdd_cfg80211_offloaded_packets()
4632 */
4633#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
4634#define PARAM_REQUEST_ID \
4635 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
4636#define PARAM_CONTROL \
4637 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
4638#define PARAM_IP_PACKET \
4639 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
4640#define PARAM_SRC_MAC_ADDR \
4641 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
4642#define PARAM_DST_MAC_ADDR \
4643 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
4644#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
4645
4646/**
4647 * wlan_hdd_add_tx_ptrn() - add tx pattern
4648 * @adapter: adapter pointer
4649 * @hdd_ctx: hdd context
4650 * @tb: nl attributes
4651 *
4652 * This function reads the NL attributes and forms a AddTxPtrn message
4653 * posts it to SME.
4654 *
4655 */
4656static int
4657wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4658 struct nlattr **tb)
4659{
4660 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304661 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004662 uint32_t request_id, ret, len;
4663 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304664 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004665 uint16_t eth_type = htons(ETH_P_IP);
4666
4667 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004668 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004669 return -ENOTSUPP;
4670 }
4671
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304672 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004673 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004674 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004675 return -ENOMEM;
4676 }
4677
4678 /* Parse and fetch request Id */
4679 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004680 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004681 goto fail;
4682 }
4683
4684 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4685 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004686 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004687 return -EINVAL;
4688 }
Jeff Johnson77848112016-06-29 14:52:06 -07004689 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004690
4691 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004692 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004693 goto fail;
4694 }
4695 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07004696 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004697 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07004698 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004699 goto fail;
4700 }
4701
4702 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004703 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004704 goto fail;
4705 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08004706 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05304707 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004708 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004709 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004710
Anurag Chouhanc5548422016-02-24 18:33:27 +05304711 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004712 &adapter->macAddressCurrent)) {
4713 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004714 goto fail;
4715 }
4716
4717 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004718 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004719 goto fail;
4720 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05304721 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004722 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004723 MAC_ADDR_ARRAY(dst_addr.bytes));
4724
4725 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004726 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004727 goto fail;
4728 }
4729 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07004730 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004731
4732 if (add_req->ucPtrnSize < 0 ||
4733 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
4734 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004735 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004736 add_req->ucPtrnSize);
4737 goto fail;
4738 }
4739
4740 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304741 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05304742 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304743 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304744 QDF_MAC_ADDR_SIZE);
4745 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304746 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004747 len += 2;
4748
4749 /*
4750 * This is the IP packet, add 14 bytes Ethernet (802.3) header
4751 * ------------------------------------------------------------
4752 * | 14 bytes Ethernet (802.3) header | IP header and payload |
4753 * ------------------------------------------------------------
4754 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304755 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004756 nla_data(tb[PARAM_IP_PACKET]),
4757 add_req->ucPtrnSize);
4758 add_req->ucPtrnSize += len;
4759
4760 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4761 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004762 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004763 goto fail;
4764 }
4765 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004766 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004767
4768 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304769 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004770 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004771 goto fail;
4772 }
4773
4774 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304775 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004776 return 0;
4777
4778fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304779 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004780 return -EINVAL;
4781}
4782
4783/**
4784 * wlan_hdd_del_tx_ptrn() - delete tx pattern
4785 * @adapter: adapter pointer
4786 * @hdd_ctx: hdd context
4787 * @tb: nl attributes
4788 *
4789 * This function reads the NL attributes and forms a DelTxPtrn message
4790 * posts it to SME.
4791 *
4792 */
4793static int
4794wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4795 struct nlattr **tb)
4796{
4797 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304798 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004799 uint32_t request_id, ret;
4800 uint8_t pattern_id = 0;
4801
4802 /* Parse and fetch request Id */
4803 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004804 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004805 return -EINVAL;
4806 }
4807 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4808 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004809 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004810 return -EINVAL;
4811 }
4812
4813 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4814 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004815 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004816 return -EINVAL;
4817 }
4818
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304819 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004820 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004821 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004822 return -ENOMEM;
4823 }
4824
Anurag Chouhanc5548422016-02-24 18:33:27 +05304825 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004826 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004827 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004828 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004829 request_id, del_req->ucPtrnId);
4830
4831 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304832 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004833 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004834 goto fail;
4835 }
4836
4837 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304838 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004839 return 0;
4840
4841fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304842 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004843 return -EINVAL;
4844}
4845
4846
4847/**
4848 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
4849 * @wiphy: Pointer to wireless phy
4850 * @wdev: Pointer to wireless device
4851 * @data: Pointer to data
4852 * @data_len: Data length
4853 *
4854 * Return: 0 on success, negative errno on failure
4855 */
4856static int
4857__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4858 struct wireless_dev *wdev,
4859 const void *data,
4860 int data_len)
4861{
4862 struct net_device *dev = wdev->netdev;
4863 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4864 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4865 struct nlattr *tb[PARAM_MAX + 1];
4866 uint8_t control;
4867 int ret;
4868 static const struct nla_policy policy[PARAM_MAX + 1] = {
4869 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4870 [PARAM_CONTROL] = { .type = NLA_U32 },
4871 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304872 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004873 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304874 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004875 [PARAM_PERIOD] = { .type = NLA_U32 },
4876 };
4877
Jeff Johnson1f61b612016-02-12 16:28:33 -08004878 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004879
Anurag Chouhan6d760662016-02-20 16:05:43 +05304880 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004881 hdd_err("Command not allowed in FTM mode");
4882 return -EPERM;
4883 }
4884
4885 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304886 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004887 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004888
4889 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004890 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004891 return -ENOTSUPP;
4892 }
4893
4894 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004895 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004896 return -EINVAL;
4897 }
4898
4899 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004900 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004901 return -EINVAL;
4902 }
4903 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07004904 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004905
4906 if (control == WLAN_START_OFFLOADED_PACKETS)
4907 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
4908 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
4909 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
4910 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004911 hdd_err("Invalid control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004912 return -EINVAL;
4913 }
4914}
4915
4916/*
4917 * done with short names for the global vendor params
4918 * used by __wlan_hdd_cfg80211_offloaded_packets()
4919 */
4920#undef PARAM_MAX
4921#undef PARAM_REQUEST_ID
4922#undef PARAM_CONTROL
4923#undef PARAM_IP_PACKET
4924#undef PARAM_SRC_MAC_ADDR
4925#undef PARAM_DST_MAC_ADDR
4926#undef PARAM_PERIOD
4927
4928/**
4929 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
4930 * @wiphy: wiphy structure pointer
4931 * @wdev: Wireless device structure pointer
4932 * @data: Pointer to the data received
4933 * @data_len: Length of @data
4934 *
4935 * Return: 0 on success; errno on failure
4936 */
4937static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4938 struct wireless_dev *wdev,
4939 const void *data,
4940 int data_len)
4941{
4942 int ret = 0;
4943
4944 cds_ssr_protect(__func__);
4945 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
4946 wdev, data, data_len);
4947 cds_ssr_unprotect(__func__);
4948
4949 return ret;
4950}
4951#endif
4952
4953/*
4954 * define short names for the global vendor params
4955 * used by __wlan_hdd_cfg80211_monitor_rssi()
4956 */
4957#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
4958#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
4959#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
4960#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
4961#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
4962
4963/**
4964 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
4965 * @wiphy: Pointer to wireless phy
4966 * @wdev: Pointer to wireless device
4967 * @data: Pointer to data
4968 * @data_len: Data length
4969 *
4970 * Return: 0 on success, negative errno on failure
4971 */
4972static int
4973__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
4974 struct wireless_dev *wdev,
4975 const void *data,
4976 int data_len)
4977{
4978 struct net_device *dev = wdev->netdev;
4979 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4980 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4981 struct nlattr *tb[PARAM_MAX + 1];
4982 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304983 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004984 int ret;
4985 uint32_t control;
4986 static const struct nla_policy policy[PARAM_MAX + 1] = {
4987 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4988 [PARAM_CONTROL] = { .type = NLA_U32 },
4989 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
4990 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
4991 };
4992
Jeff Johnson1f61b612016-02-12 16:28:33 -08004993 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004994
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05304995 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
4996 hdd_err("invalid session id: %d", adapter->sessionId);
4997 return -EINVAL;
4998 }
4999
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005000 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05305001 if (ret)
5002 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005003
5004 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07005005 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005006 return -ENOTSUPP;
5007 }
5008
5009 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005010 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005011 return -EINVAL;
5012 }
5013
5014 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005015 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005016 return -EINVAL;
5017 }
5018
5019 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005020 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005021 return -EINVAL;
5022 }
5023
5024 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
5025 req.session_id = adapter->sessionId;
5026 control = nla_get_u32(tb[PARAM_CONTROL]);
5027
5028 if (control == QCA_WLAN_RSSI_MONITORING_START) {
5029 req.control = true;
5030 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005031 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005032 return -EINVAL;
5033 }
5034
5035 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005036 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005037 return -EINVAL;
5038 }
5039
5040 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
5041 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
5042
5043 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005044 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005045 req.min_rssi, req.max_rssi);
5046 return -EINVAL;
5047 }
Jeff Johnson77848112016-06-29 14:52:06 -07005048 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005049 req.min_rssi, req.max_rssi);
5050
5051 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
5052 req.control = false;
5053 else {
Jeff Johnson77848112016-06-29 14:52:06 -07005054 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005055 return -EINVAL;
5056 }
Jeff Johnson77848112016-06-29 14:52:06 -07005057 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005058 req.request_id, req.session_id, req.control);
5059
5060 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305061 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005062 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005063 return -EINVAL;
5064 }
5065
5066 return 0;
5067}
5068
5069/*
5070 * done with short names for the global vendor params
5071 * used by __wlan_hdd_cfg80211_monitor_rssi()
5072 */
5073#undef PARAM_MAX
5074#undef PARAM_CONTROL
5075#undef PARAM_REQUEST_ID
5076#undef PARAM_MAX_RSSI
5077#undef PARAM_MIN_RSSI
5078
5079/**
5080 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5081 * @wiphy: wiphy structure pointer
5082 * @wdev: Wireless device structure pointer
5083 * @data: Pointer to the data received
5084 * @data_len: Length of @data
5085 *
5086 * Return: 0 on success; errno on failure
5087 */
5088static int
5089wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5090 const void *data, int data_len)
5091{
5092 int ret;
5093
5094 cds_ssr_protect(__func__);
5095 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5096 cds_ssr_unprotect(__func__);
5097
5098 return ret;
5099}
5100
5101/**
5102 * hdd_rssi_threshold_breached() - rssi breached NL event
5103 * @hddctx: HDD context
5104 * @data: rssi breached event data
5105 *
5106 * This function reads the rssi breached event %data and fill in the skb with
5107 * NL attributes and send up the NL event.
5108 *
5109 * Return: none
5110 */
5111void hdd_rssi_threshold_breached(void *hddctx,
5112 struct rssi_breach_event *data)
5113{
5114 hdd_context_t *hdd_ctx = hddctx;
5115 struct sk_buff *skb;
5116
5117 ENTER();
5118
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305119 if (wlan_hdd_validate_context(hdd_ctx))
5120 return;
5121 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005122 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005123 return;
5124 }
5125
5126 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5127 NULL,
5128 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5129 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5130 GFP_KERNEL);
5131
5132 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005133 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005134 return;
5135 }
5136
Jeff Johnson77848112016-06-29 14:52:06 -07005137 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005138 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005139 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005140 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5141
5142 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5143 data->request_id) ||
5144 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5145 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5146 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5147 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005148 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005149 goto fail;
5150 }
5151
5152 cfg80211_vendor_event(skb, GFP_KERNEL);
5153 return;
5154
5155fail:
5156 kfree_skb(skb);
5157 return;
5158}
5159
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305160static const struct nla_policy
5161ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5162 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5163};
5164
5165/**
5166 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5167 * @wiphy: Pointer to wireless phy
5168 * @wdev: Pointer to wireless device
5169 * @data: Pointer to data
5170 * @data_len: Length of @data
5171 *
5172 * Return: 0 on success, negative errno on failure
5173 */
5174static int
5175__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5176 struct wireless_dev *wdev,
5177 const void *data, int data_len)
5178{
5179 int status;
5180 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5181 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005182 struct net_device *dev = wdev->netdev;
5183 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305184
5185 ENTER_DEV(wdev->netdev);
5186
5187 status = wlan_hdd_validate_context(pHddCtx);
5188 if (0 != status)
5189 return status;
5190 if (!pHddCtx->config->fhostNSOffload) {
5191 hdd_err("ND Offload not supported");
5192 return -EINVAL;
5193 }
5194
5195 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5196 (struct nlattr *)data,
5197 data_len, ns_offload_set_policy)) {
5198 hdd_err("nla_parse failed");
5199 return -EINVAL;
5200 }
5201
5202 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5203 hdd_err("ND Offload flag attribute not present");
5204 return -EINVAL;
5205 }
5206
5207 pHddCtx->ns_offload_enable =
5208 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5209
Dustin Brownd8279d22016-09-07 14:52:57 -07005210 /* update ns offload in case it is already enabled/disabled */
5211 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
5212
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305213 return 0;
5214}
5215
5216/**
5217 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5218 * @wiphy: pointer to wireless wiphy structure.
5219 * @wdev: pointer to wireless_dev structure.
5220 * @data: Pointer to the data to be passed via vendor interface
5221 * @data_len:Length of the data to be passed
5222 *
5223 * Return: Return the Success or Failure code.
5224 */
5225static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5226 struct wireless_dev *wdev,
5227 const void *data, int data_len)
5228{
5229 int ret;
5230
5231 cds_ssr_protect(__func__);
5232 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5233 cds_ssr_unprotect(__func__);
5234
5235 return ret;
5236}
5237
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005238/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5239 * @wiphy: Pointer to wireless phy
5240 * @wdev: Pointer to wireless device
5241 * @data: Pointer to data
5242 * @data_len: Data length
5243 *
5244 * This function return the preferred frequency list generated by the policy
5245 * manager.
5246 *
5247 * Return: success or failure code
5248 */
5249static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5250 struct wireless_dev
5251 *wdev, const void *data,
5252 int data_len)
5253{
5254 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5255 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305256 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305257 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005258 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305259 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005260 enum cds_con_mode intf_mode;
5261 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5262 struct sk_buff *reply_skb;
5263
Jeff Johnson1f61b612016-02-12 16:28:33 -08005264 ENTER_DEV(wdev->netdev);
5265
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005266 ret = wlan_hdd_validate_context(hdd_ctx);
5267 if (ret)
5268 return -EINVAL;
5269
5270 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5271 data, data_len, NULL)) {
5272 hdd_err("Invalid ATTR");
5273 return -EINVAL;
5274 }
5275
5276 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5277 hdd_err("attr interface type failed");
5278 return -EINVAL;
5279 }
5280
5281 intf_mode = nla_get_u32(tb
5282 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5283
5284 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5285 hdd_err("Invalid interface type");
5286 return -EINVAL;
5287 }
5288
5289 hdd_debug("Userspace requested pref freq list");
5290
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305291 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5292 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305293 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005294 hdd_err("Get pcl failed");
5295 return -EINVAL;
5296 }
5297
5298 /* convert channel number to frequency */
5299 for (i = 0; i < pcl_len; i++) {
5300 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5301 freq_list[i] =
5302 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005303 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005304 else
5305 freq_list[i] =
5306 ieee80211_channel_to_frequency(pcl[i],
Dustin Browna30892e2016-10-12 17:28:36 -07005307 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005308 }
5309
5310 /* send the freq_list back to supplicant */
5311 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5312 sizeof(u32) *
5313 pcl_len +
5314 NLMSG_HDRLEN);
5315
5316 if (!reply_skb) {
5317 hdd_err("Allocate reply_skb failed");
5318 return -EINVAL;
5319 }
5320
5321 if (nla_put_u32(reply_skb,
5322 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5323 intf_mode) ||
5324 nla_put(reply_skb,
5325 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5326 sizeof(uint32_t) * pcl_len,
5327 freq_list)) {
5328 hdd_err("nla put fail");
5329 kfree_skb(reply_skb);
5330 return -EINVAL;
5331 }
5332
5333 return cfg80211_vendor_cmd_reply(reply_skb);
5334}
5335
5336/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5337 * @wiphy: Pointer to wireless phy
5338 * @wdev: Pointer to wireless device
5339 * @data: Pointer to data
5340 * @data_len: Data length
5341 *
5342 * This function return the preferred frequency list generated by the policy
5343 * manager.
5344 *
5345 * Return: success or failure code
5346 */
5347static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5348 struct wireless_dev
5349 *wdev, const void *data,
5350 int data_len)
5351{
5352 int ret = 0;
5353
5354 cds_ssr_protect(__func__);
5355 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5356 data, data_len);
5357 cds_ssr_unprotect(__func__);
5358
5359 return ret;
5360}
5361
5362/**
5363 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5364 * @wiphy: Pointer to wireless phy
5365 * @wdev: Pointer to wireless device
5366 * @data: Pointer to data
5367 * @data_len: Data length
5368 *
5369 * Return: 0 on success, negative errno on failure
5370 */
5371static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5372 struct wireless_dev *wdev,
5373 const void *data,
5374 int data_len)
5375{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305376 struct net_device *ndev = wdev->netdev;
5377 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005378 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5379 int ret = 0;
5380 enum cds_con_mode intf_mode;
5381 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5382 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005383
Jeff Johnson1f61b612016-02-12 16:28:33 -08005384 ENTER_DEV(ndev);
5385
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005386 ret = wlan_hdd_validate_context(hdd_ctx);
5387 if (ret)
5388 return ret;
5389
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005390 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5391 data, data_len, NULL)) {
5392 hdd_err("Invalid ATTR");
5393 return -EINVAL;
5394 }
5395
5396 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5397 hdd_err("attr interface type failed");
5398 return -EINVAL;
5399 }
5400
5401 intf_mode = nla_get_u32(tb
5402 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5403
5404 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5405 hdd_err("Invalid interface type");
5406 return -EINVAL;
5407 }
5408
5409 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5410 hdd_err("attr probable freq failed");
5411 return -EINVAL;
5412 }
5413
5414 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5415 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5416
5417 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005418 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005419 channel_hint, HW_MODE_20_MHZ)) {
5420 hdd_err("Set channel hint failed due to concurrency check");
5421 return -EINVAL;
5422 }
5423
Krunal Soni09e55032016-06-07 10:06:55 -07005424 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5425 hdd_warn("Remain On Channel Pending");
5426
Krunal Soni3091bcc2016-06-23 12:28:21 -07005427 ret = qdf_reset_connection_update();
5428 if (!QDF_IS_STATUS_SUCCESS(ret))
5429 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005430
Krunal Soni3091bcc2016-06-23 12:28:21 -07005431 ret = cds_current_connections_update(adapter->sessionId,
5432 channel_hint,
5433 SIR_UPDATE_REASON_SET_OPER_CHAN);
5434 if (QDF_STATUS_E_FAILURE == ret) {
5435 /* return in the failure case */
5436 hdd_err("ERROR: connections update failed!!");
5437 return -EINVAL;
5438 }
5439
5440 if (QDF_STATUS_SUCCESS == ret) {
5441 /*
5442 * Success is the only case for which we expect hw mode
5443 * change to take place, hence we need to wait.
5444 * For any other return value it should be a pass
5445 * through
5446 */
5447 ret = qdf_wait_for_connection_update();
5448 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5449 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005450 return -EINVAL;
5451 }
5452
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005453 }
5454
5455 return 0;
5456}
5457
5458/**
5459 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5460 * @wiphy: Pointer to wireless phy
5461 * @wdev: Pointer to wireless device
5462 * @data: Pointer to data
5463 * @data_len: Data length
5464 *
5465 * Return: 0 on success, negative errno on failure
5466 */
5467static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5468 struct wireless_dev *wdev,
5469 const void *data,
5470 int data_len)
5471{
5472 int ret = 0;
5473
5474 cds_ssr_protect(__func__);
5475 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5476 data, data_len);
5477 cds_ssr_unprotect(__func__);
5478
5479 return ret;
5480}
5481
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305482static const struct
5483nla_policy
5484qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5485 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5486};
5487
5488/**
5489 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
5490 * @wiphy: WIPHY structure pointer
5491 * @wdev: Wireless device structure pointer
5492 * @data: Pointer to the data received
5493 * @data_len: Length of the data received
5494 *
5495 * This function is used to get link properties like nss, rate flags and
5496 * operating frequency for the active connection with the given peer.
5497 *
5498 * Return: 0 on success and errno on failure
5499 */
5500static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5501 struct wireless_dev *wdev,
5502 const void *data,
5503 int data_len)
5504{
5505 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5506 struct net_device *dev = wdev->netdev;
5507 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5508 hdd_station_ctx_t *hdd_sta_ctx;
5509 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05305510 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305511 uint32_t sta_id;
5512 struct sk_buff *reply_skb;
5513 uint32_t rate_flags = 0;
5514 uint8_t nss;
5515 uint8_t final_rate_flags = 0;
5516 uint32_t freq;
5517
Jeff Johnson1f61b612016-02-12 16:28:33 -08005518 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305519
Anurag Chouhan6d760662016-02-20 16:05:43 +05305520 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305521 hdd_err("Command not allowed in FTM mode");
5522 return -EPERM;
5523 }
5524
5525 if (0 != wlan_hdd_validate_context(hdd_ctx))
5526 return -EINVAL;
5527
5528 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
5529 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005530 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305531 return -EINVAL;
5532 }
5533
5534 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005535 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305536 adapter->device_mode);
5537 return -EINVAL;
5538 }
5539
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305540 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05305541 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005542 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305543 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
5544
Krunal Sonib4326f22016-03-10 13:05:51 -08005545 if (adapter->device_mode == QDF_STA_MODE ||
5546 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305547 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
5548 if ((hdd_sta_ctx->conn_info.connState !=
5549 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305550 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305551 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005552 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305553 MAC_ADDR_ARRAY(peer_mac));
5554 return -EINVAL;
5555 }
5556
5557 nss = hdd_sta_ctx->conn_info.nss;
5558 freq = cds_chan_to_freq(
5559 hdd_sta_ctx->conn_info.operationChannel);
5560 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08005561 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
5562 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305563
5564 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
5565 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05305566 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305567 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305568 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305569 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305570 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305571 break;
5572 }
5573
5574 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07005575 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305576 MAC_ADDR_ARRAY(peer_mac));
5577 return -EINVAL;
5578 }
5579
5580 nss = adapter->aStaInfo[sta_id].nss;
5581 freq = cds_chan_to_freq(
5582 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
5583 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
5584 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07005585 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305586 MAC_ADDR_ARRAY(peer_mac));
5587 return -EINVAL;
5588 }
5589
5590 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
5591 if (rate_flags & eHAL_TX_RATE_VHT80) {
5592 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005593#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305594 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005595#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305596 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
5597 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005598#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305599 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005600#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305601 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
5602 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
5603 } else if (rate_flags &
5604 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
5605 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005606#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305607 if (rate_flags & eHAL_TX_RATE_HT40)
5608 final_rate_flags |=
5609 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005610#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305611 }
5612
5613 if (rate_flags & eHAL_TX_RATE_SGI) {
5614 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
5615 final_rate_flags |= RATE_INFO_FLAGS_MCS;
5616 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
5617 }
5618 }
5619
5620 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5621 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
5622
5623 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005624 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305625 return -EINVAL;
5626 }
5627
5628 if (nla_put_u8(reply_skb,
5629 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
5630 nss) ||
5631 nla_put_u8(reply_skb,
5632 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
5633 final_rate_flags) ||
5634 nla_put_u32(reply_skb,
5635 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
5636 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005637 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305638 kfree_skb(reply_skb);
5639 return -EINVAL;
5640 }
5641
5642 return cfg80211_vendor_cmd_reply(reply_skb);
5643}
5644
5645/**
5646 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
5647 * properties.
5648 * @wiphy: WIPHY structure pointer
5649 * @wdev: Wireless device structure pointer
5650 * @data: Pointer to the data received
5651 * @data_len: Length of the data received
5652 *
5653 * This function is used to get link properties like nss, rate flags and
5654 * operating frequency for the active connection with the given peer.
5655 *
5656 * Return: 0 on success and errno on failure
5657 */
5658static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5659 struct wireless_dev *wdev,
5660 const void *data,
5661 int data_len)
5662{
5663 int ret = 0;
5664
5665 cds_ssr_protect(__func__);
5666 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
5667 wdev, data, data_len);
5668 cds_ssr_unprotect(__func__);
5669
5670 return ret;
5671}
5672
Peng Xu278d0122015-09-24 16:34:17 -07005673static const struct
5674nla_policy
5675qca_wlan_vendor_ota_test_policy
5676[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
5677 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
5678};
5679
5680/**
5681 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
5682 * @wiphy: Pointer to wireless phy
5683 * @wdev: Pointer to wireless device
5684 * @data: Pointer to data
5685 * @data_len: Data length
5686 *
5687 * Return: 0 on success, negative errno on failure
5688 */
5689static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5690 struct wireless_dev *wdev,
5691 const void *data,
5692 int data_len)
5693{
5694 struct net_device *dev = wdev->netdev;
5695 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5696 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
5697 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5698 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
5699 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305700 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07005701 uint32_t current_roam_state;
5702
Jeff Johnson1f61b612016-02-12 16:28:33 -08005703 ENTER_DEV(dev);
5704
Anurag Chouhan6d760662016-02-20 16:05:43 +05305705 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07005706 hdd_err("Command not allowed in FTM mode");
5707 return -EPERM;
5708 }
5709
5710 if (0 != wlan_hdd_validate_context(hdd_ctx))
5711 return -EINVAL;
5712
5713 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
5714 data, data_len,
5715 qca_wlan_vendor_ota_test_policy)) {
5716 hdd_err("invalid attr");
5717 return -EINVAL;
5718 }
5719
5720 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
5721 hdd_err("attr ota test failed");
5722 return -EINVAL;
5723 }
5724
5725 ota_enable = nla_get_u8(
5726 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
5727
5728 hdd_info(" OTA test enable = %d", ota_enable);
5729 if (ota_enable != 1) {
5730 hdd_err("Invalid value, only enable test mode is supported!");
5731 return -EINVAL;
5732 }
5733
5734 current_roam_state =
5735 sme_get_current_roam_state(hal, adapter->sessionId);
5736 status = sme_stop_roaming(hal, adapter->sessionId,
5737 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305738 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005739 hdd_err("Enable/Disable roaming failed");
5740 return -EINVAL;
5741 }
5742
5743 status = sme_ps_enable_disable(hal, adapter->sessionId,
5744 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305745 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005746 hdd_err("Enable/Disable power save failed");
5747 /* restore previous roaming setting */
5748 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
5749 current_roam_state == eCSR_ROAMING_STATE_JOINED)
5750 status = sme_start_roaming(hal, adapter->sessionId,
5751 eCsrHddIssued);
5752 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
5753 current_roam_state == eCSR_ROAMING_STATE_IDLE)
5754 status = sme_stop_roaming(hal, adapter->sessionId,
5755 eCsrHddIssued);
5756
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305757 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07005758 hdd_err("Restoring roaming state failed");
5759
5760 return -EINVAL;
5761 }
5762
5763
5764 return 0;
5765}
5766
5767/**
5768 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
5769 * @wiphy: Pointer to wireless phy
5770 * @wdev: Pointer to wireless device
5771 * @data: Pointer to data
5772 * @data_len: Data length
5773 *
5774 * Return: 0 on success, negative errno on failure
5775 */
5776static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5777 struct wireless_dev *wdev,
5778 const void *data,
5779 int data_len)
5780{
5781 int ret = 0;
5782
5783 cds_ssr_protect(__func__);
5784 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
5785 cds_ssr_unprotect(__func__);
5786
5787 return ret;
5788}
5789
Peng Xu4d67c8f2015-10-16 16:02:26 -07005790/**
5791 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5792 * @wiphy: Pointer to wireless phy
5793 * @wdev: Pointer to wireless device
5794 * @data: Pointer to data
5795 * @data_len: Data length
5796 *
5797 * Return: 0 on success, negative errno on failure
5798 */
5799static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5800 struct wireless_dev *wdev,
5801 const void *data,
5802 int data_len)
5803{
5804 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5805 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005806 hdd_adapter_t *adapter;
5807 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005808 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
5809 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005810 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005811
Jeff Johnson1f61b612016-02-12 16:28:33 -08005812 ENTER_DEV(dev);
5813
Peng Xu4d67c8f2015-10-16 16:02:26 -07005814 ret = wlan_hdd_validate_context(hdd_ctx);
5815 if (ret)
5816 return ret;
5817
5818 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5819
5820 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
5821 data, data_len, NULL)) {
5822 hdd_err("Invalid ATTR");
5823 return -EINVAL;
5824 }
5825
5826 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
5827 hdd_err("attr tx power scale failed");
5828 return -EINVAL;
5829 }
5830
5831 scale_value = nla_get_u8(tb
5832 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
5833
5834 if (scale_value > MAX_TXPOWER_SCALE) {
5835 hdd_err("Invalid tx power scale level");
5836 return -EINVAL;
5837 }
5838
Peng Xu62c8c432016-05-09 15:23:02 -07005839 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005840
Peng Xu62c8c432016-05-09 15:23:02 -07005841 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005842 hdd_err("Set tx power scale failed");
5843 return -EINVAL;
5844 }
5845
5846 return 0;
5847}
5848
5849/**
5850 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5851 * @wiphy: Pointer to wireless phy
5852 * @wdev: Pointer to wireless device
5853 * @data: Pointer to data
5854 * @data_len: Data length
5855 *
5856 * Return: 0 on success, negative errno on failure
5857 */
5858static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5859 struct wireless_dev *wdev,
5860 const void *data,
5861 int data_len)
5862{
Peng Xu62c8c432016-05-09 15:23:02 -07005863 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005864
5865 cds_ssr_protect(__func__);
5866 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
5867 data, data_len);
5868 cds_ssr_unprotect(__func__);
5869
5870 return ret;
5871}
5872
5873/**
5874 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5875 * @wiphy: Pointer to wireless phy
5876 * @wdev: Pointer to wireless device
5877 * @data: Pointer to data
5878 * @data_len: Data length
5879 *
5880 * Return: 0 on success, negative errno on failure
5881 */
5882static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5883 struct wireless_dev *wdev,
5884 const void *data,
5885 int data_len)
5886{
5887 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5888 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005889 hdd_adapter_t *adapter;
5890 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005891 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
5892 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005893 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005894
Jeff Johnson1f61b612016-02-12 16:28:33 -08005895 ENTER_DEV(dev);
5896
Peng Xu4d67c8f2015-10-16 16:02:26 -07005897 ret = wlan_hdd_validate_context(hdd_ctx);
5898 if (ret)
5899 return ret;
5900
5901 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5902
5903 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
5904 data, data_len, NULL)) {
5905 hdd_err("Invalid ATTR");
5906 return -EINVAL;
5907 }
5908
5909 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
5910 hdd_err("attr tx power decrease db value failed");
5911 return -EINVAL;
5912 }
5913
5914 scale_value = nla_get_u8(tb
5915 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
5916
Peng Xu62c8c432016-05-09 15:23:02 -07005917 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
5918 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005919
Peng Xu62c8c432016-05-09 15:23:02 -07005920 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005921 hdd_err("Set tx power decrease db failed");
5922 return -EINVAL;
5923 }
5924
5925 return 0;
5926}
5927
5928/**
5929 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5930 * @wiphy: Pointer to wireless phy
5931 * @wdev: Pointer to wireless device
5932 * @data: Pointer to data
5933 * @data_len: Data length
5934 *
5935 * Return: 0 on success, negative errno on failure
5936 */
5937static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5938 struct wireless_dev *wdev,
5939 const void *data,
5940 int data_len)
5941{
Peng Xu62c8c432016-05-09 15:23:02 -07005942 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005943
5944 cds_ssr_protect(__func__);
5945 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
5946 data, data_len);
5947 cds_ssr_unprotect(__func__);
5948
5949 return ret;
5950}
Peng Xu8fdaa492016-06-22 10:20:47 -07005951
5952/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05305953 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
5954 * @wiphy: Pointer to wireless phy
5955 * @wdev: Pointer to wireless device
5956 * @data: Pointer to data
5957 * @data_len: Data length
5958 *
5959 * Processes the conditional channel switch request and invokes the helper
5960 * APIs to process the channel switch request.
5961 *
5962 * Return: 0 on success, negative errno on failure
5963 */
5964static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
5965 struct wireless_dev *wdev,
5966 const void *data,
5967 int data_len)
5968{
5969 int ret;
5970 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5971 struct net_device *dev = wdev->netdev;
5972 hdd_adapter_t *adapter;
5973 struct nlattr
5974 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
5975 uint32_t freq_len, i;
5976 uint32_t *freq;
5977 uint8_t chans[QDF_MAX_NUM_CHAN];
5978
5979 ENTER_DEV(dev);
5980
5981 ret = wlan_hdd_validate_context(hdd_ctx);
5982 if (ret)
5983 return ret;
5984
5985 if (!hdd_ctx->config->enableDFSMasterCap) {
5986 hdd_err("DFS master capability is not present in the driver");
5987 return -EINVAL;
5988 }
5989
5990 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5991 hdd_err("Command not allowed in FTM mode");
5992 return -EPERM;
5993 }
5994
5995 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5996 if (adapter->device_mode != QDF_SAP_MODE) {
5997 hdd_err("Invalid device mode %d", adapter->device_mode);
5998 return -EINVAL;
5999 }
6000
6001 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
6002 data, data_len, NULL)) {
6003 hdd_err("Invalid ATTR");
6004 return -EINVAL;
6005 }
6006
6007 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
6008 hdd_err("Frequency list is missing");
6009 return -EINVAL;
6010 }
6011
6012 freq_len = nla_len(
6013 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
6014 sizeof(uint32_t);
6015
6016 if (freq_len > QDF_MAX_NUM_CHAN) {
6017 hdd_err("insufficient space to hold channels");
6018 return -ENOMEM;
6019 }
6020
6021 hdd_debug("freq_len=%d", freq_len);
6022
6023 freq = nla_data(
6024 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
6025
6026
6027 for (i = 0; i < freq_len; i++) {
6028 if (freq[i] == 0)
6029 chans[i] = 0;
6030 else
6031 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6032
6033 hdd_debug("freq[%d]=%d", i, freq[i]);
6034 }
6035
6036 /*
6037 * The input frequency list from user space is designed to be a
6038 * priority based frequency list. This is only to accommodate any
6039 * future request. But, current requirement is only to perform CAC
6040 * on a single channel. So, the first entry from the list is picked.
6041 *
6042 * If channel is zero, any channel in the available outdoor regulatory
6043 * domain will be selected.
6044 */
6045 ret = wlan_hdd_request_pre_cac(chans[0]);
6046 if (ret) {
6047 hdd_err("pre cac request failed with reason:%d", ret);
6048 return ret;
6049 }
6050
6051 return 0;
6052}
6053
6054/**
Peng Xu8fdaa492016-06-22 10:20:47 -07006055 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6056 * @wiphy: Pointer to wireless phy
6057 * @wdev: Pointer to wireless device
6058 * @data: Pointer to data
6059 * @data_len: Data length
6060 *
6061 * This function is to process the p2p listen offload start vendor
6062 * command. It parses the input parameters and invoke WMA API to
6063 * send the command to firmware.
6064 *
6065 * Return: 0 on success, negative errno on failure
6066 */
6067static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6068 struct wireless_dev *wdev,
6069 const void *data,
6070 int data_len)
6071{
6072 int ret;
6073 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6074 struct net_device *dev = wdev->netdev;
6075 hdd_adapter_t *adapter;
6076 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6077 struct sir_p2p_lo_start params;
6078 QDF_STATUS status;
6079
6080 ENTER_DEV(dev);
6081
6082 ret = wlan_hdd_validate_context(hdd_ctx);
6083 if (ret)
6084 return ret;
6085
6086 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6087 hdd_err("Command not allowed in FTM mode");
6088 return -EPERM;
6089 }
6090
6091 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6092 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6093 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6094 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6095 hdd_err("Invalid device mode %d", adapter->device_mode);
6096 return -EINVAL;
6097 }
6098
6099 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6100 data, data_len, NULL)) {
6101 hdd_err("Invalid ATTR");
6102 return -EINVAL;
6103 }
6104
6105 memset(&params, 0, sizeof(params));
6106
6107 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6108 params.ctl_flags = 1; /* set to default value */
6109 else
6110 params.ctl_flags = nla_get_u32(tb
6111 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6112
6113 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6114 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6115 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6116 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6117 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6118 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6119 hdd_err("Attribute parsing failed");
6120 return -EINVAL;
6121 }
6122
6123 params.vdev_id = adapter->sessionId;
6124 params.freq = nla_get_u32(tb
6125 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6126 if ((params.freq != 2412) && (params.freq != 2437) &&
6127 (params.freq != 2462)) {
6128 hdd_err("Invalid listening channel: %d", params.freq);
6129 return -EINVAL;
6130 }
6131
6132 params.period = nla_get_u32(tb
6133 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6134 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6135 hdd_err("Invalid period: %d", params.period);
6136 return -EINVAL;
6137 }
6138
6139 params.interval = nla_get_u32(tb
6140 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6141 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6142 hdd_err("Invalid interval: %d", params.interval);
6143 return -EINVAL;
6144 }
6145
6146 params.count = nla_get_u32(tb
6147 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
6148 if (!((params.count > 0) && (params.count < UINT_MAX))) {
6149 hdd_err("Invalid count: %d", params.count);
6150 return -EINVAL;
6151 }
6152
6153 params.device_types = nla_data(tb
6154 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6155 if (params.device_types == NULL) {
6156 hdd_err("Invalid device types");
6157 return -EINVAL;
6158 }
6159
6160 params.dev_types_len = nla_len(tb
6161 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6162 if (params.dev_types_len < 8) {
6163 hdd_err("Invalid device type length: %d", params.dev_types_len);
6164 return -EINVAL;
6165 }
6166
6167 params.probe_resp_tmplt = nla_data(tb
6168 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6169 if (params.probe_resp_tmplt == NULL) {
6170 hdd_err("Invalid probe response template");
6171 return -EINVAL;
6172 }
6173
6174 params.probe_resp_len = nla_len(tb
6175 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6176 if (params.probe_resp_len == 0) {
6177 hdd_err("Invalid probe resp template length: %d",
6178 params.probe_resp_len);
6179 return -EINVAL;
6180 }
6181
6182 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6183 params.freq, params.period, params.interval, params.count);
6184
6185 status = wma_p2p_lo_start(&params);
6186
6187 if (!QDF_IS_STATUS_SUCCESS(status)) {
6188 hdd_err("P2P LO start failed");
6189 return -EINVAL;
6190 }
6191
6192 return 0;
6193}
6194
6195
6196/**
6197 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6198 * @wiphy: Pointer to wireless phy
6199 * @wdev: Pointer to wireless device
6200 * @data: Pointer to data
6201 * @data_len: Data length
6202 *
6203 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6204 * to process p2p listen offload start vendor command.
6205 *
6206 * Return: 0 on success, negative errno on failure
6207 */
6208static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6209 struct wireless_dev *wdev,
6210 const void *data,
6211 int data_len)
6212{
6213 int ret = 0;
6214
6215 cds_ssr_protect(__func__);
6216 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6217 data, data_len);
6218 cds_ssr_unprotect(__func__);
6219
6220 return ret;
6221}
6222
6223/**
6224 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6225 * @wiphy: Pointer to wireless phy
6226 * @wdev: Pointer to wireless device
6227 * @data: Pointer to data
6228 * @data_len: Data length
6229 *
6230 * This function is to process the p2p listen offload stop vendor
6231 * command. It invokes WMA API to send command to firmware.
6232 *
6233 * Return: 0 on success, negative errno on failure
6234 */
6235static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6236 struct wireless_dev *wdev,
6237 const void *data,
6238 int data_len)
6239{
6240 QDF_STATUS status;
6241 hdd_adapter_t *adapter;
6242 struct net_device *dev = wdev->netdev;
6243
6244 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6245 hdd_err("Command not allowed in FTM mode");
6246 return -EPERM;
6247 }
6248
6249 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6250 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6251 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6252 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6253 hdd_err("Invalid device mode");
6254 return -EINVAL;
6255 }
6256
6257 status = wma_p2p_lo_stop(adapter->sessionId);
6258
6259 if (!QDF_IS_STATUS_SUCCESS(status)) {
6260 hdd_err("P2P LO stop failed");
6261 return -EINVAL;
6262 }
6263
6264 return 0;
6265}
6266
6267/**
6268 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6269 * @wiphy: Pointer to wireless phy
6270 * @wdev: Pointer to wireless device
6271 * @data: Pointer to data
6272 * @data_len: Data length
6273 *
6274 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6275 * to process p2p listen offload stop vendor command.
6276 *
6277 * Return: 0 on success, negative errno on failure
6278 */
6279static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6280 struct wireless_dev *wdev,
6281 const void *data,
6282 int data_len)
6283{
6284 int ret = 0;
6285
6286 cds_ssr_protect(__func__);
6287 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6288 data, data_len);
6289 cds_ssr_unprotect(__func__);
6290
6291 return ret;
6292}
6293
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306294/**
6295 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6296 * @wiphy: Pointer to wireless phy
6297 * @wdev: Pointer to wireless device
6298 * @data: Pointer to data
6299 * @data_len: Data length
6300 *
6301 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6302 * to process the conditional channel switch request.
6303 *
6304 * Return: 0 on success, negative errno on failure
6305 */
6306static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6307 struct wireless_dev *wdev,
6308 const void *data,
6309 int data_len)
6310{
6311 int ret;
6312
6313 cds_ssr_protect(__func__);
6314 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6315 data, data_len);
6316 cds_ssr_unprotect(__func__);
6317
6318 return ret;
6319}
6320
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306321/*
6322 * define short names for the global vendor params
6323 * used by __wlan_hdd_cfg80211_bpf_offload()
6324 */
6325#define BPF_INVALID \
6326 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6327#define BPF_SET_RESET \
6328 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6329#define BPF_VERSION \
6330 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6331#define BPF_FILTER_ID \
6332 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6333#define BPF_PACKET_SIZE \
6334 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6335#define BPF_CURRENT_OFFSET \
6336 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6337#define BPF_PROGRAM \
6338 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6339#define BPF_MAX \
6340 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006341
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306342static const struct nla_policy
6343wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6344 [BPF_SET_RESET] = {.type = NLA_U32},
6345 [BPF_VERSION] = {.type = NLA_U32},
6346 [BPF_FILTER_ID] = {.type = NLA_U32},
6347 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6348 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6349 [BPF_PROGRAM] = {.type = NLA_U8},
6350};
6351
6352/**
6353 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
6354 * @hdd_context: hdd_context
6355 * @bpf_get_offload: struct for get offload
6356 *
6357 * This function receives the response/data from the lower layer and
6358 * checks to see if the thread is still waiting then post the results to
6359 * upper layer, if the request has timed out then ignore.
6360 *
6361 * Return: None
6362 */
6363void hdd_get_bpf_offload_cb(void *hdd_context,
6364 struct sir_bpf_get_offload *data)
6365{
6366 hdd_context_t *hdd_ctx = hdd_context;
6367 struct hdd_bpf_context *context;
6368
6369 ENTER();
6370
6371 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006372 hdd_err("HDD context is invalid or data(%p) is null",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306373 data);
6374 return;
6375 }
6376
6377 spin_lock(&hdd_context_lock);
6378
6379 context = &bpf_context;
6380 /* The caller presumably timed out so there is nothing we can do */
6381 if (context->magic != BPF_CONTEXT_MAGIC) {
6382 spin_unlock(&hdd_context_lock);
6383 return;
6384 }
6385
6386 /* context is valid so caller is still waiting */
6387 /* paranoia: invalidate the magic */
6388 context->magic = 0;
6389
6390 context->capability_response = *data;
6391 complete(&context->completion);
6392
6393 spin_unlock(&hdd_context_lock);
6394
6395 return;
6396}
6397
6398/**
6399 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6400 * @hdd_context: hdd_context
6401 * @bpf_get_offload: struct for get offload
6402 *
6403 * Return: 0 on success, error number otherwise.
6404 */
6405static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6406 struct sir_bpf_get_offload *bpf_get_offload)
6407{
6408 struct sk_buff *skb;
6409 uint32_t nl_buf_len;
6410
6411 ENTER();
6412
6413 nl_buf_len = NLMSG_HDRLEN;
6414 nl_buf_len +=
6415 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6416 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6417
6418 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6419 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006420 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306421 return -ENOMEM;
6422 }
6423
Jeff Johnson77848112016-06-29 14:52:06 -07006424 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306425 bpf_get_offload->bpf_version,
6426 bpf_get_offload->max_bytes_for_bpf_inst);
6427
6428 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6429 bpf_get_offload->max_bytes_for_bpf_inst) ||
6430 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006431 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306432 goto nla_put_failure;
6433 }
6434
6435 cfg80211_vendor_cmd_reply(skb);
6436 EXIT();
6437 return 0;
6438
6439nla_put_failure:
6440 kfree_skb(skb);
6441 return -EINVAL;
6442}
6443
6444/**
6445 * hdd_get_bpf_offload - Get BPF offload Capabilities
6446 * @hdd_ctx: Hdd context
6447 *
6448 * Return: 0 on success, errno on failure
6449 */
6450static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6451{
6452 unsigned long rc;
Houston Hoffman59c097f2016-11-09 15:50:25 -08006453 static struct hdd_bpf_context *context;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306454 QDF_STATUS status;
6455 int ret;
6456
6457 ENTER();
6458
6459 spin_lock(&hdd_context_lock);
6460 context = &bpf_context;
6461 context->magic = BPF_CONTEXT_MAGIC;
6462 INIT_COMPLETION(context->completion);
6463 spin_unlock(&hdd_context_lock);
6464
6465 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal);
6466 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006467 hdd_err("Unable to retrieve BPF caps");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306468 return -EINVAL;
6469 }
6470 /* request was sent -- wait for the response */
6471 rc = wait_for_completion_timeout(&context->completion,
6472 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
6473 if (!rc) {
Jeff Johnson77848112016-06-29 14:52:06 -07006474 hdd_err("Target response timed out");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306475 spin_lock(&hdd_context_lock);
6476 context->magic = 0;
6477 spin_unlock(&hdd_context_lock);
6478
6479 return -ETIMEDOUT;
6480 }
6481 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
6482 &bpf_context.capability_response);
6483 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006484 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306485
6486 EXIT();
6487 return ret;
6488}
6489
6490/**
6491 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
6492 * @hdd_ctx: Hdd context
6493 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306494 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306495 *
6496 * Return: 0 on success; errno on failure
6497 */
6498static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
6499 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306500 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306501{
6502 struct sir_bpf_set_offload *bpf_set_offload;
6503 QDF_STATUS status;
6504 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05306505 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306506
6507 ENTER();
6508
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306509 if (adapter->device_mode == QDF_STA_MODE ||
6510 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
6511 if (!hdd_conn_is_connected(
6512 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
6513 hdd_err("Not in Connected state!");
6514 return -ENOTSUPP;
6515 }
6516 }
6517
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306518 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
6519 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07006520 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306521 return -ENOMEM;
6522 }
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306523
6524 /* Parse and fetch bpf packet size */
6525 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006526 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306527 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306528 goto fail;
6529 }
6530 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
6531
6532 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07006533 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306534 goto post_sme;
6535 }
6536
6537 /* Parse and fetch bpf program */
6538 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006539 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306540 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306541 goto fail;
6542 }
6543
6544 prog_len = nla_len(tb[BPF_PROGRAM]);
6545 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05306546
6547 if (bpf_set_offload->program == NULL) {
6548 hdd_err("qdf_mem_malloc failed for bpf offload program");
6549 ret = -ENOMEM;
6550 goto fail;
6551 }
6552
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306553 bpf_set_offload->current_length = prog_len;
6554 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306555 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306556
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05306557 hdd_info("BPF set instructions");
6558 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
6559 bpf_set_offload->program, prog_len);
6560
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306561 /* Parse and fetch filter Id */
6562 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006563 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306564 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306565 goto fail;
6566 }
6567 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
6568
6569 /* Parse and fetch current offset */
6570 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006571 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306572 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306573 goto fail;
6574 }
6575 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
6576
6577post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07006578 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 +05306579 bpf_set_offload->session_id,
6580 bpf_set_offload->version,
6581 bpf_set_offload->filter_id,
6582 bpf_set_offload->total_length,
6583 bpf_set_offload->current_length,
6584 bpf_set_offload->current_offset);
6585
6586 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
6587 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006588 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05306589 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306590 goto fail;
6591 }
6592 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306593
6594fail:
6595 if (bpf_set_offload->current_length)
6596 qdf_mem_free(bpf_set_offload->program);
6597 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05306598 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306599}
6600
6601/**
6602 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
6603 * @wiphy: wiphy structure pointer
6604 * @wdev: Wireless device structure pointer
6605 * @data: Pointer to the data received
6606 * @data_len: Length of @data
6607 *
6608 * Return: 0 on success; errno on failure
6609 */
6610static int
6611__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6612 struct wireless_dev *wdev,
6613 const void *data, int data_len)
6614{
6615 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6616 struct net_device *dev = wdev->netdev;
6617 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6618 struct nlattr *tb[BPF_MAX + 1];
6619 int ret_val, packet_filter_subcmd;
6620
6621 ENTER();
6622
6623 ret_val = wlan_hdd_validate_context(hdd_ctx);
6624 if (ret_val)
6625 return ret_val;
6626
6627 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07006628 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306629 return -EINVAL;
6630 }
6631
6632 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07006633 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306634 return -ENOTSUPP;
6635 }
6636
6637 if (nla_parse(tb, BPF_MAX, data, data_len,
6638 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006639 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306640 return -EINVAL;
6641 }
6642
6643 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006644 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306645 return -EINVAL;
6646 }
6647
6648 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
6649
6650 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
6651 return hdd_get_bpf_offload(hdd_ctx);
6652 else
6653 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306654 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306655}
6656
6657/**
6658 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
6659 * @wiphy: wiphy structure pointer
6660 * @wdev: Wireless device structure pointer
6661 * @data: Pointer to the data received
6662 * @data_len: Length of @data
6663 *
6664 * Return: 0 on success; errno on failure
6665 */
6666
6667static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6668 struct wireless_dev *wdev,
6669 const void *data, int data_len)
6670{
6671 int ret;
6672
6673 cds_ssr_protect(__func__);
6674 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
6675 cds_ssr_unprotect(__func__);
6676
6677 return ret;
6678}
6679
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306680/**
6681 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
6682 * @pre_cac_adapter: AP adapter used for pre cac
6683 * @status: Status (true or false)
6684 * @handle: Global handle
6685 *
6686 * Sets the status of pre cac i.e., whether the pre cac is active or not
6687 *
6688 * Return: Zero on success, non-zero on failure
6689 */
6690static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
6691 bool status, tHalHandle handle)
6692{
6693 QDF_STATUS ret;
6694
6695 ret = wlan_sap_set_pre_cac_status(
6696 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
6697 if (QDF_IS_STATUS_ERROR(ret))
6698 return -EINVAL;
6699
6700 return 0;
6701}
6702
6703/**
6704 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
6705 * @ap_adapter: AP adapter
6706 * @chan_before_pre_cac: Channel
6707 *
6708 * Saves the channel which the AP was beaconing on before moving to the pre
6709 * cac channel. If radar is detected on the pre cac channel, this saved
6710 * channel will be used for AP operations.
6711 *
6712 * Return: Zero on success, non-zero on failure
6713 */
6714static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
6715 uint8_t chan_before_pre_cac)
6716{
6717 QDF_STATUS ret;
6718
6719 ret = wlan_sap_set_chan_before_pre_cac(
6720 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
6721 if (QDF_IS_STATUS_ERROR(ret))
6722 return -EINVAL;
6723
6724 return 0;
6725}
6726
6727/**
6728 * wlan_hdd_sap_get_nol() - Get SAPs NOL
6729 * @ap_adapter: AP adapter
6730 * @nol: Non-occupancy list
6731 * @nol_len: Length of NOL
6732 *
6733 * Get the NOL for SAP
6734 *
6735 * Return: Zero on success, non-zero on failure
6736 */
6737static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
6738 uint32_t *nol_len)
6739{
6740 QDF_STATUS ret;
6741
6742 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
6743 nol, nol_len);
6744 if (QDF_IS_STATUS_ERROR(ret))
6745 return -EINVAL;
6746
6747 return 0;
6748}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306749
6750/**
6751 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
6752 * @hdd_ctx: HDD context
6753 * @ap_adapter: AP adapter
6754 * @channel: Channel requested by userspace
6755 * @pre_cac_chan: Pointer to the pre CAC channel
6756 *
6757 * Validates the channel provided by userspace. If user provided channel 0,
6758 * a valid outdoor channel must be selected from the regulatory channel.
6759 *
6760 * Return: Zero on success and non zero value on error
6761 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07006762static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
6763 hdd_adapter_t *ap_adapter,
6764 uint8_t channel,
6765 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306766{
6767 uint32_t i, j;
6768 QDF_STATUS status;
6769 int ret;
6770 uint8_t nol[QDF_MAX_NUM_CHAN];
6771 uint32_t nol_len = 0, weight_len = 0;
6772 bool found;
6773 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6774 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
6775 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
6776
6777 if (0 == channel) {
6778 /* Channel is not obtained from PCL because PCL may not have
6779 * the entire channel list. For example: if SAP is up on
6780 * channel 6 and PCL is queried for the next SAP interface,
6781 * if SCC is preferred, the PCL will contain only the channel
6782 * 6. But, we are in need of a DFS channel. So, going with the
6783 * first channel from the valid channel list.
6784 */
6785 status = cds_get_valid_chans(channel_list, &len);
6786 if (QDF_IS_STATUS_ERROR(status)) {
6787 hdd_err("Failed to get channel list");
6788 return -EINVAL;
6789 }
6790 cds_update_with_safe_channel_list(channel_list, &len,
6791 pcl_weights, weight_len);
6792 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
6793 for (i = 0; i < len; i++) {
6794 found = false;
6795 for (j = 0; j < nol_len; j++) {
6796 if (channel_list[i] == nol[j]) {
6797 found = true;
6798 break;
6799 }
6800 }
6801 if (found)
6802 continue;
6803 if (CDS_IS_DFS_CH(channel_list[i])) {
6804 *pre_cac_chan = channel_list[i];
6805 break;
6806 }
6807 }
6808 if (*pre_cac_chan == 0) {
6809 hdd_err("unable to find outdoor channel");
6810 return -EINVAL;
6811 }
6812 } else {
6813 /* Only when driver selects a channel, check is done for
6814 * unnsafe and NOL channels. When user provides a fixed channel
6815 * the user is expected to take care of this.
6816 */
6817 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
6818 !CDS_IS_DFS_CH(channel)) {
6819 hdd_err("Invalid channel for pre cac:%d", channel);
6820 return -EINVAL;
6821 } else {
6822 *pre_cac_chan = channel;
6823 }
6824 }
6825 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
6826 return 0;
6827}
6828
6829/**
6830 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
6831 * @channel: Channel option provided by userspace
6832 *
6833 * Sets the driver to the required hardware mode and start an adapater for
6834 * pre CAC which will mimic an AP.
6835 *
6836 * Return: Zero on success, non-zero value on error
6837 */
6838int wlan_hdd_request_pre_cac(uint8_t channel)
6839{
Krunal Sonib37bb352016-12-20 14:12:21 -08006840 uint8_t pre_cac_chan = 0, *mac_addr;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306841 hdd_context_t *hdd_ctx;
6842 int ret;
6843 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
6844 hdd_ap_ctx_t *hdd_ap_ctx;
6845 QDF_STATUS status;
6846 struct wiphy *wiphy;
6847 struct net_device *dev;
6848 struct cfg80211_chan_def chandef;
6849 enum nl80211_channel_type channel_type;
6850 uint32_t freq;
6851 struct ieee80211_channel *chan;
6852 tHalHandle handle;
6853 bool val;
6854
6855 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
6856 if (0 != wlan_hdd_validate_context(hdd_ctx))
6857 return -EINVAL;
6858
6859 if (cds_get_connection_count() > 1) {
6860 hdd_err("pre cac not allowed in concurrency");
6861 return -EINVAL;
6862 }
6863
6864 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
6865 if (!ap_adapter) {
6866 hdd_err("unable to get SAP adapter");
6867 return -EINVAL;
6868 }
6869
6870 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
6871 if (!handle) {
6872 hdd_err("Invalid handle");
6873 return -EINVAL;
6874 }
6875
6876 val = wlan_sap_is_pre_cac_active(handle);
6877 if (val) {
6878 hdd_err("pre cac is already in progress");
6879 return -EINVAL;
6880 }
6881
6882 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6883 if (!hdd_ap_ctx) {
6884 hdd_err("SAP context is NULL");
6885 return -EINVAL;
6886 }
6887
6888 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
6889 hdd_err("SAP is already on DFS channel:%d",
6890 hdd_ap_ctx->operatingChannel);
6891 return -EINVAL;
6892 }
6893
6894 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
6895 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
6896 hdd_ap_ctx->operatingChannel);
6897 return -EINVAL;
6898 }
6899
Krunal Sonib37bb352016-12-20 14:12:21 -08006900 mac_addr = wlan_hdd_get_intf_addr(hdd_ctx);
6901 if (!mac_addr) {
6902 hdd_err("can't add virtual intf: Not getting valid mac addr");
6903 return -EINVAL;
6904 }
6905
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306906 hdd_info("channel:%d", channel);
6907
6908 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
6909 &pre_cac_chan);
Krunal Sonib37bb352016-12-20 14:12:21 -08006910 if (ret != 0) {
6911 hdd_err("can't validate pre-cac channel");
6912 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306913 }
6914
6915 hdd_debug("starting pre cac SAP adapter");
6916
6917 /* Starting a SAP adapter:
6918 * Instead of opening an adapter, we could just do a SME open session
6919 * for AP type. But, start BSS would still need an adapter.
6920 * So, this option is not taken.
6921 *
6922 * hdd open adapter is going to register this precac interface with
6923 * user space. This interface though exposed to user space will be in
6924 * DOWN state. Consideration was done to avoid this registration to the
6925 * user space. But, as part of SAP operations multiple events are sent
6926 * to user space. Some of these events received from unregistered
6927 * interface was causing crashes. So, retaining the registration.
6928 *
6929 * So, this interface would remain registered and will remain in DOWN
6930 * state for the CAC duration. We will add notes in the feature
6931 * announcement to not use this temporary interface for any activity
6932 * from user space.
6933 */
6934 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
Krunal Sonib37bb352016-12-20 14:12:21 -08006935 mac_addr, NET_NAME_UNKNOWN, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306936 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306937 hdd_err("error opening the pre cac adapter");
Krunal Sonib37bb352016-12-20 14:12:21 -08006938 goto release_intf_addr_and_return_failure;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306939 }
6940
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306941 /*
6942 * This interface is internally created by the driver. So, no interface
6943 * up comes for this interface from user space and hence starting
6944 * the adapter internally.
6945 */
6946 if (hdd_start_adapter(pre_cac_adapter)) {
6947 hdd_err("error starting the pre cac adapter");
6948 goto close_pre_cac_adapter;
6949 }
6950
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306951 hdd_debug("preparing for start ap/bss on the pre cac adapter");
6952
6953 wiphy = hdd_ctx->wiphy;
6954 dev = pre_cac_adapter->dev;
6955
6956 /* Since this is only a dummy interface lets us use the IEs from the
6957 * other active SAP interface. In regular scenarios, these IEs would
6958 * come from the user space entity
6959 */
6960 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
6961 sizeof(*ap_adapter->sessionCtx.ap.beacon));
6962 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
6963 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306964 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306965 }
6966 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
6967 ap_adapter->sessionCtx.ap.beacon,
6968 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
6969 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
6970 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
6971 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
6972 ap_adapter->sessionCtx.ap.sapConfig.authType;
6973
6974 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
6975 * to operate on the same bandwidth as that of the 2.4GHz operations.
6976 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
6977 */
6978 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
6979 case CH_WIDTH_20MHZ:
6980 channel_type = NL80211_CHAN_HT20;
6981 break;
6982 case CH_WIDTH_40MHZ:
6983 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
6984 ap_adapter->sessionCtx.ap.sapConfig.channel)
6985 channel_type = NL80211_CHAN_HT40PLUS;
6986 else
6987 channel_type = NL80211_CHAN_HT40MINUS;
6988 break;
6989 default:
6990 channel_type = NL80211_CHAN_NO_HT;
6991 break;
6992 }
6993
6994 freq = cds_chan_to_freq(pre_cac_chan);
6995 chan = __ieee80211_get_channel(wiphy, freq);
6996 if (!chan) {
6997 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306998 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306999 }
7000
7001 cfg80211_chandef_create(&chandef, chan, channel_type);
7002
7003 hdd_debug("orig width:%d channel_type:%d freq:%d",
7004 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
7005 channel_type, freq);
Krunal Sonib37bb352016-12-20 14:12:21 -08007006 /*
7007 * Doing update after opening and starting pre-cac adapter will make
7008 * sure that driver won't do hardware mode change if there are any
7009 * initial hick-ups or issues in pre-cac adapter's configuration.
7010 * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
7011 * connection update should result in DBS mode
7012 */
7013 status = cds_update_and_wait_for_connection_update(
7014 ap_adapter->sessionId,
7015 pre_cac_chan,
7016 SIR_UPDATE_REASON_PRE_CAC);
7017 if (QDF_IS_STATUS_ERROR(status)) {
7018 hdd_err("error in moving to DBS mode");
7019 goto stop_close_pre_cac_adapter;
7020 }
7021
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307022
7023 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
7024 if (0 != ret) {
7025 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307026 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307027 }
7028
7029 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
7030 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
Archana Ramachandran1a5b6042016-11-08 16:36:50 -08007031 eHIDDEN_SSID_NOT_IN_USE, false, false);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307032 if (QDF_IS_STATUS_ERROR(status)) {
7033 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307034 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307035 }
7036
7037 /*
7038 * The pre cac status is set here. But, it would not be reset explicitly
7039 * anywhere, since after the pre cac success/failure, the pre cac
7040 * adapter itself would be removed.
7041 */
7042 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
7043 if (0 != ret) {
7044 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307045 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307046 }
7047
7048 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
7049 hdd_ap_ctx->operatingChannel);
7050 if (0 != ret) {
7051 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307052 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307053 }
7054
7055 ap_adapter->pre_cac_chan = pre_cac_chan;
7056
7057 return 0;
7058
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307059stop_close_pre_cac_adapter:
7060 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307061 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
7062 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05307063close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307064 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
Krunal Sonib37bb352016-12-20 14:12:21 -08007065release_intf_addr_and_return_failure:
7066 /*
7067 * Release the interface address as the adapter
7068 * failed to start, if you don't release then next
7069 * adapter which is trying to come wouldn't get valid
7070 * mac address. Remember we have limited pool of mac addresses
7071 */
7072 wlan_hdd_release_intf_addr(hdd_ctx, mac_addr);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307073 return -EINVAL;
7074}
7075
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307076/**
7077 * hdd_init_bpf_completion() - Initialize the completion event for bpf
7078 *
7079 * Return: None
7080 */
7081void hdd_init_bpf_completion(void)
7082{
7083 init_completion(&bpf_context.completion);
7084}
7085
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307086static const struct nla_policy
7087wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7088 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7089};
7090
Agrawal Ashish65634612016-08-18 13:24:32 +05307091static const struct nla_policy
7092wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7093 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7094 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7095};
7096
7097/**
7098 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7099 * @wiphy: Pointer to wireless phy
7100 * @wdev: Pointer to wireless device
7101 * @data: Pointer to data
7102 * @data_len: Length of @data
7103 *
7104 * This function parses the incoming NL vendor command data attributes and
7105 * updates the SAP context about channel_hint and DFS mode.
7106 * If channel_hint is set, SAP will choose that channel
7107 * as operating channel.
7108 *
7109 * If DFS mode is enabled, driver will include DFS channels
7110 * in ACS else driver will skip DFS channels.
7111 *
7112 * Return: 0 on success, negative errno on failure
7113 */
7114static int
7115__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7116 struct wireless_dev *wdev,
7117 const void *data, int data_len)
7118{
7119 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7120 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7121 int ret;
7122 struct acs_dfs_policy *acs_policy;
7123 int mode = DFS_MODE_NONE;
7124 int channel_hint = 0;
7125
7126 ENTER_DEV(wdev->netdev);
7127
7128 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7129 hdd_err("Command not allowed in FTM mode");
7130 return -EINVAL;
7131 }
7132
7133 ret = wlan_hdd_validate_context(hdd_ctx);
7134 if (0 != ret)
7135 return ret;
7136
7137 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7138 data, data_len,
7139 wlan_hdd_set_acs_dfs_config_policy)) {
7140 hdd_err("invalid attr");
7141 return -EINVAL;
7142 }
7143
7144 acs_policy = &hdd_ctx->acs_policy;
7145 /*
7146 * SCM sends this attribute to restrict SAP from choosing
7147 * DFS channels from ACS.
7148 */
7149 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7150 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7151
7152 if (!IS_DFS_MODE_VALID(mode)) {
7153 hdd_err("attr acs dfs mode is not valid");
7154 return -EINVAL;
7155 }
7156 acs_policy->acs_dfs_mode = mode;
7157
7158 /*
7159 * SCM sends this attribute to provide an active channel,
7160 * to skip redundant ACS between drivers, and save driver start up time
7161 */
7162 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7163 channel_hint = nla_get_u8(
7164 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7165
7166 if (!IS_CHANNEL_VALID(channel_hint)) {
7167 hdd_err("acs channel is not valid");
7168 return -EINVAL;
7169 }
7170 acs_policy->acs_channel = channel_hint;
7171
7172 return 0;
7173}
7174
7175/**
7176 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7177 * @wiphy: wiphy structure pointer
7178 * @wdev: Wireless device structure pointer
7179 * @data: Pointer to the data received
7180 * @data_len: Length of @data
7181 *
7182 * This function parses the incoming NL vendor command data attributes and
7183 * updates the SAP context about channel_hint and DFS mode.
7184 *
7185 * Return: 0 on success; errno on failure
7186 */
7187static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7188 struct wireless_dev *wdev,
7189 const void *data, int data_len)
7190{
7191 int ret;
7192
7193 cds_ssr_protect(__func__);
7194 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7195 cds_ssr_unprotect(__func__);
7196
7197 return ret;
7198}
7199
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307200/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307201 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7202 * @mode : cfg80211 dfs mode
7203 *
7204 * Return: return csr sta roam dfs mode else return NONE
7205 */
7206static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7207 enum dfs_mode mode)
7208{
7209 switch (mode) {
7210 case DFS_MODE_ENABLE:
7211 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7212 break;
7213 case DFS_MODE_DISABLE:
7214 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7215 break;
7216 case DFS_MODE_DEPRIORITIZE:
7217 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7218 break;
7219 default:
7220 hdd_err("STA Roam policy dfs mode is NONE");
7221 return CSR_STA_ROAM_POLICY_NONE;
7222 }
7223}
7224
7225static const struct nla_policy
7226wlan_hdd_set_sta_roam_config_policy[
7227QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7228 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7229 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7230};
7231
7232/**
7233 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7234 * for station connection or roaming.
7235 * @wiphy: Pointer to wireless phy
7236 * @wdev: Pointer to wireless device
7237 * @data: Pointer to data
7238 * @data_len: Length of @data
7239 *
7240 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7241 * channels needs to be skipped in scanning or not.
7242 * If dfs_mode is disabled, driver will not scan DFS channels.
7243 * If skip_unsafe_channels is set, driver will skip unsafe channels
7244 * in Scanning.
7245 *
7246 * Return: 0 on success, negative errno on failure
7247 */
7248static int
7249__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7250 struct wireless_dev *wdev,
7251 const void *data, int data_len)
7252{
7253 struct net_device *dev = wdev->netdev;
7254 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7255 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7256 struct nlattr *tb[
7257 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7258 int ret;
7259 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7260 enum dfs_mode mode = DFS_MODE_NONE;
7261 bool skip_unsafe_channels = false;
7262 QDF_STATUS status;
7263
7264 ENTER_DEV(dev);
7265
7266 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7267 hdd_err("Command not allowed in FTM mode");
7268 return -EINVAL;
7269 }
7270
7271 ret = wlan_hdd_validate_context(hdd_ctx);
7272 if (0 != ret)
7273 return ret;
7274 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7275 data, data_len,
7276 wlan_hdd_set_sta_roam_config_policy)) {
7277 hdd_err("invalid attr");
7278 return -EINVAL;
7279 }
7280 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7281 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7282 if (!IS_DFS_MODE_VALID(mode)) {
7283 hdd_err("attr sta roam dfs mode policy is not valid");
7284 return -EINVAL;
7285 }
7286
7287 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7288
7289 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7290 skip_unsafe_channels = nla_get_u8(
7291 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
7292
7293 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
7294 skip_unsafe_channels, adapter->sessionId);
7295
7296 if (!QDF_IS_STATUS_SUCCESS(status)) {
7297 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7298 return -EINVAL;
7299 }
7300 return 0;
7301}
7302
7303/**
7304 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7305 * connection and roaming for station.
7306 * @wiphy: wiphy structure pointer
7307 * @wdev: Wireless device structure pointer
7308 * @data: Pointer to the data received
7309 * @data_len: Length of @data
7310 *
7311 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7312 * channels needs to be skipped in scanning or not.
7313 * If dfs_mode is disabled, driver will not scan DFS channels.
7314 * If skip_unsafe_channels is set, driver will skip unsafe channels
7315 * in Scanning.
7316 * Return: 0 on success; errno on failure
7317 */
7318static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7319 struct wireless_dev *wdev,
7320 const void *data, int data_len)
7321{
7322 int ret;
7323
7324 cds_ssr_protect(__func__);
7325 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7326 cds_ssr_unprotect(__func__);
7327
7328 return ret;
7329}
7330
Agrawal Ashish467dde42016-09-08 18:44:22 +05307331#ifdef FEATURE_WLAN_CH_AVOID
7332/**
7333 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7334 * is on unsafe channel.
7335 * @wiphy: wiphy structure pointer
7336 * @wdev: Wireless device structure pointer
7337 * @data: Pointer to the data received
7338 * @data_len: Length of @data
7339 *
7340 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7341 * on any of unsafe channels.
7342 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7343 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7344 *
7345 * Return: 0 on success; errno on failure
7346 */
7347static int
7348__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7349 struct wireless_dev *wdev,
7350 const void *data, int data_len)
7351{
7352 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7353 int ret;
7354 uint16_t unsafe_channel_count;
7355 int unsafe_channel_index;
7356 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7357
7358 ENTER_DEV(wdev->netdev);
7359
7360 if (!qdf_ctx) {
7361 cds_err("qdf_ctx is NULL");
7362 return -EINVAL;
7363 }
7364
7365 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7366 hdd_err("Command not allowed in FTM mode");
7367 return -EINVAL;
7368 }
7369
7370 ret = wlan_hdd_validate_context(hdd_ctx);
7371 if (0 != ret)
7372 return ret;
7373 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7374 &(hdd_ctx->unsafe_channel_count),
7375 sizeof(hdd_ctx->unsafe_channel_list));
7376
7377 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7378 (uint16_t)NUM_CHANNELS);
7379 for (unsafe_channel_index = 0;
7380 unsafe_channel_index < unsafe_channel_count;
7381 unsafe_channel_index++) {
7382 hdd_info("Channel %d is not safe",
7383 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7384 }
7385 hdd_unsafe_channel_restart_sap(hdd_ctx);
7386 return 0;
7387}
7388
7389/**
7390 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7391 * is on unsafe channel.
7392 * @wiphy: wiphy structure pointer
7393 * @wdev: Wireless device structure pointer
7394 * @data: Pointer to the data received
7395 * @data_len: Length of @data
7396 *
7397 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7398 * on any of unsafe channels.
7399 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7400 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7401 *
7402 * Return: 0 on success; errno on failure
7403 */
7404static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7405 struct wireless_dev *wdev,
7406 const void *data, int data_len)
7407{
7408 int ret;
7409
7410 cds_ssr_protect(__func__);
7411 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
7412 cds_ssr_unprotect(__func__);
7413
7414 return ret;
7415}
7416
7417#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307418/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307419 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
7420 * SAP is on unsafe channel.
7421 * @wiphy: wiphy structure pointer
7422 * @wdev: Wireless device structure pointer
7423 * @data: Pointer to the data received
7424 * @data_len: Length of @data
7425 *
7426 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7427 * driver.
7428 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7429 * will initiate restart of sap.
7430 *
7431 * Return: 0 on success; errno on failure
7432 */
7433static int
7434__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7435 struct wireless_dev *wdev,
7436 const void *data, int data_len)
7437{
7438 struct net_device *ndev = wdev->netdev;
7439 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7440 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7441 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
7442 uint8_t config_channel = 0;
7443 hdd_ap_ctx_t *ap_ctx;
7444 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307445 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307446
7447 ENTER();
7448
7449 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007450 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307451 return -EINVAL;
7452 }
7453
7454 ret = wlan_hdd_validate_context(hdd_ctx);
7455 if (0 != ret)
7456 return -EINVAL;
7457
7458 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
7459 data, data_len,
7460 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007461 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307462 return -EINVAL;
7463 }
7464
7465 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
7466 if (!test_bit(SOFTAP_BSS_STARTED,
7467 &hostapd_adapter->event_flags)) {
7468 hdd_err("SAP is not started yet. Restart sap will be invalid");
7469 return -EINVAL;
7470 }
7471
7472 config_channel =
7473 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
7474
7475 if (!((IS_24G_CH(config_channel)) ||
7476 (IS_5G_CH(config_channel)))) {
7477 hdd_err("Channel %d is not valid to restart SAP",
7478 config_channel);
7479 return -ENOTSUPP;
7480 }
7481
7482 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
7483 ap_ctx->sapConfig.channel = config_channel;
7484 ap_ctx->sapConfig.ch_params.ch_width =
7485 ap_ctx->sapConfig.ch_width_orig;
7486
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07007487 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307488 ap_ctx->sapConfig.sec_ch,
7489 &ap_ctx->sapConfig.ch_params);
7490
7491 cds_restart_sap(hostapd_adapter);
7492 }
7493
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307494 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
7495 uint32_t freq_len, i;
7496 uint32_t *freq;
7497 uint8_t chans[QDF_MAX_NUM_CHAN];
7498
7499 hdd_debug("setting mandatory freq/chan list");
7500
7501 freq_len = nla_len(
7502 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
7503 sizeof(uint32_t);
7504
7505 if (freq_len > QDF_MAX_NUM_CHAN) {
7506 hdd_err("insufficient space to hold channels");
7507 return -ENOMEM;
7508 }
7509
7510 freq = nla_data(
7511 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
7512
7513 hdd_debug("freq_len=%d", freq_len);
7514
7515 for (i = 0; i < freq_len; i++) {
7516 chans[i] = ieee80211_frequency_to_channel(freq[i]);
7517 hdd_debug("freq[%d]=%d", i, freq[i]);
7518 }
7519
7520 status = cds_set_sap_mandatory_channels(chans, freq_len);
7521 if (QDF_IS_STATUS_ERROR(status))
7522 return -EINVAL;
7523 }
7524
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307525 return 0;
7526}
7527
7528/**
7529 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
7530 * @wiphy: wiphy structure pointer
7531 * @wdev: Wireless device structure pointer
7532 * @data: Pointer to the data received
7533 * @data_len: Length of @data
7534 *
7535 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7536 * driver.
7537 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7538 * will initiate restart of sap.
7539 *
7540 * Return: 0 on success; errno on failure
7541 */
7542static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7543 struct wireless_dev *wdev,
7544 const void *data, int data_len)
7545{
7546 int ret;
7547
7548 cds_ssr_protect(__func__);
7549 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
7550 wdev, data, data_len);
7551 cds_ssr_unprotect(__func__);
7552
7553 return ret;
7554}
7555
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307556#undef BPF_INVALID
7557#undef BPF_SET_RESET
7558#undef BPF_VERSION
7559#undef BPF_ID
7560#undef BPF_PACKET_SIZE
7561#undef BPF_CURRENT_OFFSET
7562#undef BPF_PROGRAM
7563#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307564
7565/**
7566 * define short names for the global vendor params
7567 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
7568 */
7569#define PARAM_TOTAL_CMD_EVENT_WAKE \
7570 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
7571#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
7572 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
7573#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
7574 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
7575#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
7576 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
7577#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
7578 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
7579#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
7580 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
7581#define PARAM_TOTAL_RX_DATA_WAKE \
7582 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
7583#define PARAM_RX_UNICAST_CNT \
7584 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
7585#define PARAM_RX_MULTICAST_CNT \
7586 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
7587#define PARAM_RX_BROADCAST_CNT \
7588 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
7589#define PARAM_ICMP_PKT \
7590 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
7591#define PARAM_ICMP6_PKT \
7592 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
7593#define PARAM_ICMP6_RA \
7594 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
7595#define PARAM_ICMP6_NA \
7596 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
7597#define PARAM_ICMP6_NS \
7598 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
7599#define PARAM_ICMP4_RX_MULTICAST_CNT \
7600 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
7601#define PARAM_ICMP6_RX_MULTICAST_CNT \
7602 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
7603#define PARAM_OTHER_RX_MULTICAST_CNT \
7604 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05307605#define PARAM_RSSI_BREACH_CNT \
7606 QCA_WLAN_VENDOR_ATTR_RSSI_BREACH_CNT
7607#define PARAM_LOW_RSSI_CNT \
7608 QCA_WLAN_VENDOR_ATTR_LOW_RSSI_CNT
7609#define PARAM_GSCAN_CNT \
7610 QCA_WLAN_VENDOR_ATTR_GSCAN_CNT
7611#define PARAM_PNO_COMPLETE_CNT \
7612 QCA_WLAN_VENDOR_ATTR_PNO_COMPLETE_CNT
7613#define PARAM_PNO_MATCH_CNT \
7614 QCA_WLAN_VENDOR_ATTR_PNO_MATCH_CNT
7615
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307616
7617
7618/**
7619 * hdd_send_wakelock_stats() - API to send wakelock stats
7620 * @ctx: context to be passed to callback
7621 * @data: data passed to callback
7622 *
7623 * This function is used to send wake lock stats to HAL layer
7624 *
7625 * Return: 0 on success, error number otherwise.
7626 */
7627static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
7628 const struct sir_wake_lock_stats *data)
7629{
7630 struct sk_buff *skb;
7631 uint32_t nl_buf_len;
7632 uint32_t total_rx_data_wake, rx_multicast_cnt;
7633 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307634 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307635
7636 ENTER();
7637
7638 nl_buf_len = NLMSG_HDRLEN;
7639 nl_buf_len +=
7640 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
7641 (NLMSG_HDRLEN + sizeof(uint32_t));
7642
7643 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7644
7645 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007646 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307647 return -ENOMEM;
7648 }
7649
Jeff Johnson64943bd2016-08-23 13:14:06 -07007650 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307651 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007652 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307653 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007654 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307655 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007656 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307657 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007658 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307659 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007660 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307661 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007662 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307663 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007664 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
7665 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307666 data->wow_icmpv6_count);
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05307667 hdd_info("wow_rssi_breach_wake_up_count %d",
7668 data->wow_rssi_breach_wake_up_count);
7669 hdd_info("wow_low_rssi_wake_up_count %d",
7670 data->wow_low_rssi_wake_up_count);
7671 hdd_info("wow_gscan_wake_up_count %d",
7672 data->wow_gscan_wake_up_count);
7673 hdd_info("wow_pno_complete_wake_up_count %d",
7674 data->wow_pno_complete_wake_up_count);
7675 hdd_info("wow_pno_match_wake_up_count %d",
7676 data->wow_pno_match_wake_up_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307677
7678 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307679 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307680
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307681 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307682 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307683
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307684 rx_multicast_cnt =
7685 data->wow_ipv4_mcast_wake_up_count +
7686 ipv6_rx_multicast_addr_cnt;
7687
7688 total_rx_data_wake =
7689 data->wow_ucast_wake_up_count +
7690 data->wow_bcast_wake_up_count +
7691 rx_multicast_cnt;
7692
7693 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
7694 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
7695 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
7696 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
7697 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
7698 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
7699 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
7700 total_rx_data_wake) ||
7701 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
7702 data->wow_ucast_wake_up_count) ||
7703 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
7704 rx_multicast_cnt) ||
7705 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
7706 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307707 nla_put_u32(skb, PARAM_ICMP_PKT,
7708 data->wow_icmpv4_count) ||
7709 nla_put_u32(skb, PARAM_ICMP6_PKT,
7710 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307711 nla_put_u32(skb, PARAM_ICMP6_RA,
7712 data->wow_ipv6_mcast_ra_stats) ||
7713 nla_put_u32(skb, PARAM_ICMP6_NA,
7714 data->wow_ipv6_mcast_na_stats) ||
7715 nla_put_u32(skb, PARAM_ICMP6_NS,
7716 data->wow_ipv6_mcast_ns_stats) ||
7717 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
7718 data->wow_ipv4_mcast_wake_up_count) ||
7719 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
7720 ipv6_rx_multicast_addr_cnt) ||
Poddar, Siddarthc01681a2016-12-21 18:36:30 +05307721 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0) ||
7722 nla_put_u32(skb, PARAM_RSSI_BREACH_CNT,
7723 data->wow_rssi_breach_wake_up_count) ||
7724 nla_put_u32(skb, PARAM_LOW_RSSI_CNT,
7725 data->wow_low_rssi_wake_up_count) ||
7726 nla_put_u32(skb, PARAM_GSCAN_CNT,
7727 data->wow_gscan_wake_up_count) ||
7728 nla_put_u32(skb, PARAM_PNO_COMPLETE_CNT,
7729 data->wow_pno_complete_wake_up_count) ||
7730 nla_put_u32(skb, PARAM_PNO_MATCH_CNT,
7731 data->wow_pno_match_wake_up_count)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007732 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307733 goto nla_put_failure;
7734 }
7735
7736 cfg80211_vendor_cmd_reply(skb);
7737
7738 EXIT();
7739 return 0;
7740
7741nla_put_failure:
7742 kfree_skb(skb);
7743 return -EINVAL;
7744}
7745
7746/**
7747 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7748 * @wiphy: wiphy pointer
7749 * @wdev: pointer to struct wireless_dev
7750 * @data: pointer to incoming NL vendor data
7751 * @data_len: length of @data
7752 *
7753 * This function parses the incoming NL vendor command data attributes and
7754 * invokes the SME Api and blocks on a completion variable.
7755 * WMA copies required data and invokes callback
7756 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7757 *
7758 * Return: 0 on success; error number otherwise.
7759 */
7760static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7761 struct wireless_dev *wdev,
7762 const void *data,
7763 int data_len)
7764{
7765 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7766 int status, ret;
7767 struct sir_wake_lock_stats wake_lock_stats;
7768 QDF_STATUS qdf_status;
7769
7770 ENTER();
7771
7772 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007773 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307774 return -EINVAL;
7775 }
7776
7777 status = wlan_hdd_validate_context(hdd_ctx);
7778 if (0 != status)
7779 return -EINVAL;
7780
7781 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
7782 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007783 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307784 return -EINVAL;
7785 }
7786
7787 ret = hdd_send_wakelock_stats(hdd_ctx,
7788 &wake_lock_stats);
7789 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07007790 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307791
7792 EXIT();
7793 return ret;
7794}
7795
7796/**
7797 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7798 * @wiphy: wiphy pointer
7799 * @wdev: pointer to struct wireless_dev
7800 * @data: pointer to incoming NL vendor data
7801 * @data_len: length of @data
7802 *
7803 * This function parses the incoming NL vendor command data attributes and
7804 * invokes the SME Api and blocks on a completion variable.
7805 * WMA copies required data and invokes callback
7806 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7807 *
7808 * Return: 0 on success; error number otherwise.
7809 */
7810static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7811 struct wireless_dev *wdev,
7812 const void *data, int data_len)
7813{
7814 int ret;
7815
7816 cds_ssr_protect(__func__);
7817 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
7818 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07007819 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307820
7821 return ret;
7822}
7823
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307824/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05307825 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
7826 * @wiphy: wiphy structure pointer
7827 * @wdev: Wireless device structure pointer
7828 * @data: Pointer to the data received
7829 * @data_len: Length of @data
7830 *
7831 * This function reads wmi max bus size and fill in the skb with
7832 * NL attributes and send up the NL event.
7833 * Return: 0 on success; errno on failure
7834 */
7835static int
7836__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7837 struct wireless_dev *wdev,
7838 const void *data, int data_len)
7839{
7840 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7841 int ret_val;
7842 struct sk_buff *skb;
7843 uint32_t nl_buf_len;
7844
7845 ENTER();
7846
7847 ret_val = wlan_hdd_validate_context(hdd_ctx);
7848 if (ret_val)
7849 return ret_val;
7850
7851 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7852 hdd_err("Command not allowed in FTM mode");
7853 return -EINVAL;
7854 }
7855
7856 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
7857
7858 nl_buf_len = NLMSG_HDRLEN;
7859 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
7860
7861 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7862 if (!skb) {
7863 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
7864 return -ENOMEM;
7865 }
7866
7867 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
7868 hdd_ctx->wmi_max_len)) {
7869 hdd_err("nla put failure");
7870 goto nla_put_failure;
7871 }
7872
7873 cfg80211_vendor_cmd_reply(skb);
7874
7875 EXIT();
7876
7877 return 0;
7878
7879nla_put_failure:
7880 kfree_skb(skb);
7881 return -EINVAL;
7882}
7883
7884/**
7885 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
7886 * @wiphy: wiphy structure pointer
7887 * @wdev: Wireless device structure pointer
7888 * @data: Pointer to the data received
7889 * @data_len: Length of @data
7890 *
7891 * Return: 0 on success; errno on failure
7892 */
7893static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7894 struct wireless_dev *wdev,
7895 const void *data, int data_len)
7896{
7897 int ret;
7898
7899 cds_ssr_protect(__func__);
7900 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
7901 cds_ssr_unprotect(__func__);
7902
7903 return ret;
7904}
7905
7906/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307907 *__wlan_hdd_cfg80211_setband() - set band
7908 * @wiphy: Pointer to wireless phy
7909 * @wdev: Pointer to wireless device
7910 * @data: Pointer to data
7911 * @data_len: Length of @data
7912 *
7913 * Return: 0 on success, negative errno on failure
7914 */
7915static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7916 struct wireless_dev *wdev,
7917 const void *data, int data_len)
7918{
7919 struct net_device *dev = wdev->netdev;
7920 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7921 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7922 int ret;
7923 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
7924 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
7925
7926 ENTER();
7927
7928 ret = wlan_hdd_validate_context(hdd_ctx);
7929 if (ret)
7930 return ret;
7931
7932 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
7933 hdd_err(FL("Invalid ATTR"));
7934 return -EINVAL;
7935 }
7936
7937 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
7938 hdd_err(FL("attr SETBAND_VALUE failed"));
7939 return -EINVAL;
7940 }
7941
7942 ret = hdd_set_band(dev,
7943 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
7944
7945 EXIT();
7946 return ret;
7947}
7948
7949/**
7950 * wlan_hdd_cfg80211_setband() - Wrapper to setband
7951 * @wiphy: wiphy structure pointer
7952 * @wdev: Wireless device structure pointer
7953 * @data: Pointer to the data received
7954 * @data_len: Length of @data
7955 *
7956 * Return: 0 on success; errno on failure
7957 */
7958static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7959 struct wireless_dev *wdev,
7960 const void *data, int data_len)
7961{
7962 int ret;
7963
7964 cds_ssr_protect(__func__);
7965 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
7966 cds_ssr_unprotect(__func__);
7967
7968 return ret;
7969}
7970
Mukul Sharma69c44cd2016-09-12 18:33:57 +05307971static const struct
7972nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
7973 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
7974 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
7975 .len = QDF_MAC_ADDR_SIZE},
7976};
7977
7978/**
7979 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7980 * @wiphy: Pointer to wireless phy
7981 * @wdev: Pointer to wireless device
7982 * @data: Pointer to data
7983 * @data_len: Length of @data
7984 *
7985 * This function is used to enable/disable roaming using vendor commands
7986 *
7987 * Return: 0 on success, negative errno on failure
7988 */
7989static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7990 struct wireless_dev *wdev,
7991 const void *data, int data_len)
7992{
7993 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7994 struct net_device *dev = wdev->netdev;
7995 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7996 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7997 uint32_t is_fast_roam_enabled;
7998 int ret;
7999
8000 ENTER_DEV(dev);
8001
8002 ret = wlan_hdd_validate_context(hdd_ctx);
8003 if (0 != ret)
8004 return ret;
8005
8006 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
8007 hdd_err("Command not allowed in FTM mode");
8008 return -EINVAL;
8009 }
8010
8011 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
8012 qca_wlan_vendor_attr);
8013 if (ret) {
8014 hdd_err("Invalid ATTR");
8015 return -EINVAL;
8016 }
8017
8018 /* Parse and fetch Enable flag */
8019 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
8020 hdd_err("attr enable failed");
8021 return -EINVAL;
8022 }
8023
8024 is_fast_roam_enabled = nla_get_u32(
8025 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
8026 hdd_notice("isFastRoamEnabled %d", is_fast_roam_enabled);
8027
8028 /* Update roaming */
8029 ret = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
8030 is_fast_roam_enabled);
8031 if (ret)
8032 hdd_err("sme_config_fast_roaming failed");
8033 EXIT();
8034 return ret;
8035}
8036
8037/**
8038 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
8039 * @wiphy: Pointer to wireless phy
8040 * @wdev: Pointer to wireless device
8041 * @data: Pointer to data
8042 * @data_len: Length of @data
8043 *
8044 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
8045 *
8046 * Return: 0 on success, negative errno on failure
8047 */
8048static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
8049 struct wireless_dev *wdev,
8050 const void *data, int data_len)
8051{
8052 int ret;
8053
8054 cds_ssr_protect(__func__);
8055 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
8056 cds_ssr_unprotect(__func__);
8057
8058 return ret;
8059}
8060
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008061const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
8062 {
8063 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8064 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
8065 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05308066 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008067 .doit = is_driver_dfs_capable
8068 },
8069
8070#ifdef WLAN_FEATURE_NAN
8071 {
8072 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8073 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
8074 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8075 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8076 .doit = wlan_hdd_cfg80211_nan_request
8077 },
8078#endif
8079
8080#ifdef WLAN_FEATURE_STATS_EXT
8081 {
8082 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8083 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
8084 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8085 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8086 .doit = wlan_hdd_cfg80211_stats_ext_request
8087 },
8088#endif
8089#ifdef FEATURE_WLAN_EXTSCAN
8090 {
8091 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8092 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
8093 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8094 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8095 .doit = wlan_hdd_cfg80211_extscan_start
8096 },
8097 {
8098 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8099 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
8100 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8101 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8102 .doit = wlan_hdd_cfg80211_extscan_stop
8103 },
8104 {
8105 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8106 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
8107 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8108 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
8109 },
8110 {
8111 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8112 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
8113 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8114 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8115 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
8116 },
8117 {
8118 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8119 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
8120 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8121 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8122 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
8123 },
8124 {
8125 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8126 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
8127 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8128 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8129 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
8130 },
8131 {
8132 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8133 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
8134 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8135 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8136 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
8137 },
8138 {
8139 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8140 .info.subcmd =
8141 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
8142 .flags =
8143 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8144 WIPHY_VENDOR_CMD_NEED_RUNNING,
8145 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
8146 },
8147 {
8148 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8149 .info.subcmd =
8150 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
8151 .flags =
8152 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8153 WIPHY_VENDOR_CMD_NEED_RUNNING,
8154 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
8155 },
8156 {
8157 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8158 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
8159 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8160 WIPHY_VENDOR_CMD_NEED_NETDEV |
8161 WIPHY_VENDOR_CMD_NEED_RUNNING,
8162 .doit = wlan_hdd_cfg80211_set_epno_list
8163 },
8164#endif /* FEATURE_WLAN_EXTSCAN */
8165
8166#ifdef WLAN_FEATURE_LINK_LAYER_STATS
8167 {
8168 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8169 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
8170 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8171 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8172 .doit = wlan_hdd_cfg80211_ll_stats_clear
8173 },
8174
8175 {
8176 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8177 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
8178 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8179 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8180 .doit = wlan_hdd_cfg80211_ll_stats_set
8181 },
8182
8183 {
8184 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8185 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
8186 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8187 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8188 .doit = wlan_hdd_cfg80211_ll_stats_get
8189 },
8190#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
8191#ifdef FEATURE_WLAN_TDLS
8192 {
8193 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8194 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
8195 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8196 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8197 .doit = wlan_hdd_cfg80211_exttdls_enable
8198 },
8199 {
8200 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8201 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
8202 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8203 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8204 .doit = wlan_hdd_cfg80211_exttdls_disable
8205 },
8206 {
8207 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8208 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
8209 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8210 .doit = wlan_hdd_cfg80211_exttdls_get_status
8211 },
8212#endif
8213 {
8214 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8215 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
8216 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8217 .doit = wlan_hdd_cfg80211_get_supported_features
8218 },
8219 {
8220 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8221 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
8222 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8223 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
8224 },
8225 {
8226 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8227 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
8228 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05308229 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008230 },
8231 {
8232 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8233 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
8234 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8235 WIPHY_VENDOR_CMD_NEED_NETDEV,
8236 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
8237 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07008238 {
8239 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8240 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
8241 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8242 WIPHY_VENDOR_CMD_NEED_NETDEV,
8243 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
8244 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008245 {
8246 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05308247 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
8248 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8249 WIPHY_VENDOR_CMD_NEED_NETDEV |
8250 WIPHY_VENDOR_CMD_NEED_RUNNING,
8251 .doit = hdd_cfg80211_get_station_cmd
8252 },
8253 {
8254 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008255 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
8256 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8257 WIPHY_VENDOR_CMD_NEED_NETDEV |
8258 WIPHY_VENDOR_CMD_NEED_RUNNING,
8259 .doit = wlan_hdd_cfg80211_do_acs
8260 },
8261
8262 {
8263 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8264 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
8265 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8266 WIPHY_VENDOR_CMD_NEED_NETDEV,
8267 .doit = wlan_hdd_cfg80211_get_features
8268 },
8269#ifdef WLAN_FEATURE_ROAM_OFFLOAD
8270 {
8271 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8272 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
8273 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8274 WIPHY_VENDOR_CMD_NEED_NETDEV |
8275 WIPHY_VENDOR_CMD_NEED_RUNNING,
8276 .doit = wlan_hdd_cfg80211_keymgmt_set_key
8277 },
8278#endif
8279#ifdef FEATURE_WLAN_EXTSCAN
8280 {
8281 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8282 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
8283 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8284 WIPHY_VENDOR_CMD_NEED_NETDEV |
8285 WIPHY_VENDOR_CMD_NEED_RUNNING,
8286 .doit = wlan_hdd_cfg80211_set_passpoint_list
8287 },
8288 {
8289 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8290 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
8291 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8292 WIPHY_VENDOR_CMD_NEED_NETDEV |
8293 WIPHY_VENDOR_CMD_NEED_RUNNING,
8294 .doit = wlan_hdd_cfg80211_reset_passpoint_list
8295 },
8296 {
8297 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8298 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
8299 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8300 WIPHY_VENDOR_CMD_NEED_NETDEV |
8301 WIPHY_VENDOR_CMD_NEED_RUNNING,
8302 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
8303 },
8304 {
8305 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8306 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
8307 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8308 WIPHY_VENDOR_CMD_NEED_NETDEV |
8309 WIPHY_VENDOR_CMD_NEED_RUNNING,
8310 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
8311 },
8312#endif /* FEATURE_WLAN_EXTSCAN */
8313 {
8314 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8315 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
8316 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8317 WIPHY_VENDOR_CMD_NEED_NETDEV,
8318 .doit = wlan_hdd_cfg80211_get_wifi_info
8319 },
Paul Zhang3a210c52016-12-08 10:18:12 +08008320#ifndef WLAN_UMAC_CONVERGENCE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008321 {
8322 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8323 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
8324 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8325 WIPHY_VENDOR_CMD_NEED_NETDEV |
8326 WIPHY_VENDOR_CMD_NEED_RUNNING,
8327 .doit = wlan_hdd_cfg80211_wifi_configuration_set
8328 },
Paul Zhang3a210c52016-12-08 10:18:12 +08008329#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008330 {
8331 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8332 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
8333 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8334 WIPHY_VENDOR_CMD_NEED_NETDEV,
8335 .doit = wlan_hdd_cfg80211_set_ext_roam_params
8336 },
8337 {
8338 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8339 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
8340 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8341 WIPHY_VENDOR_CMD_NEED_NETDEV,
8342 .doit = wlan_hdd_cfg80211_wifi_logger_start
8343 },
8344 {
8345 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8346 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
8347 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8348 WIPHY_VENDOR_CMD_NEED_NETDEV,
8349 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
8350 },
8351 {
8352 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8353 .info.subcmd =
8354 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
8355 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8356 WIPHY_VENDOR_CMD_NEED_NETDEV |
8357 WIPHY_VENDOR_CMD_NEED_RUNNING,
8358 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
8359 },
8360 {
8361 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8362 .info.subcmd =
8363 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
8364 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8365 WIPHY_VENDOR_CMD_NEED_NETDEV |
8366 WIPHY_VENDOR_CMD_NEED_RUNNING,
8367 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
8368 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07008369#ifdef WLAN_FEATURE_TSF
8370 {
8371 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8372 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
8373 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8374 WIPHY_VENDOR_CMD_NEED_NETDEV |
8375 WIPHY_VENDOR_CMD_NEED_RUNNING,
8376 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
8377 },
8378#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008379#ifdef FEATURE_WLAN_TDLS
8380 {
8381 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8382 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
8383 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8384 WIPHY_VENDOR_CMD_NEED_NETDEV |
8385 WIPHY_VENDOR_CMD_NEED_RUNNING,
8386 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
8387 },
8388#endif
8389#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
8390 {
8391 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8392 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
8393 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8394 WIPHY_VENDOR_CMD_NEED_NETDEV |
8395 WIPHY_VENDOR_CMD_NEED_RUNNING,
8396 .doit = wlan_hdd_cfg80211_offloaded_packets
8397 },
8398#endif
8399 {
8400 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8401 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
8402 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8403 WIPHY_VENDOR_CMD_NEED_NETDEV |
8404 WIPHY_VENDOR_CMD_NEED_RUNNING,
8405 .doit = wlan_hdd_cfg80211_monitor_rssi
8406 },
8407 {
8408 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308409 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
8410 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8411 WIPHY_VENDOR_CMD_NEED_NETDEV |
8412 WIPHY_VENDOR_CMD_NEED_RUNNING,
8413 .doit = wlan_hdd_cfg80211_set_ns_offload
8414 },
8415 {
8416 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008417 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
8418 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8419 WIPHY_VENDOR_CMD_NEED_NETDEV |
8420 WIPHY_VENDOR_CMD_NEED_RUNNING,
8421 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
8422 },
8423#ifdef WLAN_FEATURE_MEMDUMP
8424 {
8425 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8426 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
8427 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8428 WIPHY_VENDOR_CMD_NEED_NETDEV |
8429 WIPHY_VENDOR_CMD_NEED_RUNNING,
8430 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
8431 },
8432#endif /* WLAN_FEATURE_MEMDUMP */
8433 {
8434 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8435 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
8436 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8437 WIPHY_VENDOR_CMD_NEED_NETDEV |
8438 WIPHY_VENDOR_CMD_NEED_RUNNING,
8439 .doit = wlan_hdd_cfg80211_vendor_scan
8440 },
8441
8442 /* OCB commands */
8443 {
8444 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8445 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
8446 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8447 WIPHY_VENDOR_CMD_NEED_NETDEV |
8448 WIPHY_VENDOR_CMD_NEED_RUNNING,
8449 .doit = wlan_hdd_cfg80211_ocb_set_config
8450 },
8451 {
8452 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8453 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
8454 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8455 WIPHY_VENDOR_CMD_NEED_NETDEV |
8456 WIPHY_VENDOR_CMD_NEED_RUNNING,
8457 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
8458 },
8459 {
8460 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8461 .info.subcmd =
8462 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
8463 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8464 WIPHY_VENDOR_CMD_NEED_NETDEV |
8465 WIPHY_VENDOR_CMD_NEED_RUNNING,
8466 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
8467 },
8468 {
8469 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8470 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
8471 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8472 WIPHY_VENDOR_CMD_NEED_NETDEV |
8473 WIPHY_VENDOR_CMD_NEED_RUNNING,
8474 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
8475 },
8476 {
8477 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8478 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
8479 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8480 WIPHY_VENDOR_CMD_NEED_NETDEV |
8481 WIPHY_VENDOR_CMD_NEED_RUNNING,
8482 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
8483 },
8484 {
8485 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8486 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
8487 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8488 WIPHY_VENDOR_CMD_NEED_NETDEV |
8489 WIPHY_VENDOR_CMD_NEED_RUNNING,
8490 .doit = wlan_hdd_cfg80211_dcc_get_stats
8491 },
8492 {
8493 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8494 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
8495 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8496 WIPHY_VENDOR_CMD_NEED_NETDEV |
8497 WIPHY_VENDOR_CMD_NEED_RUNNING,
8498 .doit = wlan_hdd_cfg80211_dcc_clear_stats
8499 },
8500 {
8501 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8502 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
8503 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8504 WIPHY_VENDOR_CMD_NEED_NETDEV |
8505 WIPHY_VENDOR_CMD_NEED_RUNNING,
8506 .doit = wlan_hdd_cfg80211_dcc_update_ndl
8507 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308508 {
8509 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8510 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
8511 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8512 WIPHY_VENDOR_CMD_NEED_NETDEV |
8513 WIPHY_VENDOR_CMD_NEED_RUNNING,
8514 .doit = wlan_hdd_cfg80211_get_link_properties
8515 },
Peng Xu278d0122015-09-24 16:34:17 -07008516 {
Peng Xud2220962016-07-11 17:59:17 -07008517 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07008518 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
8519 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8520 WIPHY_VENDOR_CMD_NEED_NETDEV |
8521 WIPHY_VENDOR_CMD_NEED_RUNNING,
8522 .doit = wlan_hdd_cfg80211_set_ota_test
8523 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08008524#ifdef FEATURE_LFR_SUBNET_DETECTION
8525 {
8526 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8527 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
8528 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8529 WIPHY_VENDOR_CMD_NEED_NETDEV |
8530 WIPHY_VENDOR_CMD_NEED_RUNNING,
8531 .doit = wlan_hdd_cfg80211_set_gateway_params
8532 },
8533#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07008534 {
Peng Xud2220962016-07-11 17:59:17 -07008535 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07008536 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
8537 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8538 WIPHY_VENDOR_CMD_NEED_NETDEV |
8539 WIPHY_VENDOR_CMD_NEED_RUNNING,
8540 .doit = wlan_hdd_cfg80211_txpower_scale
8541 },
8542 {
8543 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8544 .info.subcmd =
8545 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
8546 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8547 WIPHY_VENDOR_CMD_NEED_NETDEV |
8548 WIPHY_VENDOR_CMD_NEED_RUNNING,
8549 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
8550 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308551 {
8552 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8553 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
8554 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8555 WIPHY_VENDOR_CMD_NEED_NETDEV |
8556 WIPHY_VENDOR_CMD_NEED_RUNNING,
8557 .doit = wlan_hdd_cfg80211_bpf_offload
8558 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308559 {
8560 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05308561 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
8562 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8563 WIPHY_VENDOR_CMD_NEED_NETDEV |
8564 WIPHY_VENDOR_CMD_NEED_RUNNING,
8565 .doit = wlan_hdd_cfg80211_acs_dfs_mode
8566 },
8567 {
8568 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308569 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
8570 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8571 WIPHY_VENDOR_CMD_NEED_NETDEV |
8572 WIPHY_VENDOR_CMD_NEED_RUNNING,
8573 .doit = wlan_hdd_cfg80211_sta_roam_policy
8574 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05308575#ifdef FEATURE_WLAN_CH_AVOID
8576 {
8577 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8578 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
8579 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8580 WIPHY_VENDOR_CMD_NEED_NETDEV |
8581 WIPHY_VENDOR_CMD_NEED_RUNNING,
8582 .doit = wlan_hdd_cfg80211_avoid_freq
8583 },
8584#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308585 {
8586 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308587 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
8588 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8589 WIPHY_VENDOR_CMD_NEED_NETDEV |
8590 WIPHY_VENDOR_CMD_NEED_RUNNING,
8591 .doit = wlan_hdd_cfg80211_sap_configuration_set
8592 },
Peng Xu8fdaa492016-06-22 10:20:47 -07008593 {
Peng Xu4225c152016-07-14 21:18:14 -07008594 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07008595 .info.subcmd =
8596 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
8597 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8598 WIPHY_VENDOR_CMD_NEED_NETDEV |
8599 WIPHY_VENDOR_CMD_NEED_RUNNING,
8600 .doit = wlan_hdd_cfg80211_p2p_lo_start
8601 },
8602 {
8603 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8604 .info.subcmd =
8605 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
8606 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8607 WIPHY_VENDOR_CMD_NEED_NETDEV |
8608 WIPHY_VENDOR_CMD_NEED_RUNNING,
8609 .doit = wlan_hdd_cfg80211_p2p_lo_stop
8610 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308611 {
8612 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8613 .info.subcmd =
8614 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
8615 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8616 WIPHY_VENDOR_CMD_NEED_NETDEV |
8617 WIPHY_VENDOR_CMD_NEED_RUNNING,
8618 .doit = wlan_hdd_cfg80211_conditional_chan_switch
8619 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07008620#ifdef WLAN_FEATURE_NAN_DATAPATH
8621 {
8622 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8623 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
8624 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8625 WIPHY_VENDOR_CMD_NEED_NETDEV |
8626 WIPHY_VENDOR_CMD_NEED_RUNNING,
8627 .doit = wlan_hdd_cfg80211_process_ndp_cmd
8628 },
8629#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308630 {
8631 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8632 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
8633 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8634 WIPHY_VENDOR_CMD_NEED_NETDEV |
8635 WIPHY_VENDOR_CMD_NEED_RUNNING,
8636 .doit = wlan_hdd_cfg80211_get_wakelock_stats
8637 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308638 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308639 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8640 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
8641 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8642 WIPHY_VENDOR_CMD_NEED_NETDEV |
8643 WIPHY_VENDOR_CMD_NEED_RUNNING,
8644 .doit = wlan_hdd_cfg80211_get_bus_size
8645 },
8646 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308647 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
8648 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8649 WIPHY_VENDOR_CMD_NEED_NETDEV |
8650 WIPHY_VENDOR_CMD_NEED_RUNNING,
8651 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308652 },
8653 {
8654 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8655 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
8656 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8657 WIPHY_VENDOR_CMD_NEED_NETDEV |
8658 WIPHY_VENDOR_CMD_NEED_RUNNING,
8659 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05308660 },
8661#ifdef WLAN_FEATURE_DISA
8662 {
8663 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8664 .info.subcmd =
8665 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
8666 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8667 WIPHY_VENDOR_CMD_NEED_NETDEV |
8668 WIPHY_VENDOR_CMD_NEED_RUNNING,
8669 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
8670 },
8671#endif
Kabilan Kannand053aaf2016-10-26 02:06:14 -07008672#ifdef FEATURE_WLAN_TDLS
8673 {
8674 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8675 .info.subcmd =
8676 QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS,
8677 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8678 WIPHY_VENDOR_CMD_NEED_NETDEV |
8679 WIPHY_VENDOR_CMD_NEED_RUNNING,
8680 .doit = wlan_hdd_cfg80211_configure_tdls_mode
8681 }
8682#endif
Paul Zhang3a210c52016-12-08 10:18:12 +08008683#ifdef WLAN_UMAC_CONVERGENCE
8684 COMMON_VENDOR_COMMANDS
8685#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008686};
8687
Anurag Chouhan7c01cc42016-12-16 21:33:43 +05308688#if ((LINUX_VERSION_CODE > KERNEL_VERSION(4, 4, 0)) || \
8689 defined(CFG80211_MULTI_SCAN_PLAN_BACKPORT)) && \
8690 defined(FEATURE_WLAN_SCAN_PNO)
8691/**
8692 * hdd_config_sched_scan_plans_to_wiphy() - configure sched scan plans to wiphy
8693 * @wiphy: pointer to wiphy
8694 * @config: pointer to config
8695 *
8696 * Return: None
8697 */
8698static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
8699 struct hdd_config *config)
8700{
8701 if (config->configPNOScanSupport) {
8702 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8703 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
8704 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
8705 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
8706 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
8707 if (config->max_sched_scan_plan_interval)
8708 wiphy->max_sched_scan_plan_interval =
8709 config->max_sched_scan_plan_interval;
8710 if (config->max_sched_scan_plan_iterations)
8711 wiphy->max_sched_scan_plan_iterations =
8712 config->max_sched_scan_plan_iterations;
8713 }
8714}
8715#else
8716static void hdd_config_sched_scan_plans_to_wiphy(struct wiphy *wiphy,
8717 struct hdd_config *config)
8718{
8719}
8720#endif
8721
8722
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008723/**
8724 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
8725 * @priv_size: Size of the hdd context.
8726 *
8727 * Allocate wiphy context and hdd context.
8728 *
8729 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008730 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008731hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008732{
8733 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008734 hdd_context_t *hdd_ctx;
8735
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008736 ENTER();
8737
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008738 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
8739
8740 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008741 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008742 return NULL;
8743 }
8744
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008745 hdd_ctx = wiphy_priv(wiphy);
8746
8747 hdd_ctx->wiphy = wiphy;
8748
8749 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008750}
8751
8752/*
8753 * FUNCTION: wlan_hdd_cfg80211_update_band
8754 * This function is called from the supplicant through a
8755 * private ioctl to change the band value
8756 */
8757int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
8758{
8759 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07008760 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008761
8762 ENTER();
8763
Dustin Browna30892e2016-10-12 17:28:36 -07008764 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008765
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008766 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008767 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008768
8769 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8770 struct ieee80211_supported_band *band = wiphy->bands[i];
8771
8772 channelEnabledState =
8773 cds_get_channel_state(band->channels[j].
8774 hw_value);
8775
Dustin Browna30892e2016-10-12 17:28:36 -07008776 if (NL80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008777 /* 5G only */
8778#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8779 /* Enable Social channels for P2P */
8780 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8781 (band->channels[j].center_freq)
8782 && CHANNEL_STATE_ENABLE ==
8783 channelEnabledState)
8784 band->channels[j].flags &=
8785 ~IEEE80211_CHAN_DISABLED;
8786 else
8787#endif
8788 band->channels[j].flags |=
8789 IEEE80211_CHAN_DISABLED;
8790 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07008791 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008792 eCSR_BAND_24 == eBand) {
8793 /* 2G only */
8794 band->channels[j].flags |=
8795 IEEE80211_CHAN_DISABLED;
8796 continue;
8797 }
8798
Amar Singhal6842e8f2016-02-23 16:30:32 -08008799 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008800 band->channels[j].flags &=
8801 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008802 }
8803 }
8804 return 0;
8805}
8806
8807/*
8808 * FUNCTION: wlan_hdd_cfg80211_init
8809 * This function is called by hdd_wlan_startup()
8810 * during initialization.
8811 * This function is used to initialize and register wiphy structure.
8812 */
8813int wlan_hdd_cfg80211_init(struct device *dev,
8814 struct wiphy *wiphy, struct hdd_config *pCfg)
8815{
8816 int i, j;
8817 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8818
8819 ENTER();
8820
8821 /* Now bind the underlying wlan device with wiphy */
8822 set_wiphy_dev(wiphy, dev);
8823
8824 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
8825
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008826#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
8827 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008828 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008829#else
8830 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008831 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008832#endif
8833
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008834 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
8835 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
8836 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
8837#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
8838 | WIPHY_FLAG_4ADDR_STATION
8839#endif
8840 | WIPHY_FLAG_OFFCHAN_TX;
8841
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008842#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
8843 wiphy->wowlan = &wowlan_support_cfg80211_init;
8844#else
8845 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
8846 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
8847 wiphy->wowlan.pattern_min_len = 1;
8848 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
8849#endif
8850
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07008851 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008852#ifdef FEATURE_WLAN_ESE
8853 || pCfg->isEseIniFeatureEnabled
8854#endif
8855 ) {
8856 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
8857 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008858#ifdef FEATURE_WLAN_TDLS
8859 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
8860 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
8861#endif
8862
8863 wiphy->features |= NL80211_FEATURE_HT_IBSS;
8864
Naveen Rawatc77e6e72016-08-05 15:19:03 -07008865#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
8866 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
8867#endif
8868
Anurag Chouhan7c01cc42016-12-16 21:33:43 +05308869 hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008870
8871#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05308872 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008873#endif
8874
8875 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
8876 driver can still register regulatory callback and
8877 it will get regulatory settings in wiphy->band[], but
8878 driver need to determine what to do with both
8879 regulatory settings */
8880
8881 wiphy->reg_notifier = hdd_reg_notifier;
8882
8883#if defined QCA_WIFI_FTM
8884}
8885#endif
8886
8887 wiphy->max_scan_ssids = MAX_SCAN_SSID;
8888
8889 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
8890
8891 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
8892
Arun Khandavallifae92942016-08-01 13:31:08 +05308893 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
8894 | BIT(NL80211_IFTYPE_ADHOC)
8895 | BIT(NL80211_IFTYPE_P2P_CLIENT)
8896 | BIT(NL80211_IFTYPE_P2P_GO)
8897 | BIT(NL80211_IFTYPE_AP)
8898 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008899
Arun Khandavallifae92942016-08-01 13:31:08 +05308900 if (pCfg->advertiseConcurrentOperation) {
8901 if (pCfg->enableMCC) {
8902 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07008903
Arun Khandavallifae92942016-08-01 13:31:08 +05308904 for (i = 0;
8905 i < ARRAY_SIZE(wlan_hdd_iface_combination);
8906 i++) {
8907 if (!pCfg->allowMCCGODiffBI)
8908 wlan_hdd_iface_combination[i].
8909 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008910 }
8911 }
8912 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +05308913 ARRAY_SIZE(wlan_hdd_iface_combination);
8914 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008915 }
8916
8917 /* Before registering we need to update the ht capabilitied based
8918 * on ini values*/
8919 if (!pCfg->ShortGI20MhzEnable) {
8920 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
8921 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008922 }
8923
8924 if (!pCfg->ShortGI40MhzEnable) {
8925 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
8926 }
8927
8928 if (!pCfg->nChannelBondingMode5GHz) {
8929 wlan_hdd_band_5_ghz.ht_cap.cap &=
8930 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
8931 }
8932
Abhishek Singhf512bf32016-05-04 16:47:46 +05308933 /*
8934 * In case of static linked driver at the time of driver unload,
8935 * module exit doesn't happens. Module cleanup helps in cleaning
8936 * of static memory.
8937 * If driver load happens statically, at the time of driver unload,
8938 * wiphy flags don't get reset because of static memory.
8939 * It's better not to store channel in static memory.
8940 */
Dustin Browna30892e2016-10-12 17:28:36 -07008941 wiphy->bands[NL80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
8942 wiphy->bands[NL80211_BAND_2GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05308943 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07008944 if (wiphy->bands[NL80211_BAND_2GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05308945 hdd_err("Not enough memory to allocate channels");
8946 return -ENOMEM;
8947 }
Dustin Browna30892e2016-10-12 17:28:36 -07008948 qdf_mem_copy(wiphy->bands[NL80211_BAND_2GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05308949 &hdd_channels_2_4_ghz[0],
8950 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +05308951 if ((hdd_is_5g_supported(pHddCtx)) &&
8952 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
8953 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
8954 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
8955 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Dustin Browna30892e2016-10-12 17:28:36 -07008956 wiphy->bands[NL80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
8957 wiphy->bands[NL80211_BAND_5GHZ]->channels =
Abhishek Singhf512bf32016-05-04 16:47:46 +05308958 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
Dustin Browna30892e2016-10-12 17:28:36 -07008959 if (wiphy->bands[NL80211_BAND_5GHZ]->channels == NULL) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05308960 hdd_err("Not enough memory to allocate channels");
8961 qdf_mem_free(wiphy->
Dustin Browna30892e2016-10-12 17:28:36 -07008962 bands[NL80211_BAND_2GHZ]->channels);
8963 wiphy->bands[NL80211_BAND_2GHZ]->channels = NULL;
Abhishek Singhf512bf32016-05-04 16:47:46 +05308964 return -ENOMEM;
8965 }
Dustin Browna30892e2016-10-12 17:28:36 -07008966 qdf_mem_copy(wiphy->bands[NL80211_BAND_5GHZ]->channels,
Abhishek Singhf512bf32016-05-04 16:47:46 +05308967 &hdd_channels_5_ghz[0],
8968 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008969 }
8970
Dustin Browna30892e2016-10-12 17:28:36 -07008971 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008972
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008973 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008974 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008975
8976 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8977 struct ieee80211_supported_band *band = wiphy->bands[i];
8978
Dustin Browna30892e2016-10-12 17:28:36 -07008979 if (NL80211_BAND_2GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008980 eCSR_BAND_5G == pCfg->nBandCapability) {
8981 /* 5G only */
8982#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8983 /* Enable social channels for P2P */
8984 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8985 (band->channels[j].center_freq))
8986 band->channels[j].flags &=
8987 ~IEEE80211_CHAN_DISABLED;
8988 else
8989#endif
8990 band->channels[j].flags |=
8991 IEEE80211_CHAN_DISABLED;
8992 continue;
Dustin Browna30892e2016-10-12 17:28:36 -07008993 } else if (NL80211_BAND_5GHZ == i &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008994 eCSR_BAND_24 == pCfg->nBandCapability) {
8995 /* 2G only */
8996 band->channels[j].flags |=
8997 IEEE80211_CHAN_DISABLED;
8998 continue;
8999 }
9000 }
9001 }
9002 /*Initialise the supported cipher suite details */
9003 wiphy->cipher_suites = hdd_cipher_suites;
9004 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
9005
9006 /*signal strength in mBm (100*dBm) */
9007 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
9008 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
9009
Anurag Chouhan6d760662016-02-20 16:05:43 +05309010 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009011 wiphy->n_vendor_commands =
9012 ARRAY_SIZE(hdd_wiphy_vendor_commands);
9013 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
9014
9015 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
9016 wiphy->n_vendor_events =
9017 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
9018 }
9019
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009020 if (pCfg->enableDFSMasterCap) {
9021 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
9022 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009023
9024 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
9025
9026#ifdef QCA_HT_2040_COEX
9027 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
9028#endif
Agrawal, Ashish4e5fa1c2016-09-21 19:03:43 +05309029 wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
Abhishek Singh1bdb1572015-10-16 16:24:19 +05309030 hdd_add_channel_switch_support(&wiphy->flags);
9031
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009032 EXIT();
9033 return 0;
9034}
9035
Abhishek Singhf512bf32016-05-04 16:47:46 +05309036/**
Yingying Tang80e15f32016-09-27 18:23:01 +08009037 * wlan_hdd_cfg80211_deinit() - Deinit cfg80211
9038 * @wiphy: the wiphy to validate against
Abhishek Singhf512bf32016-05-04 16:47:46 +05309039 *
9040 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +05309041 * memory allocated in wlan_hdd_cfg80211_init also
9042 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +05309043 *
9044 * Return: void
9045 */
9046void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
9047{
9048 int i;
9049
Dustin Browna30892e2016-10-12 17:28:36 -07009050 for (i = 0; i < NUM_NL80211_BANDS; i++) {
Abhishek Singhf512bf32016-05-04 16:47:46 +05309051 if (NULL != wiphy->bands[i] &&
9052 (NULL != wiphy->bands[i]->channels)) {
9053 qdf_mem_free(wiphy->bands[i]->channels);
9054 wiphy->bands[i]->channels = NULL;
9055 }
9056 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +05309057 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +05309058}
9059
Yingying Tang80e15f32016-09-27 18:23:01 +08009060/**
9061 * wlan_hdd_update_band_cap() - update capabilities for supported bands
9062 * @hdd_ctx: HDD context
9063 *
9064 * this function will update capabilities for supported bands
9065 *
9066 * Return: void
9067 */
9068static void wlan_hdd_update_band_cap(hdd_context_t *hdd_ctx)
9069{
9070 uint32_t val32;
9071 uint16_t val16;
9072 tSirMacHTCapabilityInfo *ht_cap_info;
9073 QDF_STATUS status;
9074
9075 status = sme_cfg_get_int(hdd_ctx->hHal, WNI_CFG_HT_CAP_INFO, &val32);
9076 if (QDF_STATUS_SUCCESS != status) {
9077 hdd_err("could not get HT capability info");
9078 val32 = 0;
9079 }
9080 val16 = (uint16_t)val32;
9081 ht_cap_info = (tSirMacHTCapabilityInfo *)&val16;
9082
9083 if (ht_cap_info->txSTBC == true) {
9084 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ])
9085 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap |=
9086 IEEE80211_HT_CAP_TX_STBC;
9087 if (NULL != hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ])
9088 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->ht_cap.cap |=
9089 IEEE80211_HT_CAP_TX_STBC;
9090 }
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08009091
9092 if (!sme_is_feature_supported_by_fw(DOT11AC)) {
9093 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->
9094 vht_cap.vht_supported = 0;
9095 hdd_ctx->wiphy->bands[NL80211_BAND_2GHZ]->vht_cap.cap = 0;
9096 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->
9097 vht_cap.vht_supported = 0;
9098 hdd_ctx->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap.cap = 0;
9099 }
Yingying Tang80e15f32016-09-27 18:23:01 +08009100}
9101
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009102/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309103 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009104 * initialization. In wlan_hdd_cfg80211_init, only the
9105 * default values will be initialized. The final initialization
9106 * of all required members can be done here.
9107 */
Yingying Tang80e15f32016-09-27 18:23:01 +08009108void wlan_hdd_update_wiphy(hdd_context_t *hdd_ctx)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009109{
Yingying Tang80e15f32016-09-27 18:23:01 +08009110 hdd_ctx->wiphy->max_ap_assoc_sta = hdd_ctx->config->maxNumberOfPeers;
9111
9112 wlan_hdd_update_band_cap(hdd_ctx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009113}
9114
Yingying Tang3ba3dbc2016-09-27 16:36:58 +08009115/**
9116 * wlan_hdd_update_11n_mode - update 11n mode in hdd cfg
9117 * @cfg: hdd cfg
9118 *
9119 * this function update 11n mode in hdd cfg
9120 *
9121 * Return: void
9122 */
9123void wlan_hdd_update_11n_mode(struct hdd_config *cfg)
9124{
9125 if (sme_is_feature_supported_by_fw(DOT11AC)) {
9126 hdd_notice("support 11ac");
9127 } else {
9128 hdd_notice("not support 11ac");
9129 if ((cfg->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ||
9130 (cfg->dot11Mode == eHDD_DOT11_MODE_11ac)) {
9131 cfg->dot11Mode = eHDD_DOT11_MODE_11n;
9132 cfg->sap_p2p_11ac_override = 0;
9133 }
9134 }
9135}
9136
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009137/* In this function we are registering wiphy. */
9138int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
9139{
9140 ENTER();
9141 /* Register our wiphy dev with cfg80211 */
9142 if (0 > wiphy_register(wiphy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009143 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009144 return -EIO;
9145 }
9146
9147 EXIT();
9148 return 0;
9149}
9150
9151/*
9152 HDD function to update wiphy capability based on target offload status.
9153
9154 wlan_hdd_cfg80211_init() does initialization of all wiphy related
9155 capability even before downloading firmware to the target. In discrete
9156 case, host will get know certain offload capability (say sched_scan
9157 caps) only after downloading firmware to the target and target boots up.
9158 This function is used to override setting done in wlan_hdd_cfg80211_init()
9159 based on target capability.
9160 */
9161void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
9162{
9163#ifdef FEATURE_WLAN_SCAN_PNO
9164 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
9165 struct hdd_config *pCfg = pHddCtx->config;
9166
9167 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
9168 * control comes here. Here just we need to clear it if firmware doesn't
9169 * have PNO support. */
9170 if (!pCfg->PnoOffload) {
9171 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
9172 wiphy->max_sched_scan_ssids = 0;
9173 wiphy->max_match_sets = 0;
9174 wiphy->max_sched_scan_ie_len = 0;
9175 }
9176#endif
9177}
9178
9179/* This function registers for all frame which supplicant is interested in */
9180void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
9181{
9182 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9183 /* Register for all P2P action, public action etc frames */
9184 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9185
9186 ENTER();
9187
Abhishek Singh7996eb72015-12-30 17:24:02 +05309188 /* Register frame indication call back */
9189 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
9190
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +05309191 /* Register for p2p ack indication */
9192 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
9193
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009194 /* Right now we are registering these frame when driver is getting
9195 initialized. Once we will move to 2.6.37 kernel, in which we have
9196 frame register ops, we will move this code as a part of that */
9197 /* GAS Initial Request */
9198 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9199 (uint8_t *) GAS_INITIAL_REQ,
9200 GAS_INITIAL_REQ_SIZE);
9201
9202 /* GAS Initial Response */
9203 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9204 (uint8_t *) GAS_INITIAL_RSP,
9205 GAS_INITIAL_RSP_SIZE);
9206
9207 /* GAS Comeback Request */
9208 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9209 (uint8_t *) GAS_COMEBACK_REQ,
9210 GAS_COMEBACK_REQ_SIZE);
9211
9212 /* GAS Comeback Response */
9213 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9214 (uint8_t *) GAS_COMEBACK_RSP,
9215 GAS_COMEBACK_RSP_SIZE);
9216
9217 /* P2P Public Action */
9218 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9219 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9220 P2P_PUBLIC_ACTION_FRAME_SIZE);
9221
9222 /* P2P Action */
9223 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9224 (uint8_t *) P2P_ACTION_FRAME,
9225 P2P_ACTION_FRAME_SIZE);
9226
9227 /* WNM BSS Transition Request frame */
9228 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9229 (uint8_t *) WNM_BSS_ACTION_FRAME,
9230 WNM_BSS_ACTION_FRAME_SIZE);
9231
9232 /* WNM-Notification */
9233 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
9234 (uint8_t *) WNM_NOTIFICATION_FRAME,
9235 WNM_NOTIFICATION_FRAME_SIZE);
9236}
9237
9238void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
9239{
9240 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9241 /* Register for all P2P action, public action etc frames */
9242 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9243
9244 ENTER();
9245
9246 /* Right now we are registering these frame when driver is getting
9247 initialized. Once we will move to 2.6.37 kernel, in which we have
9248 frame register ops, we will move this code as a part of that */
9249 /* GAS Initial Request */
9250
9251 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9252 (uint8_t *) GAS_INITIAL_REQ,
9253 GAS_INITIAL_REQ_SIZE);
9254
9255 /* GAS Initial Response */
9256 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9257 (uint8_t *) GAS_INITIAL_RSP,
9258 GAS_INITIAL_RSP_SIZE);
9259
9260 /* GAS Comeback Request */
9261 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9262 (uint8_t *) GAS_COMEBACK_REQ,
9263 GAS_COMEBACK_REQ_SIZE);
9264
9265 /* GAS Comeback Response */
9266 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9267 (uint8_t *) GAS_COMEBACK_RSP,
9268 GAS_COMEBACK_RSP_SIZE);
9269
9270 /* P2P Public Action */
9271 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9272 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9273 P2P_PUBLIC_ACTION_FRAME_SIZE);
9274
9275 /* P2P Action */
9276 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9277 (uint8_t *) P2P_ACTION_FRAME,
9278 P2P_ACTION_FRAME_SIZE);
9279
9280 /* WNM-Notification */
9281 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
9282 (uint8_t *) WNM_NOTIFICATION_FRAME,
9283 WNM_NOTIFICATION_FRAME_SIZE);
9284}
9285
9286#ifdef FEATURE_WLAN_WAPI
9287void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
9288 const uint8_t *mac_addr, const uint8_t *key,
9289 int key_Len)
9290{
9291 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9292 tCsrRoamSetKey setKey;
9293 bool isConnected = true;
9294 int status = 0;
9295 uint32_t roamId = 0xFF;
9296 uint8_t *pKeyPtr = NULL;
9297 int n = 0;
9298
Jeff Johnson46b40792016-06-29 14:03:14 -07009299 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009300 hdd_device_mode_to_string(pAdapter->device_mode),
9301 pAdapter->device_mode);
9302
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309303 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009304 setKey.keyId = key_index; /* Store Key ID */
9305 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
9306 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
9307 setKey.paeRole = 0; /* the PAE role */
9308 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05309309 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009310 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309311 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009312 }
9313 setKey.keyLength = key_Len;
9314 pKeyPtr = setKey.Key;
9315 memcpy(pKeyPtr, key, key_Len);
9316
Jeff Johnson46b40792016-06-29 14:03:14 -07009317 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009318 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -07009319 hdd_notice("WAPI KEY Data[%d]:%02x ",
9320 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009321
9322 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
9323 if (isConnected) {
9324 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9325 pAdapter->sessionId, &setKey, &roamId);
9326 }
9327 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -07009328 hdd_err("sme_roam_set_key returned ERROR status= %d",
9329 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009330 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
9331 }
9332}
9333#endif /* FEATURE_WLAN_WAPI */
9334
9335uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
9336 uint8_t eid)
9337{
9338 int left = length;
9339 uint8_t *ptr = (uint8_t *)ies_ptr;
9340 uint8_t elem_id, elem_len;
9341
9342 while (left >= 2) {
9343 elem_id = ptr[0];
9344 elem_len = ptr[1];
9345 left -= 2;
9346 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -07009347 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009348 eid, elem_len, left);
9349 return NULL;
9350 }
9351 if (elem_id == eid) {
9352 return ptr;
9353 }
9354
9355 left -= elem_len;
9356 ptr += (elem_len + 2);
9357 }
9358 return NULL;
9359}
9360
9361/*
9362 * FUNCTION: wlan_hdd_validate_operation_channel
9363 * called by wlan_hdd_cfg80211_start_bss() and
9364 * wlan_hdd_set_channel()
9365 * This function validates whether given channel is part of valid
9366 * channel list.
9367 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309368QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009369 int channel)
9370{
9371
9372 uint32_t num_ch = 0;
9373 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
9374 u32 indx = 0;
9375 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9376 uint8_t fValidChannel = false, count = 0;
9377 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
9378
9379 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
9380
9381 if (hdd_pConfig_ini->sapAllowAllChannel) {
9382 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -08009383 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07009384 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009385 fValidChannel = true;
9386 break;
9387 }
9388 }
9389 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -07009390 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309391 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009392 }
9393 } else {
9394 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
9395 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009396 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309397 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009398 }
9399 for (indx = 0; indx < num_ch; indx++) {
9400 if (channel == valid_ch[indx]) {
9401 break;
9402 }
9403 }
9404
9405 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -07009406 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309407 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009408 }
9409 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309410 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009411
9412}
9413
9414#ifdef DHCP_SERVER_OFFLOAD
9415static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
9416{
9417 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
9418 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
9419 uint8_t numEntries = 0;
9420 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
9421 uint8_t num;
9422 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309423 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009424 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -07009425 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009426 return;
9427 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009428 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
9429 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
9430 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
9431 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
9432 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
9433 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -07009434 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009435 goto end;
9436 }
9437 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009438 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009439 goto end;
9440 }
9441 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -07009442 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009443 goto end;
9444 }
9445 for (num = 0; num < numEntries; num++) {
9446 temp = srv_ip[num];
9447 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
9448 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309449 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009450 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009451 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009452 goto end;
9453 }
Jeff Johnson77848112016-06-29 14:52:06 -07009454 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009455end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309456 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009457 return;
9458}
9459#endif /* DHCP_SERVER_OFFLOAD */
9460
9461static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9462 struct net_device *dev,
9463 struct bss_parameters *params)
9464{
9465 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9466 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9467 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309468 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009469
9470 ENTER();
9471
Anurag Chouhan6d760662016-02-20 16:05:43 +05309472 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009473 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009474 return -EINVAL;
9475 }
9476
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05309477 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
9478 hdd_err("invalid session id: %d", pAdapter->sessionId);
9479 return -EINVAL;
9480 }
9481
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309482 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009483 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
9484 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -07009485 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009486 hdd_device_mode_to_string(pAdapter->device_mode),
9487 pAdapter->device_mode, params->ap_isolate);
9488
9489 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9490 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309491 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009492 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009493
Krunal Sonib4326f22016-03-10 13:05:51 -08009494 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
9495 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009496 return -EOPNOTSUPP;
9497 }
9498
9499 /* ap_isolate == -1 means that in change bss, upper layer doesn't
9500 * want to update this parameter */
9501 if (-1 != params->ap_isolate) {
9502 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
9503 !!params->ap_isolate;
9504
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309505 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009506 pAdapter->sessionId,
9507 pAdapter->sessionCtx.
9508 ap.
9509 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309510 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009511 ret = -EINVAL;
9512 }
9513 }
9514
9515 EXIT();
9516 return ret;
9517}
9518
Krunal Soni8c37e322016-02-03 16:08:37 -08009519/**
9520 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
9521 * @ndev: pointer to net device provided by supplicant
9522 * @type: type of the interface, upper layer wanted to change
9523 *
9524 * Upper layer provides the new interface mode that needs to be changed
9525 * for given net device
9526 *
9527 * Return: success or failure in terms of integer value
9528 */
9529static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009530 enum nl80211_iftype type)
9531{
Krunal Soni8c37e322016-02-03 16:08:37 -08009532 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9533 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9534 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009535 hdd_wext_state_t *wext;
9536 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309537 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009538
9539 ENTER();
9540
Krunal Soni8c37e322016-02-03 16:08:37 -08009541 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009542 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009543 return 0;
9544 }
9545
9546 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -08009547 hdd_stop_adapter(hdd_ctx, adapter, true);
9548 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009549 wdev->iftype = type;
9550 /*Check for sub-string p2p to confirm its a p2p interface */
9551 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -08009552 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009553 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009554 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -08009555 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -08009556 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009557 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -08009558 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009559 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009560 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009561 }
Krunal Soni8c37e322016-02-03 16:08:37 -08009562 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
9563 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -08009564 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
9565 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009566 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -08009567 adapter->scan_info.scanAddIE.length;
9568 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309569 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -08009570 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
9571 wext->roamProfile.phyMode =
9572 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
9573 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009574 EXIT();
9575 return status;
9576}
9577
9578static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9579 struct net_device *dev,
9580 struct bss_parameters *params)
9581{
9582 int ret;
9583
9584 cds_ssr_protect(__func__);
9585 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
9586 cds_ssr_unprotect(__func__);
9587
9588 return ret;
9589}
9590
9591/* FUNCTION: wlan_hdd_change_country_code_cd
9592 * to wait for contry code completion
9593 */
9594void *wlan_hdd_change_country_code_cb(void *pAdapter)
9595{
9596 hdd_adapter_t *call_back_pAdapter = pAdapter;
9597 complete(&call_back_pAdapter->change_country_code);
9598 return NULL;
9599}
9600
Rajeev Kumar98edb772016-01-19 12:42:19 -08009601/**
9602 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9603 * @wiphy: Pointer to the wiphy structure
9604 * @ndev: Pointer to the net device
9605 * @type: Interface type
9606 * @flags: Flags for change interface
9607 * @params: Pointer to change interface parameters
9608 *
9609 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009610 */
9611static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9612 struct net_device *ndev,
9613 enum nl80211_iftype type,
9614 u32 *flags,
9615 struct vif_params *params)
9616{
9617 struct wireless_dev *wdev;
9618 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9619 hdd_context_t *pHddCtx;
9620 tCsrRoamProfile *pRoamProfile = NULL;
9621 eCsrRoamBssType LastBSSType;
9622 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309623 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009624 int status;
9625
9626 ENTER();
9627
Anurag Chouhan6d760662016-02-20 16:05:43 +05309628 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009629 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009630 return -EINVAL;
9631 }
9632
9633 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9634 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309635 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009636 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009637
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309638 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009639 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
9640 pAdapter->sessionId, type));
9641
Jeff Johnson77848112016-06-29 14:52:06 -07009642 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009643 pAdapter->device_mode, type);
9644
Arun Khandavallifae92942016-08-01 13:31:08 +05309645 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
9646 if (status) {
9647 hdd_err("Failed to start modules");
9648 return -EINVAL;
9649 }
9650
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009651 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009652 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
9653 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009654 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009655 return -EINVAL;
9656 }
9657
9658 pConfig = pHddCtx->config;
9659 wdev = ndev->ieee80211_ptr;
9660
9661 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009662 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009663
9664 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
9665
Krunal Sonib4326f22016-03-10 13:05:51 -08009666 if ((pAdapter->device_mode == QDF_STA_MODE) ||
9667 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
9668 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
9669 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009670 hdd_wext_state_t *pWextState =
9671 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9672
9673 pRoamProfile = &pWextState->roamProfile;
9674 LastBSSType = pRoamProfile->BSSType;
9675
9676 switch (type) {
9677 case NL80211_IFTYPE_STATION:
9678 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -08009679 case NL80211_IFTYPE_ADHOC:
9680 if (type == NL80211_IFTYPE_ADHOC) {
9681 wlan_hdd_tdls_exit(pAdapter);
9682 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -07009683 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -08009684 }
9685 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
9686 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309687 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009688 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309689 if (hdd_start_adapter(pAdapter)) {
9690 hdd_err("Failed to start adapter :%d",
9691 pAdapter->device_mode);
9692 return -EINVAL;
9693 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009694 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009695 case NL80211_IFTYPE_AP:
9696 case NL80211_IFTYPE_P2P_GO:
9697 {
Jeff Johnson77848112016-06-29 14:52:06 -07009698 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009699 (type ==
9700 NL80211_IFTYPE_AP) ? "SoftAP" :
9701 "P2pGo");
9702
9703 /* Cancel any remain on channel for GO mode */
9704 if (NL80211_IFTYPE_P2P_GO == type) {
9705 wlan_hdd_cancel_existing_remain_on_channel
9706 (pAdapter);
9707 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009708
Arun Khandavallifae92942016-08-01 13:31:08 +05309709 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009710 /* De-init the adapter */
9711 hdd_deinit_adapter(pHddCtx, pAdapter, true);
9712 memset(&pAdapter->sessionCtx, 0,
9713 sizeof(pAdapter->sessionCtx));
9714 pAdapter->device_mode =
9715 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -08009716 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
9717 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009718
9719 /*
9720 * Fw will take care incase of concurrency
9721 */
9722
Krunal Sonib4326f22016-03-10 13:05:51 -08009723 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009724 && (pConfig->apRandomBssidEnabled)) {
9725 /* To meet Android requirements create a randomized
9726 MAC address of the form 02:1A:11:Fx:xx:xx */
9727 get_random_bytes(&ndev->dev_addr[3], 3);
9728 ndev->dev_addr[0] = 0x02;
9729 ndev->dev_addr[1] = 0x1A;
9730 ndev->dev_addr[2] = 0x11;
9731 ndev->dev_addr[3] |= 0xF0;
9732 memcpy(pAdapter->macAddressCurrent.
9733 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309734 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009735 pr_info("wlan: Generated HotSpot BSSID "
9736 MAC_ADDRESS_STR "\n",
9737 MAC_ADDR_ARRAY(ndev->dev_addr));
9738 }
9739
9740 hdd_set_ap_ops(pAdapter->dev);
9741
Arun Khandavallifae92942016-08-01 13:31:08 +05309742 if (hdd_start_adapter(pAdapter)) {
9743 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009744 return -EINVAL;
9745 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009746 /* Interface type changed update in wiphy structure */
9747 if (wdev) {
9748 wdev->iftype = type;
9749 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009750 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009751 return -EINVAL;
9752 }
9753 goto done;
9754 }
9755
9756 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009757 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009758 type);
9759 return -EOPNOTSUPP;
9760 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009761 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9762 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009763 switch (type) {
9764 case NL80211_IFTYPE_STATION:
9765 case NL80211_IFTYPE_P2P_CLIENT:
9766 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -08009767 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
9768 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309769 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009770 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309771 if (hdd_start_adapter(pAdapter)) {
9772 hdd_err("Failed to start adapter :%d",
9773 pAdapter->device_mode);
9774 return -EINVAL;
9775 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009776 goto done;
9777
9778 case NL80211_IFTYPE_AP:
9779 case NL80211_IFTYPE_P2P_GO:
9780 wdev->iftype = type;
9781 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009782 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009783 goto done;
9784
9785 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009786 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009787 type);
9788 return -EOPNOTSUPP;
9789 }
9790 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009791 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009792 pAdapter->device_mode);
9793 return -EOPNOTSUPP;
9794 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009795done:
9796 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009797 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009798
Jeff Johnson2ae6f712016-09-23 15:08:48 -07009799 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009800
9801 EXIT();
9802 return 0;
9803}
9804
Rajeev Kumar98edb772016-01-19 12:42:19 -08009805/**
9806 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9807 * @wiphy: Pointer to the wiphy structure
9808 * @ndev: Pointer to the net device
9809 * @type: Interface type
9810 * @flags: Flags for change interface
9811 * @params: Pointer to change interface parameters
9812 *
9813 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009814 */
9815static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9816 struct net_device *ndev,
9817 enum nl80211_iftype type,
9818 u32 *flags,
9819 struct vif_params *params)
9820{
9821 int ret;
9822
9823 cds_ssr_protect(__func__);
9824 ret =
9825 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
9826 cds_ssr_unprotect(__func__);
9827
9828 return ret;
9829}
9830
9831#ifdef FEATURE_WLAN_TDLS
9832static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
9833 int index, uint8_t match)
9834{
9835 int i;
9836 for (i = 0; i < index; i++) {
9837 if (arr[i] == match)
9838 return true;
9839 }
9840 return false;
9841}
9842#endif
9843
9844/**
9845 * __wlan_hdd_change_station() - change station
9846 * @wiphy: Pointer to the wiphy structure
9847 * @dev: Pointer to the net device.
9848 * @mac: bssid
9849 * @params: Pointer to station parameters
9850 *
9851 * Return: 0 for success, error number on failure.
9852 */
9853#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9854static int __wlan_hdd_change_station(struct wiphy *wiphy,
9855 struct net_device *dev,
9856 const uint8_t *mac,
9857 struct station_parameters *params)
9858#else
9859static int __wlan_hdd_change_station(struct wiphy *wiphy,
9860 struct net_device *dev,
9861 uint8_t *mac,
9862 struct station_parameters *params)
9863#endif
9864{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309865 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009866 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9867 hdd_context_t *pHddCtx;
9868 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +05309869 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009870#ifdef FEATURE_WLAN_TDLS
9871 tCsrStaParams StaParams = { 0 };
9872 uint8_t isBufSta = 0;
9873 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +05309874 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009875#endif
9876 int ret;
9877
9878 ENTER();
9879
Anurag Chouhan6d760662016-02-20 16:05:43 +05309880 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009881 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009882 return -EINVAL;
9883 }
9884
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309885 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009886 TRACE_CODE_HDD_CHANGE_STATION,
9887 pAdapter->sessionId, params->listen_interval));
9888
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +05309889 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
9890 hdd_err("invalid session id: %d", pAdapter->sessionId);
9891 return -EINVAL;
9892 }
9893
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009894 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9895 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309896 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009897 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009898
9899 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9900
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309901 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009902
Krunal Sonib4326f22016-03-10 13:05:51 -08009903 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9904 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009905 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
9906 status =
9907 hdd_softap_change_sta_state(pAdapter,
9908 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -08009909 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009910
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309911 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009912 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009913 return -EINVAL;
9914 }
9915 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009916 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
9917 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009918#ifdef FEATURE_WLAN_TDLS
9919 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -07009920
9921 if (cds_is_sub_20_mhz_enabled()) {
9922 hdd_err("TDLS not allowed with sub 20 MHz");
9923 return -EINVAL;
9924 }
9925
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009926 StaParams.capability = params->capability;
9927 StaParams.uapsd_queues = params->uapsd_queues;
9928 StaParams.max_sp = params->max_sp;
9929
9930 /* Convert (first channel , number of channels) tuple to
9931 * the total list of channels. This goes with the assumption
9932 * that if the first channel is < 14, then the next channels
9933 * are an incremental of 1 else an incremental of 4 till the number
9934 * of channels.
9935 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009936 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009937 if (0 != params->supported_channels_len) {
9938 int i = 0, j = 0, k = 0, no_of_channels = 0;
9939 int num_unique_channels;
9940 int next;
9941 for (i = 0;
9942 i < params->supported_channels_len
9943 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
9944 int wifi_chan_index;
9945 if (!wlan_hdd_is_duplicate_channel
9946 (StaParams.supported_channels, j,
9947 params->supported_channels[i])) {
9948 StaParams.
9949 supported_channels[j] =
9950 params->
9951 supported_channels[i];
9952 } else {
9953 continue;
9954 }
9955 wifi_chan_index =
9956 ((StaParams.supported_channels[j] <=
9957 HDD_CHANNEL_14) ? 1 : 4);
9958 no_of_channels =
9959 params->supported_channels[i + 1];
9960
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009961 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 -08009962 StaParams.
9963 supported_channels[j],
9964 wifi_chan_index,
9965 no_of_channels);
9966 for (k = 1; k <= no_of_channels &&
9967 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
9968 k++) {
9969 next =
9970 StaParams.
9971 supported_channels[j] +
9972 wifi_chan_index;
9973 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
9974 StaParams.
9975 supported_channels[j
9976 +
9977 1]
9978 = next;
9979 } else {
9980 continue;
9981 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009982 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009983 j + 1,
9984 StaParams.
9985 supported_channels[j +
9986 1]);
9987 j += 1;
9988 }
9989 }
9990 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009991 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009992 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009993 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009994 StaParams.
9995 supported_channels[i]);
9996 }
9997 if (MAX_CHANNEL < num_unique_channels)
9998 num_unique_channels = MAX_CHANNEL;
9999 StaParams.supported_channels_len =
10000 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010001 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010002 StaParams.supported_channels_len);
10003 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010004 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010005 params->supported_oper_classes,
10006 params->supported_oper_classes_len);
10007 StaParams.supported_oper_classes_len =
10008 params->supported_oper_classes_len;
10009
10010 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010011 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010012 params->ext_capab,
10013 sizeof(StaParams.extn_capability));
10014
10015 if (NULL != params->ht_capa) {
10016 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010017 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010018 sizeof(tSirHTCap));
10019 }
10020
10021 StaParams.supported_rates_len =
10022 params->supported_rates_len;
10023
10024 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
10025 * The supported_rates array , for all the structures propogating till Add Sta
10026 * to the firmware has to be modified , if the supplicant (ieee80211) is
10027 * modified to send more rates.
10028 */
10029
10030 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
10031 */
10032 if (StaParams.supported_rates_len >
10033 SIR_MAC_MAX_SUPP_RATES)
10034 StaParams.supported_rates_len =
10035 SIR_MAC_MAX_SUPP_RATES;
10036
10037 if (0 != StaParams.supported_rates_len) {
10038 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010039 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010040 params->supported_rates,
10041 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010042 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010043 StaParams.supported_rates_len);
10044 for (i = 0; i < StaParams.supported_rates_len;
10045 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010046 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010047 StaParams.supported_rates[i]);
10048 }
10049
10050 if (NULL != params->vht_capa) {
10051 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010052 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010053 params->vht_capa,
10054 sizeof(tSirVHTCap));
10055 }
10056
10057 if (0 != params->ext_capab_len) {
10058 /*Define A Macro : TODO Sunil */
10059 if ((1 << 4) & StaParams.extn_capability[3]) {
10060 isBufSta = 1;
10061 }
10062 /* TDLS Channel Switching Support */
10063 if ((1 << 6) & StaParams.extn_capability[3]) {
10064 isOffChannelSupported = 1;
10065 }
10066 }
10067
Nitesh Shah99934ac2016-09-05 15:54:08 +053010068 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +053010069 (params->ht_capa || params->vht_capa ||
10070 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +053010071 is_qos_wmm_sta = true;
10072
10073 hdd_notice("%s: TDLS Peer is QOS capable"
10074 " is_qos_wmm_sta= %d HTcapPresent = %d",
10075 __func__, is_qos_wmm_sta,
10076 StaParams.htcap_present);
10077
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010078 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +053010079 &StaParams,
10080 isBufSta,
10081 isOffChannelSupported,
10082 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010083 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010084 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010085 return -EINVAL;
10086 }
10087
10088 status =
10089 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
10090 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010091 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010092 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010093 return -EINVAL;
10094 }
10095 }
10096#endif
10097 }
10098 EXIT();
10099 return ret;
10100}
10101
10102/**
10103 * wlan_hdd_change_station() - cfg80211 change station handler function
10104 * @wiphy: Pointer to the wiphy structure
10105 * @dev: Pointer to the net device.
10106 * @mac: bssid
10107 * @params: Pointer to station parameters
10108 *
10109 * This is the cfg80211 change station handler function which invokes
10110 * the internal function @__wlan_hdd_change_station with
10111 * SSR protection.
10112 *
10113 * Return: 0 for success, error number on failure.
10114 */
10115#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
10116static int wlan_hdd_change_station(struct wiphy *wiphy,
10117 struct net_device *dev,
10118 const u8 *mac,
10119 struct station_parameters *params)
10120#else
10121static int wlan_hdd_change_station(struct wiphy *wiphy,
10122 struct net_device *dev,
10123 u8 *mac,
10124 struct station_parameters *params)
10125#endif
10126{
10127 int ret;
10128
10129 cds_ssr_protect(__func__);
10130 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
10131 cds_ssr_unprotect(__func__);
10132
10133 return ret;
10134}
10135
10136/*
10137 * FUNCTION: __wlan_hdd_cfg80211_add_key
10138 * This function is used to initialize the key information
10139 */
10140static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10141 struct net_device *ndev,
10142 u8 key_index, bool pairwise,
10143 const u8 *mac_addr,
10144 struct key_params *params)
10145{
10146 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10147 tCsrRoamSetKey setKey;
10148 int status;
10149 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010150 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010151 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010152 hdd_context_t *pHddCtx;
10153 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10154
10155 ENTER();
10156
Anurag Chouhan6d760662016-02-20 16:05:43 +053010157 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010158 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010159 return -EINVAL;
10160 }
10161
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010162 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10163 hdd_err("invalid session id: %d", pAdapter->sessionId);
10164 return -EINVAL;
10165 }
10166
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010167 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010168 TRACE_CODE_HDD_CFG80211_ADD_KEY,
10169 pAdapter->sessionId, params->key_len));
10170 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10171 status = wlan_hdd_validate_context(pHddCtx);
10172
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010173 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010174 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010175
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010176 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010177 hdd_device_mode_to_string(pAdapter->device_mode),
10178 pAdapter->device_mode);
10179
10180 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010181 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010182
10183 return -EINVAL;
10184 }
10185
10186 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010187 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010188
10189 return -EINVAL;
10190 }
10191
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010192 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010193
10194 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010195 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010196 setKey.keyId = key_index;
10197 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010198 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010199
10200 switch (params->cipher) {
10201 case WLAN_CIPHER_SUITE_WEP40:
10202 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
10203 break;
10204
10205 case WLAN_CIPHER_SUITE_WEP104:
10206 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
10207 break;
10208
10209 case WLAN_CIPHER_SUITE_TKIP:
10210 {
10211 u8 *pKey = &setKey.Key[0];
10212 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
10213
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010214 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010215
10216 /*Supplicant sends the 32bytes key in this order
10217
10218 |--------------|----------|----------|
10219 | Tk1 |TX-MIC | RX Mic |
10220 |||--------------|----------|----------|
10221 <---16bytes---><--8bytes--><--8bytes-->
10222
10223 */
10224 /*Sme expects the 32 bytes key to be in the below order
10225
10226 |--------------|----------|----------|
10227 | Tk1 |RX-MIC | TX Mic |
10228 |||--------------|----------|----------|
10229 <---16bytes---><--8bytes--><--8bytes-->
10230 */
10231 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010232 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010233
10234 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010235 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010236
10237 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010238 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010239
10240 break;
10241 }
10242
10243 case WLAN_CIPHER_SUITE_CCMP:
10244 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
10245 break;
10246
10247#ifdef FEATURE_WLAN_WAPI
10248 case WLAN_CIPHER_SUITE_SMS4:
10249 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010250 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010251 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
10252 mac_addr, params->key,
10253 params->key_len);
10254 return 0;
10255 }
10256#endif
10257
10258#ifdef FEATURE_WLAN_ESE
10259 case WLAN_CIPHER_SUITE_KRK:
10260 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
10261 break;
10262#ifdef WLAN_FEATURE_ROAM_OFFLOAD
10263 case WLAN_CIPHER_SUITE_BTK:
10264 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
10265 break;
10266#endif
10267#endif
10268
10269#ifdef WLAN_FEATURE_11W
10270 case WLAN_CIPHER_SUITE_AES_CMAC:
10271 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
10272 break;
10273#endif
10274
10275 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010276 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010277 return -EOPNOTSUPP;
10278 }
10279
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010280 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010281
10282 if (!pairwise) {
10283 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010284 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010285 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010286 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010287 } else {
10288 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010289 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010290 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010291 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010292 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010293 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010294 /* if a key is already installed, block all subsequent ones */
10295 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010296 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010297 return 0;
10298 }
10299
10300 setKey.keyDirection = eSIR_TX_RX;
10301 /*Set the group key */
10302 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10303 pAdapter->sessionId, &setKey, &roamId);
10304
10305 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010306 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010307 return -EINVAL;
10308 }
10309 /*Save the keys here and call sme_roam_set_key for setting
10310 the PTK after peer joins the IBSS network */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010311 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010312 &setKey, sizeof(tCsrRoamSetKey));
10313
10314 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
10315 return status;
10316 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010317 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10318 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010319 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10320 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070010321 status = wlansap_set_key_sta(
10322 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010323 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010324 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010325 __LINE__, status);
10326 }
10327 }
10328
10329 /* Save the key in ap ctx for use on START_BASS and restart */
10330 if (pairwise ||
10331 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
10332 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010333 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010334 sizeof(tCsrRoamSetKey));
10335 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010336 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010337 sizeof(tCsrRoamSetKey));
10338
Krunal Sonib4326f22016-03-10 13:05:51 -080010339 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
10340 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010341 hdd_wext_state_t *pWextState =
10342 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10343 hdd_station_ctx_t *pHddStaCtx =
10344 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10345
10346 if (!pairwise) {
10347 /* set group key */
10348 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010349 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010350 __func__, __LINE__);
10351 hdd_perform_roam_set_key_complete(pAdapter);
10352 }
10353 }
10354
10355 pWextState->roamProfile.Keys.KeyLength[key_index] =
10356 (u8) params->key_len;
10357
10358 pWextState->roamProfile.Keys.defaultIndex = key_index;
10359
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010360 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010361 KeyMaterial[key_index][0], params->key,
10362 params->key_len);
10363
10364 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10365
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010366 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010367 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10368 setKey.keyDirection);
10369
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010370 /* The supplicant may attempt to set the PTK once pre-authentication
10371 is done. Save the key in the UMAC and include it in the ADD BSS
10372 request */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010373 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010374 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010375 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010376 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010377 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010378 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010379 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010380 return -EINVAL;
10381 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010382
10383 /* issue set key request to SME */
10384 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10385 pAdapter->sessionId, &setKey, &roamId);
10386
10387 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010388 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010389 pHddStaCtx->roam_info.roamingState =
10390 HDD_ROAM_STATE_NONE;
10391 return -EINVAL;
10392 }
10393
10394 /* in case of IBSS as there was no information available about WEP keys during
10395 * IBSS join, group key intialized with NULL key, so re-initialize group key
10396 * with correct value*/
10397 if ((eCSR_BSS_TYPE_START_IBSS ==
10398 pWextState->roamProfile.BSSType)
10399 &&
10400 !((IW_AUTH_KEY_MGMT_802_1X ==
10401 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
10402 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
10403 pHddStaCtx->conn_info.authType)
10404 )
10405 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
10406 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
10407 )
10408 ) {
10409 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010410 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010411
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010412 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010413 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10414 setKey.keyDirection);
10415
10416 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10417 pAdapter->sessionId, &setKey,
10418 &roamId);
10419
10420 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010421 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010422 pHddStaCtx->roam_info.roamingState =
10423 HDD_ROAM_STATE_NONE;
10424 return -EINVAL;
10425 }
10426 }
10427 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010428 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010429 return 0;
10430}
10431
10432static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10433 struct net_device *ndev,
10434 u8 key_index, bool pairwise,
10435 const u8 *mac_addr,
10436 struct key_params *params)
10437{
10438 int ret;
10439 cds_ssr_protect(__func__);
10440 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
10441 mac_addr, params);
10442 cds_ssr_unprotect(__func__);
10443
10444 return ret;
10445}
10446
10447/*
10448 * FUNCTION: __wlan_hdd_cfg80211_get_key
10449 * This function is used to get the key information
10450 */
10451static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10452 struct net_device *ndev,
10453 u8 key_index, bool pairwise,
10454 const u8 *mac_addr, void *cookie,
10455 void (*callback)(void *cookie,
10456 struct key_params *)
10457 )
10458{
10459 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10460 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10461 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
10462 struct key_params params;
10463
10464 ENTER();
10465
Anurag Chouhan6d760662016-02-20 16:05:43 +053010466 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010467 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010468 return -EINVAL;
10469 }
10470
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010471 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010472 hdd_device_mode_to_string(pAdapter->device_mode),
10473 pAdapter->device_mode);
10474
10475 memset(&params, 0, sizeof(params));
10476
10477 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010478 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010479 key_index);
10480 return -EINVAL;
10481 }
10482
10483 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
10484 case eCSR_ENCRYPT_TYPE_NONE:
10485 params.cipher = IW_AUTH_CIPHER_NONE;
10486 break;
10487
10488 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
10489 case eCSR_ENCRYPT_TYPE_WEP40:
10490 params.cipher = WLAN_CIPHER_SUITE_WEP40;
10491 break;
10492
10493 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
10494 case eCSR_ENCRYPT_TYPE_WEP104:
10495 params.cipher = WLAN_CIPHER_SUITE_WEP104;
10496 break;
10497
10498 case eCSR_ENCRYPT_TYPE_TKIP:
10499 params.cipher = WLAN_CIPHER_SUITE_TKIP;
10500 break;
10501
10502 case eCSR_ENCRYPT_TYPE_AES:
10503 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
10504 break;
10505
10506 default:
10507 params.cipher = IW_AUTH_CIPHER_NONE;
10508 break;
10509 }
10510
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010511 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010512 TRACE_CODE_HDD_CFG80211_GET_KEY,
10513 pAdapter->sessionId, params.cipher));
10514
10515 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
10516 params.seq_len = 0;
10517 params.seq = NULL;
10518 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
10519 callback(cookie, &params);
10520
10521 EXIT();
10522 return 0;
10523}
10524
10525static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10526 struct net_device *ndev,
10527 u8 key_index, bool pairwise,
10528 const u8 *mac_addr, void *cookie,
10529 void (*callback)(void *cookie,
10530 struct key_params *)
10531 )
10532{
10533 int ret;
10534
10535 cds_ssr_protect(__func__);
10536 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
10537 mac_addr, cookie, callback);
10538 cds_ssr_unprotect(__func__);
10539
10540 return ret;
10541}
10542
10543/**
10544 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
10545 * @wiphy: wiphy interface context
10546 * @ndev: pointer to net device
10547 * @key_index: Key index used in 802.11 frames
10548 * @unicast: true if it is unicast key
10549 * @multicast: true if it is multicast key
10550 *
10551 * This function is required for cfg80211_ops API.
10552 * It is used to delete the key information
10553 * Underlying hardware implementation does not have API to delete the
10554 * encryption key. It is automatically deleted when the peer is
10555 * removed. Hence this function currently does nothing.
10556 * Future implementation may interprete delete key operation to
10557 * replacing the key with a random junk value, effectively making it
10558 * useless.
10559 *
10560 * Return: status code, always 0.
10561 */
10562
10563static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10564 struct net_device *ndev,
10565 u8 key_index,
10566 bool pairwise, const u8 *mac_addr)
10567{
10568 EXIT();
10569 return 0;
10570}
10571
10572/**
10573 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
10574 * @wiphy: Pointer to wiphy structure.
10575 * @dev: Pointer to net_device structure.
10576 * @key_index: key index
10577 * @pairwise: pairwise
10578 * @mac_addr: mac address
10579 *
10580 * This is the cfg80211 delete key handler function which invokes
10581 * the internal function @__wlan_hdd_cfg80211_del_key with
10582 * SSR protection.
10583 *
10584 * Return: 0 for success, error number on failure.
10585 */
10586static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10587 struct net_device *dev,
10588 u8 key_index,
10589 bool pairwise, const u8 *mac_addr)
10590{
10591 int ret;
10592
10593 cds_ssr_protect(__func__);
10594 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
10595 pairwise, mac_addr);
10596 cds_ssr_unprotect(__func__);
10597
10598 return ret;
10599}
10600
10601/*
10602 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
10603 * This function is used to set the default tx key index
10604 */
10605static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10606 struct net_device *ndev,
10607 u8 key_index,
10608 bool unicast, bool multicast)
10609{
10610 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10611 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10612 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10613 hdd_context_t *pHddCtx;
10614 int status;
10615
10616 ENTER();
10617
Anurag Chouhan6d760662016-02-20 16:05:43 +053010618 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010619 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010620 return -EINVAL;
10621 }
10622
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053010623 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
10624 hdd_err("invalid session id: %d", pAdapter->sessionId);
10625 return -EINVAL;
10626 }
10627
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010628 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010629 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
10630 pAdapter->sessionId, key_index));
10631
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010632 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010633 hdd_device_mode_to_string(pAdapter->device_mode),
10634 pAdapter->device_mode, key_index);
10635
10636 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010637 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010638 return -EINVAL;
10639 }
10640
10641 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10642 status = wlan_hdd_validate_context(pHddCtx);
10643
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010644 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010645 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010646
Krunal Sonib4326f22016-03-10 13:05:51 -080010647 if ((pAdapter->device_mode == QDF_STA_MODE) ||
10648 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010649 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10650 pHddStaCtx->conn_info.ucEncryptionType) &&
10651 (eCSR_ENCRYPT_TYPE_AES !=
10652 pHddStaCtx->conn_info.ucEncryptionType)) {
10653 /* If default key index is not same as previous one,
10654 * then update the default key index */
10655
10656 tCsrRoamSetKey setKey;
10657 uint32_t roamId = 0xFF;
10658 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
10659
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010660 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010661
10662 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010663 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010664 setKey.keyId = key_index;
10665 setKey.keyLength = Keys->KeyLength[key_index];
10666
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010667 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010668 &Keys->KeyMaterial[key_index][0],
10669 Keys->KeyLength[key_index]);
10670
10671 setKey.keyDirection = eSIR_TX_RX;
10672
Anurag Chouhanc5548422016-02-24 18:33:27 +053010673 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010674 &pHddStaCtx->conn_info.bssId);
10675
10676 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
10677 pWextState->roamProfile.EncryptionType.
10678 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
10679 /* In the case of dynamic wep supplicant hardcodes DWEP type
10680 * to eCSR_ENCRYPT_TYPE_WEP104 even though ap is configured for
10681 * WEP-40 encryption. In this canse the key length is 5 but the
10682 * encryption type is 104 hence checking the key langht(5) and
10683 * encryption type(104) and switching encryption type to 40*/
10684 pWextState->roamProfile.EncryptionType.
10685 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10686 pWextState->roamProfile.mcEncryptionType.
10687 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10688 }
10689
10690 setKey.encType =
10691 pWextState->roamProfile.EncryptionType.
10692 encryptionType[0];
10693
10694 /* Issue set key request */
10695 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10696 pAdapter->sessionId, &setKey,
10697 &roamId);
10698
10699 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010700 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010701 status);
10702 return -EINVAL;
10703 }
10704 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010705 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010706 /* In SoftAp mode setting key direction for default mode */
10707 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10708 pWextState->roamProfile.EncryptionType.encryptionType[0])
10709 && (eCSR_ENCRYPT_TYPE_AES !=
10710 pWextState->roamProfile.EncryptionType.
10711 encryptionType[0])) {
10712 /* Saving key direction for default key index to TX default */
10713 hdd_ap_ctx_t *pAPCtx =
10714 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10715 pAPCtx->wepKey[key_index].keyDirection =
10716 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010717 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053010718 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010719 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010720 }
10721 }
10722
10723 EXIT();
10724 return status;
10725}
10726
10727static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10728 struct net_device *ndev,
10729 u8 key_index,
10730 bool unicast, bool multicast)
10731{
10732 int ret;
10733 cds_ssr_protect(__func__);
10734 ret =
10735 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
10736 multicast);
10737 cds_ssr_unprotect(__func__);
10738
10739 return ret;
10740}
10741
Abhishek Singhc9941602016-08-09 16:06:22 +053010742/*
10743 * wlan_hdd_cfg80211_get_bss :to get the bss from kernel cache.
10744 * @wiphy: wiphy pointer
10745 * @channel: channel of the BSS
10746 * @bssid: Bssid of BSS
10747 * @ssid: Ssid of the BSS
10748 * @ssid_len: ssid length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010749 *
Abhishek Singhc9941602016-08-09 16:06:22 +053010750 * Return: bss found in kernel cache
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010751 */
Abhishek Singhc9941602016-08-09 16:06:22 +053010752#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010753static
Abhishek Singhc9941602016-08-09 16:06:22 +053010754struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10755 struct ieee80211_channel *channel, const u8 *bssid,
10756 const u8 *ssid, size_t ssid_len)
10757{
10758 return cfg80211_get_bss(wiphy, channel, bssid,
10759 ssid,
10760 ssid_len,
10761 WLAN_CAPABILITY_ESS,
10762 WLAN_CAPABILITY_ESS);
10763}
10764#else
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010765static
Abhishek Singhc9941602016-08-09 16:06:22 +053010766struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10767 struct ieee80211_channel *channel, const u8 *bssid,
10768 const u8 *ssid, size_t ssid_len)
10769{
10770 return cfg80211_get_bss(wiphy, channel, bssid,
10771 ssid,
10772 ssid_len,
10773 IEEE80211_BSS_TYPE_ESS,
10774 IEEE80211_PRIVACY_ANY);
10775}
10776#endif
10777
10778
10779/*
10780 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
10781 * interface that BSS might have been lost.
10782 * @pAdapter: adaptor
10783 * @bssid: bssid which might have been lost
10784 *
10785 * Return: bss which is unlinked from kernel cache
10786 */
10787struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
10788 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010789{
10790 struct net_device *dev = pAdapter->dev;
10791 struct wireless_dev *wdev = dev->ieee80211_ptr;
10792 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010793 struct cfg80211_bss *bss = NULL;
10794
Abhishek Singhc9941602016-08-09 16:06:22 +053010795 bss = wlan_hdd_cfg80211_get_bss(wiphy, NULL, bssid,
10796 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010797 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010798 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010799 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053010800 hdd_info("cfg80211_unlink_bss called for BSSID "
10801 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010802 cfg80211_unlink_bss(wiphy, bss);
10803 }
10804 return bss;
10805}
10806
Abhishek Singhc9941602016-08-09 16:06:22 +053010807
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010808/**
10809 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
10810 * @pAdapter: Pointer to adapter
10811 * @bss_desc: Pointer to bss descriptor
10812 *
10813 * This function is used to inform the BSS details to nl80211 interface.
10814 *
10815 * Return: struct cfg80211_bss pointer
10816 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053010817struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
10818 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010819{
10820 /*
10821 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
10822 * already exists in bss data base of cfg80211 for that particular BSS
10823 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
10824 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
10825 * As of now there is no possibility to get the mgmt(probe response)
10826 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
10827 * and passing to cfg80211_inform_bss_frame.
10828 */
10829 struct net_device *dev = pAdapter->dev;
10830 struct wireless_dev *wdev = dev->ieee80211_ptr;
10831 struct wiphy *wiphy = wdev->wiphy;
10832 int chan_no = bss_desc->channelId;
10833#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10834 qcom_ie_age *qie_age = NULL;
10835 int ie_length =
10836 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
10837#else
10838 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
10839#endif
10840 const char *ie =
10841 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
10842 unsigned int freq;
10843 struct ieee80211_channel *chan;
10844 struct ieee80211_mgmt *mgmt = NULL;
10845 struct cfg80211_bss *bss_status = NULL;
10846 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
10847 int rssi = 0;
10848 hdd_context_t *pHddCtx;
10849 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010850 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010851 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010852
10853 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10854 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010855 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010856 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010857
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010858 cfg_param = pHddCtx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010859 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
10860 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010861 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010862 return NULL;
10863 }
10864
10865 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
10866
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010867 /* Android does not want the timestamp from the frame.
10868 Instead it wants a monotonic increasing value */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070010869 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010870 mgmt->u.probe_resp.timestamp =
10871 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010872
10873 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
10874 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
10875
10876#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10877 /* GPS Requirement: need age ie per entry. Using vendor specific. */
10878 /* Assuming this is the last IE, copy at the end */
10879 ie_length -= sizeof(qcom_ie_age);
10880 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
10881 qie_age->element_id = QCOM_VENDOR_IE_ID;
10882 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
10883 qie_age->oui_1 = QCOM_OUI1;
10884 qie_age->oui_2 = QCOM_OUI2;
10885 qie_age->oui_3 = QCOM_OUI3;
10886 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowri6acee342016-10-28 15:00:38 +053010887 /*
10888 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
10889 * all bss related timestamp is in units of ms. Due to this when scan
10890 * results are sent to lowi the scan age is high.To address this,
10891 * send age in units of 1/10 ms.
10892 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010893 qie_age->age =
Sarada Prasanna Garnayakb3e06a62016-11-14 20:48:39 +053010894 (uint32_t)(qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010895 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070010896 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
10897 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070010898 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
10899 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010900#endif
10901
10902 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
10903 if (bss_desc->fProbeRsp) {
10904 mgmt->frame_control |=
10905 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
10906 } else {
10907 mgmt->frame_control |=
10908 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
10909 }
10910
10911 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
Dustin Browna30892e2016-10-12 17:28:36 -070010912 (wiphy->bands[NL80211_BAND_2GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010913 freq =
10914 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070010915 NL80211_BAND_2GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010916 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
Dustin Browna30892e2016-10-12 17:28:36 -070010917 && (wiphy->bands[NL80211_BAND_5GHZ] != NULL)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010918 freq =
10919 ieee80211_channel_to_frequency(chan_no,
Dustin Browna30892e2016-10-12 17:28:36 -070010920 NL80211_BAND_5GHZ);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010921 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010922 hdd_err("Invalid chan_no %d", chan_no);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010923 kfree(mgmt);
10924 return NULL;
10925 }
10926
10927 chan = __ieee80211_get_channel(wiphy, freq);
10928 /* When the band is changed on the fly using the GUI, three things are done
10929 * 1. scan abort
10930 * 2. flush scan results from cache
10931 * 3. update the band with the new band user specified (refer to the
10932 * hdd_set_band_helper function) as part of the scan abort, message will be
10933 * queued to PE and we proceed with flushing and changinh the band.
10934 * PE will stop the scanning further and report back the results what ever
10935 * it had till now by calling the call back function.
10936 * if the time between update band and scandone call back is sufficient
10937 * enough the band change reflects in SME, SME validates the channels
10938 * and discards the channels correponding to previous band and calls back
10939 * with zero bss results. but if the time between band update and scan done
10940 * callback is very small then band change will not reflect in SME and SME
10941 * reports to HDD all the channels correponding to previous band.this is due
10942 * to race condition.but those channels are invalid to the new band and so
10943 * this function __ieee80211_get_channel will return NULL.Each time we
10944 * report scan result with this pointer null warning kernel trace is printed.
10945 * if the scan results contain large number of APs continuosly kernel
10946 * warning trace is printed and it will lead to apps watch dog bark.
10947 * So drop the bss and continue to next bss.
10948 */
10949 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053010950 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
10951 chan_no, freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010952 kfree(mgmt);
10953 return NULL;
10954 }
10955
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010956 /* Based on .ini configuration, raw rssi can be reported for bss.
10957 * Raw rssi is typically used for estimating power.
10958 */
10959
10960 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
10961 bss_desc->rssi;
10962
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010963 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053010964 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010965
SaidiReddy Yenuga1fa40972016-11-15 13:44:15 +053010966 hdd_log(LOG1, "BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010967 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070010968 (int)(rssi / 100),
10969 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010970
10971 bss_status =
10972 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
10973 GFP_KERNEL);
10974 kfree(mgmt);
10975 return bss_status;
10976}
10977
10978/**
10979 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
10980 * @pAdapter: Pointer to adapter
10981 * @pRoamInfo: Pointer to roam info
10982 *
10983 * This function is used to update the BSS data base of CFG8011
10984 *
10985 * Return: struct cfg80211_bss pointer
10986 */
10987struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
10988 tCsrRoamInfo *pRoamInfo)
10989{
10990 tCsrRoamConnectedProfile roamProfile;
10991 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10992 struct cfg80211_bss *bss = NULL;
10993
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010994 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
10995 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
10996
10997 if (NULL != roamProfile.pBssDesc) {
10998 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10999 roamProfile.pBssDesc);
11000
11001 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011002 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011003
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080011004 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011005 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011006 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011007 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011008 return bss;
11009}
11010/**
11011 * wlan_hdd_cfg80211_update_bss() - update bss
11012 * @wiphy: Pointer to wiphy
11013 * @pAdapter: Pointer to adapter
11014 * @scan_time: scan request timestamp
11015 *
11016 * Return: zero if success, non-zero otherwise
11017 */
11018int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
11019 hdd_adapter_t *pAdapter,
11020 uint32_t scan_time)
11021{
11022 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
11023 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011024 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011025 tScanResultHandle pResult;
11026 struct cfg80211_bss *bss_status = NULL;
11027 hdd_context_t *pHddCtx;
11028 int ret;
11029
11030 ENTER();
11031
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053011032 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
11033 hdd_err("invalid session id: %d", pAdapter->sessionId);
11034 return -EINVAL;
11035 }
11036
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011037 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011038 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
11039 NO_SESSION, pAdapter->sessionId));
11040
11041 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11042 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011043 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011044 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011045
11046 /* start getting scan results and populate cgf80211 BSS database */
11047 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
11048
11049 /* no scan results */
11050 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011051 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053011052 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011053 }
11054
11055 pScanResult = sme_scan_result_get_first(hHal, pResult);
11056
11057 while (pScanResult) {
11058 /*
11059 * - cfg80211_inform_bss() is not updating ie field of bss
11060 * entry if entry already exists in bss data base of cfg80211
11061 * for that particular BSS ID. Using cfg80211_inform_bss_frame
11062 * to update thebss entry instead of cfg80211_inform_bss,
11063 * But this call expects mgmt packet as input. As of now
11064 * there is no possibility to get the mgmt(probe response)
11065 * frame from PE, converting bss_desc to
11066 * ieee80211_mgmt(probe response) and passing to c
11067 * fg80211_inform_bss_frame.
11068 * - Update BSS only if beacon timestamp is later than
11069 * scan request timestamp.
11070 */
11071 if ((scan_time == 0) ||
11072 (scan_time <
Deepthi Gowri6acee342016-10-28 15:00:38 +053011073 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011074 bss_status =
11075 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
11076 &pScanResult->BssDescriptor);
11077
11078 if (NULL == bss_status) {
11079 hdd_info("NULL returned by cfg80211_inform_bss_frame");
11080 } else {
11081 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011082 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011083 bss_status);
11084 }
11085 } else {
11086 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
11087 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
11088 }
11089 pScanResult = sme_scan_result_get_next(hHal, pResult);
11090 }
11091
11092 sme_scan_result_purge(hHal, pResult);
11093 /*
11094 * For SAP mode, scan is invoked by hostapd during SAP start
11095 * if hostapd is restarted, we need to flush previous scan
11096 * result so that it will reflect environment change
11097 */
Krunal Sonib4326f22016-03-10 13:05:51 -080011098 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011099#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
11100 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
11101#endif
11102 )
11103 sme_scan_flush_result(hHal);
11104
11105 EXIT();
11106 return 0;
11107}
11108
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011109/**
11110 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
11111 * @pAdapter: Pointer to adapter
11112 * @pRoamInfo: Pointer to roam info
11113 * @index: Index
11114 * @preauth: Preauth flag
11115 *
11116 * This function is used to notify the supplicant of a new PMKSA candidate.
11117 *
11118 * Return: 0 for success, non-zero for failure
11119 */
11120int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
11121 tCsrRoamInfo *pRoamInfo,
11122 int index, bool preauth)
11123{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011124 struct net_device *dev = pAdapter->dev;
11125 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
11126
11127 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011128 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011129
11130 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011131 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011132 return -EINVAL;
11133 }
11134
11135 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011136 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011137 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
11138 cfg80211_pmksa_candidate_notify(dev, index,
11139 pRoamInfo->bssid.bytes,
11140 preauth, GFP_KERNEL);
11141 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011142 return 0;
11143}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011144
11145#ifdef FEATURE_WLAN_LFR_METRICS
11146/**
11147 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
11148 * @pAdapter: Pointer to adapter
11149 * @pRoamInfo: Pointer to roam info
11150 *
11151 * 802.11r/LFR metrics reporting function to report preauth initiation
11152 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011153 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011154 */
11155#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011156QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011157 tCsrRoamInfo *pRoamInfo)
11158{
11159 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11160 union iwreq_data wrqu;
11161
11162 ENTER();
11163
11164 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011165 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011166 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011167 }
11168
11169 /* create the event */
11170 memset(&wrqu, 0, sizeof(wrqu));
11171 memset(metrics_notification, 0, sizeof(metrics_notification));
11172
11173 wrqu.data.pointer = metrics_notification;
11174 wrqu.data.length = scnprintf(metrics_notification,
11175 sizeof(metrics_notification),
11176 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
11177 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11178
11179 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11180 metrics_notification);
11181
11182 EXIT();
11183
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011184 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011185}
11186
11187/**
11188 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11189 * @pAdapter: Pointer to adapter
11190 * @pRoamInfo: Pointer to roam info
11191 * @preauth_status: Preauth status
11192 *
11193 * 802.11r/LFR metrics reporting function to report handover initiation
11194 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011195 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011196 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011197QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011198wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
11199 tCsrRoamInfo *pRoamInfo,
11200 bool preauth_status)
11201{
11202 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11203 union iwreq_data wrqu;
11204
11205 ENTER();
11206
11207 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011208 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011209 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011210 }
11211
11212 /* create the event */
11213 memset(&wrqu, 0, sizeof(wrqu));
11214 memset(metrics_notification, 0, sizeof(metrics_notification));
11215
11216 scnprintf(metrics_notification, sizeof(metrics_notification),
11217 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
11218 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11219
11220 if (1 == preauth_status)
11221 strlcat(metrics_notification, " true",
11222 sizeof(metrics_notification));
11223 else
11224 strlcat(metrics_notification, " false",
11225 sizeof(metrics_notification));
11226
11227 wrqu.data.pointer = metrics_notification;
11228 wrqu.data.length = strlen(metrics_notification);
11229
11230 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11231 metrics_notification);
11232
11233 EXIT();
11234
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011235 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011236}
11237
11238/**
11239 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11240 * @pAdapter: Pointer to adapter
11241 * @pRoamInfo: Pointer to roam info
11242 *
11243 * 802.11r/LFR metrics reporting function to report handover initiation
11244 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011245 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011246 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011247QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011248 tCsrRoamInfo *pRoamInfo)
11249{
11250 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11251 union iwreq_data wrqu;
11252
11253 ENTER();
11254
11255 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011256 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011257 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011258 }
11259
11260 /* create the event */
11261 memset(&wrqu, 0, sizeof(wrqu));
11262 memset(metrics_notification, 0, sizeof(metrics_notification));
11263
11264 wrqu.data.pointer = metrics_notification;
11265 wrqu.data.length = scnprintf(metrics_notification,
11266 sizeof(metrics_notification),
11267 "QCOM: LFR_PREAUTH_HANDOVER "
11268 MAC_ADDRESS_STR,
11269 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11270
11271 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11272 metrics_notification);
11273
11274 EXIT();
11275
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011276 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011277}
11278#endif
11279
11280/**
11281 * hdd_select_cbmode() - select channel bonding mode
11282 * @pAdapter: Pointer to adapter
11283 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011284 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011285 *
11286 * Return: none
11287 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011288void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
11289 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011290{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011291 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011292 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011293 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011294
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011295 /*
11296 * CDS api expects secondary channel for calculating
11297 * the channel params
11298 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011299 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011300 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
11301 if (operationChannel >= 1 && operationChannel <= 5)
11302 sec_ch = operationChannel + 4;
11303 else if (operationChannel >= 6 && operationChannel <= 13)
11304 sec_ch = operationChannel - 4;
11305 }
11306
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011307 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011308 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011309
11310 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011311 eHddDot11Mode hdd_dot11_mode;
11312 uint8_t iniDot11Mode =
11313 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
11314
11315 hdd_notice("Dot11Mode is %u", iniDot11Mode);
11316 switch (iniDot11Mode) {
11317 case eHDD_DOT11_MODE_AUTO:
11318 case eHDD_DOT11_MODE_11ac:
11319 case eHDD_DOT11_MODE_11ac_ONLY:
11320 if (sme_is_feature_supported_by_fw(DOT11AC))
11321 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
11322 else
11323 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11324 break;
11325 case eHDD_DOT11_MODE_11n:
11326 case eHDD_DOT11_MODE_11n_ONLY:
11327 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11328 break;
11329 default:
11330 hdd_dot11_mode = iniDot11Mode;
11331 break;
11332 }
11333 ch_info->channel_width = ch_params->ch_width;
11334 ch_info->phy_mode =
11335 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011336 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011337 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011338 hdd_info("ch_info width %d, phymode %d channel %d",
11339 ch_info->channel_width, ch_info->phy_mode,
11340 ch_info->channel);
11341 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011342}
11343
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011344/**
11345 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
11346 * @adapter: STA adapter
11347 * @roam_profile: STA roam profile
11348 *
11349 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
11350 *
11351 * Return: false if sta-sap conc is not allowed, else return true
11352 */
11353static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
11354 tCsrRoamProfile *roam_profile)
11355{
11356 hdd_context_t *hdd_ctx;
11357 hdd_adapter_t *ap_adapter;
11358 hdd_ap_ctx_t *hdd_ap_ctx;
11359 hdd_hostapd_state_t *hostapd_state;
11360 uint8_t channel = 0;
11361 QDF_STATUS status;
11362
11363 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11364 if (!hdd_ctx) {
11365 hdd_err("HDD context is NULL");
11366 return true;
11367 }
11368
11369 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
11370 /* probably no sap running, no handling required */
11371 if (ap_adapter == NULL)
11372 return true;
11373
11374 /*
11375 * sap is not in started state, so it is fine to go ahead with sta.
11376 * if sap is currently doing CAC then don't allow sta to go further.
11377 */
11378 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
11379 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
11380 return true;
11381
11382 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
11383 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
11384 return false;
11385 }
11386
11387 /*
11388 * log and return error, if we allow STA to go through, we don't
11389 * know what is going to happen better stop sta connection
11390 */
11391 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
11392 if (NULL == hdd_ap_ctx) {
11393 hdd_err("AP context not found");
11394 return false;
11395 }
11396
11397 /* sap is on non-dfs channel, nothing to handle */
11398 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
11399 hdd_info("sap is on non-dfs channel, sta is allowed");
11400 return true;
11401 }
11402 /*
11403 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053011404 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011405 */
11406 status = cds_get_channel_from_scan_result(adapter,
11407 roam_profile, &channel);
11408
Nitesh Shah59774522016-09-16 15:14:21 +053011409 /*
11410 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
11411 * channels for roaming case.
11412 */
11413 if (CDS_IS_CHANNEL_24GHZ(channel)) {
11414 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
11415 return true;
11416 }
11417
11418 /*
11419 * If channel is 0 or DFS then better to call pcl and find out the
11420 * best channel. If channel is non-dfs 5 GHz then better move SAP
11421 * to STA's channel to make scc, so we have room for 3port MCC
11422 * scenario.
11423 */
11424 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011425 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
11426 true);
11427
11428 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
11429 qdf_event_reset(&hostapd_state->qdf_event);
11430 status = wlansap_set_channel_change_with_csa(
11431 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
11432 hdd_ap_ctx->sapConfig.ch_width_orig);
11433
11434 if (QDF_STATUS_SUCCESS != status) {
11435 hdd_err("Set channel with CSA IE failed, can't allow STA");
11436 return false;
11437 }
11438
11439 /*
11440 * wait here for SAP to finish the channel switch. When channel
11441 * switch happens, SAP sends few beacons with CSA_IE. After
11442 * successfully Transmission of those beacons, it will move its
11443 * state from started to disconnected and move to new channel.
11444 * once it moves to new channel, sap again moves its state
11445 * machine from disconnected to started and set this event.
11446 * wait for 10 secs to finish this.
11447 */
11448 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
11449 if (!QDF_IS_STATUS_SUCCESS(status)) {
11450 hdd_err("wait for qdf_event failed, STA not allowed!!");
11451 return false;
11452 }
11453
11454 return true;
11455}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011456
Krunal Soni31949422016-07-29 17:17:53 -070011457/**
11458 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011459 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070011460 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011461 * @ssid_len: Length of ssid
11462 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070011463 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011464 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011465 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011466 *
11467 * This function is used to start the association process
11468 *
11469 * Return: 0 for success, non-zero for failure
11470 */
Krunal Soni31949422016-07-29 17:17:53 -070011471static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011472 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070011473 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011474 u8 operatingChannel,
11475 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011476{
11477 int status = 0;
11478 hdd_wext_state_t *pWextState;
11479 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011480 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011481 uint32_t roamId;
11482 tCsrRoamProfile *pRoamProfile;
11483 eCsrAuthType RSNAuthType;
11484 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053011485 uint8_t channel = 0;
11486 struct sir_hw_mode_params hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011487
11488 ENTER();
11489
11490 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11491 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011492 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011493
11494 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011495 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011496 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011497
11498 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011499 hdd_err("wrong SSID len");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011500 return -EINVAL;
11501 }
11502
11503 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053011504 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
11505 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011506
11507 if (pRoamProfile) {
11508 hdd_station_ctx_t *pHddStaCtx;
11509 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11510
11511 if (HDD_WMM_USER_MODE_NO_QOS ==
11512 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
11513 /*QoS not enabled in cfg file */
11514 pRoamProfile->uapsd_mask = 0;
11515 } else {
11516 /*QoS enabled, update uapsd mask from cfg file */
11517 pRoamProfile->uapsd_mask =
11518 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
11519 }
11520
11521 pRoamProfile->SSIDs.numOfSSIDs = 1;
11522 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011523 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011524 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011525 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011526 ssid, ssid_len);
11527
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011528 pRoamProfile->do_not_roam = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011529 if (bssid) {
11530 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011531 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011532 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011533 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011534 /*
11535 * Save BSSID in seperate variable as
11536 * pRoamProfile's BSSID is getting zeroed out in the
11537 * association process. In case of join failure
11538 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011539 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011540 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011541 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011542 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011543 } else if (bssid_hint) {
11544 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011545 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011546 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011547 /*
11548 * Save BSSID in a separate variable as
11549 * pRoamProfile's BSSID is getting zeroed out in the
11550 * association process. In case of join failure
11551 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011552 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011553 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011554 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011555 hdd_info("bssid_hint is given by upper layer %pM",
11556 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011557 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011558 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011559 QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011560 hdd_info("no bssid given by upper layer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011561 }
11562
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011563 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011564 pRoamProfile->SSIDs.SSIDList->SSID.length,
11565 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
11566 operatingChannel);
11567
11568 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
11569 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011570 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011571 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
11572 }
11573#ifdef FEATURE_WLAN_WAPI
11574 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011575 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011576 switch (pAdapter->wapi_info.wapiAuthMode) {
11577 case WAPI_AUTH_MODE_PSK:
11578 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011579 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011580 pAdapter->wapi_info.wapiAuthMode);
11581 pRoamProfile->AuthType.authType[0] =
11582 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
11583 break;
11584 }
11585 case WAPI_AUTH_MODE_CERT:
11586 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011587 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011588 pAdapter->wapi_info.wapiAuthMode);
11589 pRoamProfile->AuthType.authType[0] =
11590 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
11591 break;
11592 }
11593 } /* End of switch */
11594 if (pAdapter->wapi_info.wapiAuthMode ==
11595 WAPI_AUTH_MODE_PSK
11596 || pAdapter->wapi_info.wapiAuthMode ==
11597 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011598 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011599 pRoamProfile->AuthType.numEntries = 1;
11600 pRoamProfile->EncryptionType.numEntries = 1;
11601 pRoamProfile->EncryptionType.encryptionType[0] =
11602 eCSR_ENCRYPT_TYPE_WPI;
11603 pRoamProfile->mcEncryptionType.numEntries = 1;
11604 pRoamProfile->mcEncryptionType.
11605 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
11606 }
11607 }
Krunal Soni31949422016-07-29 17:17:53 -070011608#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011609#ifdef WLAN_FEATURE_GTK_OFFLOAD
11610 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080011611 if ((QDF_STA_MODE == pAdapter->device_mode) ||
11612 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011613 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
11614 sizeof(tSirGtkOffloadParams));
11615 pHddStaCtx->gtkOffloadReqParams.ulFlags =
11616 GTK_OFFLOAD_DISABLE;
11617 }
11618#endif
11619 pRoamProfile->csrPersona = pAdapter->device_mode;
11620
11621 if (operatingChannel) {
11622 pRoamProfile->ChannelInfo.ChannelList =
11623 &operatingChannel;
11624 pRoamProfile->ChannelInfo.numOfChannels = 1;
11625 } else {
11626 pRoamProfile->ChannelInfo.ChannelList = NULL;
11627 pRoamProfile->ChannelInfo.numOfChannels = 0;
11628 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011629 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011630 && operatingChannel) {
11631 /*
11632 * Need to post the IBSS power save parameters
11633 * to WMA. WMA will configure this parameters
11634 * to firmware if power save is enabled by the
11635 * firmware.
11636 */
11637 status = hdd_set_ibss_power_save_params(pAdapter);
11638
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011639 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011640 hdd_err("Set IBSS Power Save Params Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011641 return -EINVAL;
11642 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011643 pRoamProfile->ch_params.ch_width =
11644 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053011645 /*
11646 * In IBSS mode while operating in 2.4 GHz,
11647 * the device supports only 20 MHz.
11648 */
11649 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
11650 pRoamProfile->ch_params.ch_width =
11651 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011652 hdd_select_cbmode(pAdapter, operatingChannel,
11653 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011654 }
Abhishek Singh99bce862016-06-20 15:10:51 +053011655 /*
11656 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
11657 * or pmf=2 is an explicit configuration in the supplicant
11658 * configuration, drop the connection request.
11659 */
11660 if (pWextState->roamProfile.MFPEnabled &&
11661 !(pWextState->roamProfile.MFPRequired ||
11662 pWextState->roamProfile.MFPCapable)) {
11663 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
11664 pWextState->roamProfile.MFPEnabled,
11665 pWextState->roamProfile.MFPRequired,
11666 pWextState->roamProfile.MFPCapable);
11667 return -EINVAL;
11668 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011669
Krunal Soni3091bcc2016-06-23 12:28:21 -070011670 if (true == cds_is_connection_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011671 hdd_err("Connection refused: conn in progress");
11672 return -EINVAL;
11673 }
11674
Krunal Soni31949422016-07-29 17:17:53 -070011675 /*
11676 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011677 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070011678 * enhancements, the supplicant is not issuing the scan command
11679 * now. So the unicast frames which are sent from the host are
11680 * not having the additional IEs. If it is P2P CLIENT and there
11681 * is no additional IE present in roamProfile, then use the
11682 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011683 */
11684
Krunal Sonib4326f22016-03-10 13:05:51 -080011685 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011686 (!pRoamProfile->pAddIEScan)) {
11687 pRoamProfile->pAddIEScan =
11688 &pAdapter->scan_info.scanAddIE.addIEdata[0];
11689 pRoamProfile->nAddIEScanLength =
11690 pAdapter->scan_info.scanAddIE.length;
11691 }
11692 /*
11693 * When policy manager is enabled from ini file, we shouldn't
11694 * check for other concurrency rules.
11695 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070011696 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080011697 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011698 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011699 pAdapter, pRoamProfile, &roamId))
11700 return 0;
11701 }
11702
Krunal Soni3091bcc2016-06-23 12:28:21 -070011703 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011704 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
11705 pRoamProfile))) {
11706 hdd_err("sap-sta conc will fail, can't allow sta");
11707 hdd_conn_set_connection_state(pAdapter,
11708 eConnectionState_NotConnected);
11709 return -ENOMEM;
11710 }
11711
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011712 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011713 if (!sme_config) {
11714 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011715 hdd_conn_set_connection_state(pAdapter,
11716 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011717 return -ENOMEM;
11718 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011719 sme_get_config_param(pHddCtx->hHal, sme_config);
11720 /* These values are not sessionized. So, any change in these SME
11721 * configs on an older or parallel interface will affect the
11722 * cb mode. So, restoring the default INI params before starting
11723 * interfaces such as sta, cli etc.,
11724 */
11725 sme_config->csrConfig.channelBondingMode5GHz =
11726 pHddCtx->config->nChannelBondingMode5GHz;
11727 sme_config->csrConfig.channelBondingMode24GHz =
11728 pHddCtx->config->nChannelBondingMode24GHz;
11729 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011730 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053011731 /*
11732 * Change conn_state to connecting before sme_roam_connect(),
11733 * because sme_roam_connect() has a direct path to call
11734 * hdd_sme_roam_callback(), which will change the conn_state
11735 * If direct path, conn_state will be accordingly changed to
11736 * NotConnected or Associated by either
11737 * hdd_association_completion_handler() or
11738 * hdd_dis_connect_handler() in sme_RoamCallback()if
11739 * sme_RomConnect is to be queued,
11740 * Connecting state will remain until it is completed.
11741 *
11742 * If connection state is not changed, connection state will
11743 * remain in eConnectionState_NotConnected state.
11744 * In hdd_association_completion_handler, "hddDisconInProgress"
11745 * is set to true if conn state is
11746 * eConnectionState_NotConnected.
11747 * If "hddDisconInProgress" is set to true then cfg80211 layer
11748 * is not informed of connect result indication which
11749 * is an issue.
11750 */
11751 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053011752 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053011753 hdd_conn_set_connection_state(pAdapter,
11754 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011755
Komal Seelama89be8d2016-09-29 11:09:26 +053011756 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
11757 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011758 status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
11759 pAdapter->sessionId, pRoamProfile,
11760 &roamId);
11761
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011762 if ((QDF_STATUS_SUCCESS != status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080011763 (QDF_STA_MODE == pAdapter->device_mode ||
11764 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011765 hdd_err("sme_roam_connect (session %d) failed with "
11766 "status %d. -> NotConnected",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011767 pAdapter->sessionId, status);
11768 /* change back to NotAssociated */
11769 hdd_conn_set_connection_state(pAdapter,
11770 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053011771 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
11772 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011773 }
11774
11775 pRoamProfile->ChannelInfo.ChannelList = NULL;
11776 pRoamProfile->ChannelInfo.numOfChannels = 0;
11777
Nitesh Shah044fd672016-10-13 18:53:25 +053011778 if (!QDF_IS_STATUS_SUCCESS(
11779 wma_get_current_hw_mode(&hw_mode))) {
11780 hdd_err("wma_get_current_hw_mode failed");
11781 return status;
11782 }
11783
11784 if ((QDF_STA_MODE == pAdapter->device_mode)
11785 && hw_mode.dbs_cap) {
11786 cds_get_channel_from_scan_result(pAdapter,
11787 pRoamProfile, &channel);
11788 if (channel)
11789 cds_checkn_update_hw_mode_single_mac_mode
11790 (channel);
11791 }
11792
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011793 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011794 hdd_err("No valid Roam profile");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011795 return -EINVAL;
11796 }
11797 EXIT();
11798 return status;
11799}
11800
11801/**
11802 * wlan_hdd_cfg80211_set_auth_type() - set auth type
11803 * @pAdapter: Pointer to adapter
11804 * @auth_type: Auth type
11805 *
11806 * This function is used to set the authentication type (OPEN/SHARED).
11807 *
11808 * Return: 0 for success, non-zero for failure
11809 */
11810static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
11811 enum nl80211_auth_type auth_type)
11812{
11813 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11814 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11815
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011816 /*set authentication type */
11817 switch (auth_type) {
11818 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011819 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011820 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
11821 break;
11822
11823 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011824 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011825 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011826 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
11827 break;
11828
11829 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011830 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011831 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
11832 break;
11833#ifdef FEATURE_WLAN_ESE
11834 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011835 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011836 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
11837 break;
11838#endif
11839
11840 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011841 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011842 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
11843 return -EINVAL;
11844 }
11845
11846 pWextState->roamProfile.AuthType.authType[0] =
11847 pHddStaCtx->conn_info.authType;
11848 return 0;
11849}
11850
11851/**
11852 * wlan_hdd_set_akm_suite() - set key management type
11853 * @pAdapter: Pointer to adapter
11854 * @key_mgmt: Key management type
11855 *
11856 * This function is used to set the key mgmt type(PSK/8021x).
11857 *
11858 * Return: 0 for success, non-zero for failure
11859 */
11860static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
11861{
11862 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11863
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011864#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
11865#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
11866 /*set key mgmt type */
11867 switch (key_mgmt) {
11868 case WLAN_AKM_SUITE_PSK:
11869 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011870 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011871 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011872 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
11873 break;
11874
11875 case WLAN_AKM_SUITE_8021X_SHA256:
11876 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011877 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011878 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011879 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11880 break;
11881#ifdef FEATURE_WLAN_ESE
11882#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
11883#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
11884 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011885 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011886 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
11887 break;
11888#endif
11889#ifndef WLAN_AKM_SUITE_OSEN
11890#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
11891#endif
11892 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011893 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011894 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11895 break;
11896
11897 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011898 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011899 return -EINVAL;
11900
11901 }
11902 return 0;
11903}
11904
11905/**
11906 * wlan_hdd_cfg80211_set_cipher() - set encryption type
11907 * @pAdapter: Pointer to adapter
11908 * @cipher: Cipher type
11909 * @ucast: Unicast flag
11910 *
11911 * This function is used to set the encryption type
11912 * (NONE/WEP40/WEP104/TKIP/CCMP).
11913 *
11914 * Return: 0 for success, non-zero for failure
11915 */
11916static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
11917 u32 cipher, bool ucast)
11918{
11919 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11920 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11921 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11922
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011923 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080011924 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011925 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11926 } else {
11927
11928 /*set encryption method */
11929 switch (cipher) {
11930 case IW_AUTH_CIPHER_NONE:
11931 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11932 break;
11933
11934 case WLAN_CIPHER_SUITE_WEP40:
11935 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
11936 break;
11937
11938 case WLAN_CIPHER_SUITE_WEP104:
11939 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
11940 break;
11941
11942 case WLAN_CIPHER_SUITE_TKIP:
11943 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
11944 break;
11945
11946 case WLAN_CIPHER_SUITE_CCMP:
11947 encryptionType = eCSR_ENCRYPT_TYPE_AES;
11948 break;
11949#ifdef FEATURE_WLAN_WAPI
11950 case WLAN_CIPHER_SUITE_SMS4:
11951 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
11952 break;
11953#endif
11954
11955#ifdef FEATURE_WLAN_ESE
11956 case WLAN_CIPHER_SUITE_KRK:
11957 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
11958 break;
11959#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11960 case WLAN_CIPHER_SUITE_BTK:
11961 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
11962 break;
11963#endif
11964#endif
11965 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011966 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011967 return -EOPNOTSUPP;
11968 }
11969 }
11970
11971 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011972 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011973 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
11974 pWextState->roamProfile.EncryptionType.numEntries = 1;
11975 pWextState->roamProfile.EncryptionType.encryptionType[0] =
11976 encryptionType;
11977 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011978 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011979 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
11980 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
11981 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
11982 encryptionType;
11983 }
11984
11985 return 0;
11986}
11987
11988/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011989 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
11990 * @wext_state: Pointer to wext state
11991 * @gen_ie: Pointer to IE data
11992 * @len: length of IE data
11993 *
11994 * Return: 0 for success, non-zero for failure
11995 */
11996static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
11997 const uint8_t *gen_ie, uint16_t len)
11998{
11999 uint16_t cur_add_ie_len =
12000 wext_state->assocAddIE.length;
12001
12002 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12003 (wext_state->assocAddIE.length + len)) {
12004 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
12005 QDF_ASSERT(0);
12006 return -ENOMEM;
12007 }
12008 memcpy(wext_state->assocAddIE.addIEdata +
12009 cur_add_ie_len, gen_ie, len);
12010 wext_state->assocAddIE.length += len;
12011
12012 wext_state->roamProfile.pAddIEAssoc =
12013 wext_state->assocAddIE.addIEdata;
12014 wext_state->roamProfile.nAddIEAssocLength =
12015 wext_state->assocAddIE.length;
12016 return 0;
12017}
12018
12019/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012020 * wlan_hdd_cfg80211_set_ie() - set IEs
12021 * @pAdapter: Pointer to adapter
12022 * @ie: Pointer ot ie
12023 * @ie: IE length
12024 *
12025 * Return: 0 for success, non-zero for failure
12026 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012027static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012028 size_t ie_len)
12029{
12030 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12031 const uint8_t *genie = ie;
12032 uint16_t remLen = ie_len;
12033#ifdef FEATURE_WLAN_WAPI
12034 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
12035 u16 *tmp;
12036 uint16_t akmsuiteCount;
12037 int *akmlist;
12038#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012039 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012040
12041 /* clear previous assocAddIE */
12042 pWextState->assocAddIE.length = 0;
12043 pWextState->roamProfile.bWPSAssociation = false;
12044 pWextState->roamProfile.bOSENAssociation = false;
12045
12046 while (remLen >= 2) {
12047 uint16_t eLen = 0;
12048 uint8_t elementId;
12049 elementId = *genie++;
12050 eLen = *genie++;
12051 remLen -= 2;
12052
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012053 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012054
12055 switch (elementId) {
12056 case DOT11F_EID_WPA:
12057 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 -070012058 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012059 return -EINVAL;
12060 } else if (0 ==
12061 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
12062 uint16_t curAddIELen =
12063 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012064 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012065
12066 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12067 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012068 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012069 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012070 return -ENOMEM;
12071 }
12072 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
12073 memcpy(pWextState->assocAddIE.addIEdata +
12074 curAddIELen, genie - 2, eLen + 2);
12075 pWextState->assocAddIE.length += eLen + 2;
12076
12077 pWextState->roamProfile.bWPSAssociation = true;
12078 pWextState->roamProfile.pAddIEAssoc =
12079 pWextState->assocAddIE.addIEdata;
12080 pWextState->roamProfile.nAddIEAssocLength =
12081 pWextState->assocAddIE.length;
12082 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012083 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012084 memset(pWextState->WPARSNIE, 0,
12085 MAX_WPA_RSN_IE_LEN);
12086 memcpy(pWextState->WPARSNIE, genie - 2,
12087 (eLen + 2));
12088 pWextState->roamProfile.pWPAReqIE =
12089 pWextState->WPARSNIE;
12090 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
12091 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
12092 P2P_OUI_TYPE_SIZE))) {
12093 uint16_t curAddIELen =
12094 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012095 hdd_notice("Set P2P 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 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
12104 memcpy(pWextState->assocAddIE.addIEdata +
12105 curAddIELen, genie - 2, eLen + 2);
12106 pWextState->assocAddIE.length += eLen + 2;
12107
12108 pWextState->roamProfile.pAddIEAssoc =
12109 pWextState->assocAddIE.addIEdata;
12110 pWextState->roamProfile.nAddIEAssocLength =
12111 pWextState->assocAddIE.length;
12112 }
12113#ifdef WLAN_FEATURE_WFD
12114 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
12115 WFD_OUI_TYPE_SIZE)) &&
12116 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080012117 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012118 pAdapter->device_mode)) {
12119 uint16_t curAddIELen =
12120 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012121 hdd_notice("Set WFD 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 /* WFD IE is saved to Additional IE ; it should
12130 * be accumulated to handle WPS IE + P2P IE +
12131 * WFD IE */
12132 memcpy(pWextState->assocAddIE.addIEdata +
12133 curAddIELen, genie - 2, eLen + 2);
12134 pWextState->assocAddIE.length += eLen + 2;
12135
12136 pWextState->roamProfile.pAddIEAssoc =
12137 pWextState->assocAddIE.addIEdata;
12138 pWextState->roamProfile.nAddIEAssocLength =
12139 pWextState->assocAddIE.length;
12140 }
12141#endif
12142 /* Appending HS 2.0 Indication Element in Assiciation Request */
12143 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
12144 HS20_OUI_TYPE_SIZE))) {
12145 uint16_t curAddIELen =
12146 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012147 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012148
12149 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12150 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012151 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012152 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012153 return -ENOMEM;
12154 }
12155 memcpy(pWextState->assocAddIE.addIEdata +
12156 curAddIELen, genie - 2, eLen + 2);
12157 pWextState->assocAddIE.length += eLen + 2;
12158
12159 pWextState->roamProfile.pAddIEAssoc =
12160 pWextState->assocAddIE.addIEdata;
12161 pWextState->roamProfile.nAddIEAssocLength =
12162 pWextState->assocAddIE.length;
12163 }
12164 /* Appending OSEN Information Element in Assiciation Request */
12165 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
12166 OSEN_OUI_TYPE_SIZE))) {
12167 uint16_t curAddIELen =
12168 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012169 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012170
12171 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12172 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012173 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012174 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012175 return -ENOMEM;
12176 }
12177 memcpy(pWextState->assocAddIE.addIEdata +
12178 curAddIELen, genie - 2, eLen + 2);
12179 pWextState->assocAddIE.length += eLen + 2;
12180
12181 pWextState->roamProfile.bOSENAssociation = true;
12182 pWextState->roamProfile.pAddIEAssoc =
12183 pWextState->assocAddIE.addIEdata;
12184 pWextState->roamProfile.nAddIEAssocLength =
12185 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012186 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
12187 MBO_OUI_TYPE_SIZE))){
12188 hdd_info("Set MBO IE(len %d)", eLen + 2);
12189 status = wlan_hdd_add_assoc_ie(pWextState,
12190 genie - 2, eLen + 2);
12191 if (status)
12192 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012193 } else {
12194 uint16_t add_ie_len =
12195 pWextState->assocAddIE.length;
12196
12197 hdd_info("Set OSEN IE(len %d)", eLen + 2);
12198
12199 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12200 (pWextState->assocAddIE.length + eLen)) {
12201 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012202 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012203 return -ENOMEM;
12204 }
12205
12206 memcpy(pWextState->assocAddIE.addIEdata +
12207 add_ie_len, genie - 2, eLen + 2);
12208 pWextState->assocAddIE.length += eLen + 2;
12209
12210 pWextState->roamProfile.pAddIEAssoc =
12211 pWextState->assocAddIE.addIEdata;
12212 pWextState->roamProfile.nAddIEAssocLength =
12213 pWextState->assocAddIE.length;
12214 }
12215 break;
12216 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012217 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012218 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
12219 memcpy(pWextState->WPARSNIE, genie - 2,
12220 (eLen + 2));
12221 pWextState->roamProfile.pRSNReqIE =
12222 pWextState->WPARSNIE;
12223 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
12224 break;
12225 /*
12226 * Appending Extended Capabilities with Interworking bit set
12227 * in Assoc Req.
12228 *
12229 * In assoc req this EXT Cap will only be taken into account if
12230 * interworkingService bit is set to 1. Currently
12231 * driver is only interested in interworkingService capability
12232 * from supplicant. If in future any other EXT Cap info is
12233 * required from supplicat, it needs to be handled while
12234 * sending Assoc Req in LIM.
12235 */
12236 case DOT11F_EID_EXTCAP:
12237 {
12238 uint16_t curAddIELen =
12239 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012240 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012241
12242 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12243 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012244 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012245 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012246 return -ENOMEM;
12247 }
12248 memcpy(pWextState->assocAddIE.addIEdata +
12249 curAddIELen, genie - 2, eLen + 2);
12250 pWextState->assocAddIE.length += eLen + 2;
12251
12252 pWextState->roamProfile.pAddIEAssoc =
12253 pWextState->assocAddIE.addIEdata;
12254 pWextState->roamProfile.nAddIEAssocLength =
12255 pWextState->assocAddIE.length;
12256 break;
12257 }
12258#ifdef FEATURE_WLAN_WAPI
12259 case WLAN_EID_WAPI:
12260 /* Setting WAPI Mode to ON=1 */
12261 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012262 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012263 tmp = (u16 *) ie;
12264 tmp = tmp + 2; /* Skip element Id and Len, Version */
12265 akmsuiteCount = WPA_GET_LE16(tmp);
12266 tmp = tmp + 1;
12267 akmlist = (int *)(tmp);
12268 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
12269 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
12270 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012271 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012272 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012273 return -EINVAL;
12274 }
12275
12276 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012277 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012278 pAdapter->wapi_info.wapiAuthMode =
12279 WAPI_AUTH_MODE_PSK;
12280 }
12281 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012282 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012283 pAdapter->wapi_info.wapiAuthMode =
12284 WAPI_AUTH_MODE_CERT;
12285 }
12286 break;
12287#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012288 case DOT11F_EID_SUPPOPERATINGCLASSES:
12289 {
12290 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
12291 status = wlan_hdd_add_assoc_ie(pWextState,
12292 genie - 2, eLen + 2);
12293 if (status)
12294 return status;
12295 break;
12296 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012297 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012298 hdd_err("Set UNKNOWN IE %X", elementId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012299 /* when Unknown IE is received we should break and continue
12300 * to the next IE in the buffer instead we were returning
12301 * so changing this to break */
12302 break;
12303 }
12304 genie += eLen;
12305 remLen -= eLen;
12306 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012307 return 0;
12308}
12309
12310/**
12311 * hdd_is_wpaie_present() - check for WPA ie
12312 * @ie: Pointer to ie
12313 * @ie_len: Ie length
12314 *
12315 * Parse the received IE to find the WPA IE
12316 *
12317 * Return: true if wpa ie is found else false
12318 */
12319static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
12320{
12321 uint8_t eLen = 0;
12322 uint16_t remLen = ie_len;
12323 uint8_t elementId = 0;
12324
12325 while (remLen >= 2) {
12326 elementId = *ie++;
12327 eLen = *ie++;
12328 remLen -= 2;
12329 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012330 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012331 return false;
12332 }
12333 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
12334 /* OUI - 0x00 0X50 0XF2
12335 * WPA Information Element - 0x01
12336 * WPA version - 0x01
12337 */
12338 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
12339 return true;
12340 }
12341 ie += eLen;
12342 remLen -= eLen;
12343 }
12344 return false;
12345}
12346
12347/**
12348 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
12349 * @pAdapter: Pointer to adapter
12350 * @req: Pointer to security parameters
12351 *
12352 * Return: 0 for success, non-zero for failure
12353 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012354static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
12355 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012356{
12357 int status = 0;
12358 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12359 ENTER();
12360
12361 /*set wpa version */
12362 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
12363
12364 if (req->crypto.wpa_versions) {
12365 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
12366 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
12367 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
12368 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12369 }
12370 }
12371
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012372 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012373
12374 /*set authentication type */
12375 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
12376
12377 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012378 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012379 return status;
12380 }
12381
12382 /*set key mgmt type */
12383 if (req->crypto.n_akm_suites) {
12384 status =
12385 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
12386 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012387 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012388 return status;
12389 }
12390 }
12391
12392 /*set pairwise cipher type */
12393 if (req->crypto.n_ciphers_pairwise) {
12394 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
12395 req->crypto.
12396 ciphers_pairwise[0],
12397 true);
12398 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012399 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012400 return status;
12401 }
12402 } else {
12403 /*Reset previous cipher suite to none */
12404 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
12405 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012406 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012407 return status;
12408 }
12409 }
12410
12411 /*set group cipher type */
12412 status =
12413 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
12414 false);
12415
12416 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012417 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012418 return status;
12419 }
12420#ifdef WLAN_FEATURE_11W
12421 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
12422#endif
12423
12424 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
12425 if (req->ie_len) {
12426 status =
12427 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
12428 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012429 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012430 return status;
12431 }
12432 }
12433
12434 /*incase of WEP set default key information */
12435 if (req->key && req->key_len) {
12436 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
12437 || (WLAN_CIPHER_SUITE_WEP104 ==
12438 req->crypto.ciphers_pairwise[0])
12439 ) {
12440 if (IW_AUTH_KEY_MGMT_802_1X
12441 ==
12442 (pWextState->
12443 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012444 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012445 return -EOPNOTSUPP;
12446 } else {
12447 u8 key_len = req->key_len;
12448 u8 key_idx = req->key_idx;
12449
12450 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
12451 key_len)
12452 && (CSR_MAX_NUM_KEY > key_idx)
12453 ) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012454 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012455 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012456 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012457 Keys.
12458 KeyMaterial[key_idx][0],
12459 req->key, key_len);
12460 pWextState->roamProfile.Keys.
12461 KeyLength[key_idx] = (u8) key_len;
12462 pWextState->roamProfile.Keys.
12463 defaultIndex = (u8) key_idx;
12464 }
12465 }
12466 }
12467 }
12468
12469 return status;
12470}
12471
12472/**
12473 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
12474 * @pAdapter: Pointer to adapter
12475 *
12476 * This function is used to disconnect from previous connection
12477 *
12478 * Return: 0 for success, non-zero for failure
12479 */
12480static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
12481{
12482 unsigned long rc;
12483 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012484 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012485
12486 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12487
Jeff Johnson9edf9572016-10-03 15:24:49 -070012488 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053012489 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
12490 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
12491 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012492 hdd_conn_set_connection_state(pAdapter,
12493 eConnectionState_Disconnecting);
12494 /* Issue disconnect to CSR */
12495 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012496
12497 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12498 pAdapter->sessionId,
12499 eCSR_DISCONNECT_REASON_UNSPECIFIED);
12500 /*
12501 * Wait here instead of returning directly, this will block the
12502 * next connect command and allow processing of the scan for
12503 * ssid and the previous connect command in CSR. Else we might
12504 * hit some race conditions leading to SME and HDD out of sync.
12505 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012506 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012507 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
12508 } else if (0 != status) {
12509 hdd_err("csrRoamDisconnect failure, returned %d",
12510 (int)status);
12511 pHddStaCtx->staDebugState = status;
12512 result = -EINVAL;
12513 goto disconnected;
12514 }
12515
12516 rc = wait_for_completion_timeout(
12517 &pAdapter->disconnect_comp_var,
12518 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012519 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012520 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
12521 pAdapter->sessionId, pHddStaCtx->staDebugState);
12522 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012523 }
12524 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012525 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012526 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012527 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012528 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012529 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012530 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012531 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012532 }
12533 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012534disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012535 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12536 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012537}
12538
12539/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012540 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
12541 * @adapter: Pointer to the HDD adapter
12542 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070012543 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012544 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012545 * This function will start reassociation if prev_bssid is set and bssid/
12546 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012547 *
Naveen Rawat07332902016-07-27 09:13:17 -070012548 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012549 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053012550#if defined(CFG80211_CONNECT_PREV_BSSID) || \
12551 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070012552static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12553 struct cfg80211_connect_params *req,
12554 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012555{
Naveen Rawat07332902016-07-27 09:13:17 -070012556 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012557 const uint8_t *bssid = NULL;
12558 uint16_t channel = 0;
12559
12560 if (req->bssid)
12561 bssid = req->bssid;
12562 else if (req->bssid_hint)
12563 bssid = req->bssid_hint;
12564
12565 if (req->channel)
12566 channel = req->channel->hw_value;
12567 else if (req->channel_hint)
12568 channel = req->channel_hint->hw_value;
12569
12570 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070012571 reassoc = true;
12572 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012573 channel, MAC_ADDR_ARRAY(bssid));
12574 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012575 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070012576 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012577 }
Naveen Rawat07332902016-07-27 09:13:17 -070012578 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012579}
12580#else
Naveen Rawat07332902016-07-27 09:13:17 -070012581static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12582 struct cfg80211_connect_params *req,
12583 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012584{
Naveen Rawat07332902016-07-27 09:13:17 -070012585 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012586}
12587#endif
12588
12589/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012590 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
12591 * @wiphy: Pointer to wiphy
12592 * @dev: Pointer to network device
12593 * @req: Pointer to cfg80211 connect request
12594 *
12595 * This function is used to start the association process
12596 *
12597 * Return: 0 for success, non-zero for failure
12598 */
12599static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12600 struct net_device *ndev,
12601 struct cfg80211_connect_params *req)
12602{
12603 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012604 u16 channel;
12605#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
12606 const u8 *bssid_hint = req->bssid_hint;
12607#else
12608 const u8 *bssid_hint = NULL;
12609#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012610 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12611 hdd_context_t *pHddCtx;
12612
12613 ENTER();
12614
Anurag Chouhan6d760662016-02-20 16:05:43 +053012615 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012616 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012617 return -EINVAL;
12618 }
12619
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012620 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12621 hdd_err("invalid session id: %d", pAdapter->sessionId);
12622 return -EINVAL;
12623 }
12624
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012625 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012626 TRACE_CODE_HDD_CFG80211_CONNECT,
12627 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012628 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012629 hdd_device_mode_to_string(pAdapter->device_mode),
12630 pAdapter->device_mode);
12631
Krunal Sonib4326f22016-03-10 13:05:51 -080012632 if (pAdapter->device_mode != QDF_STA_MODE &&
12633 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012634 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012635 hdd_device_mode_to_string(pAdapter->device_mode),
12636 pAdapter->device_mode);
12637 return -EINVAL;
12638 }
12639
12640 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12641 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012642 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012643 return -EINVAL;
12644 }
12645
12646 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012647 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012648 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012649
Naveen Rawat07332902016-07-27 09:13:17 -070012650 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012651 return status;
12652
Agrawal Ashishf156e942016-08-04 14:54:47 +053012653 wlan_hdd_disable_roaming(pAdapter);
12654
12655 /* Try disconnecting if already in connected state */
12656 status = wlan_hdd_try_disconnect(pAdapter);
12657 if (0 > status) {
12658 hdd_err("Failed to disconnect the existing connection");
12659 return -EALREADY;
12660 }
12661
12662 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012663 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012664 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012665 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012666 pAdapter->device_mode),
12667 req->channel->hw_value, HW_MODE_20_MHZ)) {
12668 hdd_err("This concurrency combination is not allowed");
12669 return -ECONNREFUSED;
12670 }
12671 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012672 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012673 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012674 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
12675 hdd_err("This concurrency combination is not allowed");
12676 return -ECONNREFUSED;
12677 }
12678 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012679
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012680 /*initialise security parameters */
12681 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
12682
12683 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012684 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012685 return status;
12686 }
12687
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012688 if (req->channel)
12689 channel = req->channel->hw_value;
12690 else
12691 channel = 0;
12692 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
12693 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012694 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012695 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012696 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012697 return status;
12698 }
12699 EXIT();
12700 return status;
12701}
12702
12703/**
12704 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
12705 * @wiphy: Pointer to wiphy
12706 * @dev: Pointer to network device
12707 * @req: Pointer to cfg80211 connect request
12708 *
12709 * Return: 0 for success, non-zero for failure
12710 */
12711static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12712 struct net_device *ndev,
12713 struct cfg80211_connect_params *req)
12714{
12715 int ret;
12716 cds_ssr_protect(__func__);
12717 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
12718 cds_ssr_unprotect(__func__);
12719
12720 return ret;
12721}
12722
12723/**
12724 * wlan_hdd_disconnect() - hdd disconnect api
12725 * @pAdapter: Pointer to adapter
12726 * @reason: Disconnect reason code
12727 *
12728 * This function is used to issue a disconnect request to SME
12729 *
12730 * Return: 0 for success, non-zero for failure
12731 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012732static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012733{
12734 int status, result = 0;
12735 unsigned long rc;
12736 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12737 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12738
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012739 ENTER();
12740
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012741 status = wlan_hdd_validate_context(pHddCtx);
12742
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012743 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012744 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012745
12746 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012747 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012748 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
12749 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012750 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012751 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
12752 INIT_COMPLETION(pAdapter->disconnect_comp_var);
12753
12754 /*issue disconnect */
12755
12756 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12757 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053012758 /*
12759 * Wait here instead of returning directly, this will block the next
12760 * connect command and allow processing of the scan for ssid and
12761 * the previous connect command in CSR. Else we might hit some
12762 * race conditions leading to SME and HDD out of sync.
12763 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012764 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012765 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012766 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012767 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012768 (int)status);
12769 pHddStaCtx->staDebugState = status;
12770 result = -EINVAL;
12771 goto disconnected;
12772 }
12773 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
12774 msecs_to_jiffies
12775 (WLAN_WAIT_TIME_DISCONNECT));
12776
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012777 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012778 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012779 result = -ETIMEDOUT;
12780 }
12781disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012782 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12783#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
12784 /* Sending disconnect event to userspace for kernel version < 3.11
12785 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
12786 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012787 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053012788 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
12789 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012790#endif
12791
12792 return result;
12793}
12794
12795/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012796 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
12797 * @reason: ieee80211 reason code.
12798 *
12799 * This utility function helps log string conversion of reason code.
12800 *
12801 * Return: string conversion of reason code, if match found;
12802 * "Unknown" otherwise.
12803 */
12804static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
12805{
12806 switch (reason) {
12807 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
12808 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
12809 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
12810 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
12811 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
12812 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
12813 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
12814 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
12815 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
12816 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
12817 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
12818 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
12819 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
12820 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
12821 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
12822 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
12823 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
12824 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
12825 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
12826 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
12827 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
12828 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
12829 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
12830 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
12831 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
12832 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
12833 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
12834 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
12835 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
12836 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
12837 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
12838 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
12839 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
12840 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
12841 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
12842 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
12843 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
12844 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
12845 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
12846 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
12847 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
12848 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
12849 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
12850 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
12851 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
12852 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
12853 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
12854 default:
12855 return "Unknown";
12856 }
12857}
12858
12859/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012860 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12861 * @wiphy: Pointer to wiphy
12862 * @dev: Pointer to network device
12863 * @reason: Disconnect reason code
12864 *
12865 * This function is used to issue a disconnect request to SME
12866 *
12867 * Return: 0 for success, non-zero for failure
12868 */
12869static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12870 struct net_device *dev, u16 reason)
12871{
12872 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12873 int status;
12874 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12875 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12876#ifdef FEATURE_WLAN_TDLS
12877 uint8_t staIdx;
12878#endif
12879
12880 ENTER();
12881
Anurag Chouhan6d760662016-02-20 16:05:43 +053012882 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012883 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012884 return -EINVAL;
12885 }
12886
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053012887 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
12888 hdd_err("invalid session id: %d", pAdapter->sessionId);
12889 return -EINVAL;
12890 }
12891
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012892 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012893 TRACE_CODE_HDD_CFG80211_DISCONNECT,
12894 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012895 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012896 hdd_device_mode_to_string(pAdapter->device_mode),
12897 pAdapter->device_mode, reason);
12898
12899 status = wlan_hdd_validate_context(pHddCtx);
12900
Varun Reddy Yeturu3e213e52016-11-24 16:24:15 -080012901 if (hdd_is_roaming_in_progress()) {
12902 hdd_err("Roaming In Progress. Ignore!!!");
12903 return -EAGAIN;
12904 }
12905
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012906 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012907 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012908
12909 /* Issue disconnect request to SME, if station is in connected state */
12910 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
12911 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
12912 eCsrRoamDisconnectReason reasonCode =
12913 eCSR_DISCONNECT_REASON_UNSPECIFIED;
12914 hdd_scaninfo_t *pScanInfo;
12915
12916 switch (reason) {
12917 case WLAN_REASON_MIC_FAILURE:
12918 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
12919 break;
12920
12921 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
12922 case WLAN_REASON_DISASSOC_AP_BUSY:
12923 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
12924 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
12925 break;
12926
12927 case WLAN_REASON_PREV_AUTH_NOT_VALID:
12928 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
12929 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
12930 break;
12931
12932 case WLAN_REASON_DEAUTH_LEAVING:
12933 reasonCode =
12934 pHddCtx->config->
12935 gEnableDeauthToDisassocMap ?
12936 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
12937 eCSR_DISCONNECT_REASON_DEAUTH;
12938 break;
12939 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
12940 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
12941 break;
12942 default:
12943 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
12944 break;
12945 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012946 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012947 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012948 pScanInfo = &pAdapter->scan_info;
12949 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012950 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012951 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
12952 eCSR_SCAN_ABORT_DEFAULT);
12953 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053012954 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012955#ifdef FEATURE_WLAN_TDLS
12956 /* First clean up the tdls peers if any */
12957 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
12958 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
12959 pAdapter->sessionId)
12960 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
12961 uint8_t *mac;
12962 mac =
12963 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012964 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
12965 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012966 pHddCtx->tdlsConnInfo[staIdx].staId,
12967 pAdapter->sessionId,
12968 MAC_ADDR_ARRAY(mac));
12969 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
12970 (pAdapter),
12971 pAdapter->sessionId, mac);
12972 }
12973 }
12974#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012975 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012976 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012977 hdd_info("Disconnect request from user space with reason: %s",
12978 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012979 status = wlan_hdd_disconnect(pAdapter, reasonCode);
12980 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012981 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012982 return -EINVAL;
12983 }
12984 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012985 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012986 pHddStaCtx->conn_info.connState);
12987 }
12988
12989 return status;
12990}
12991
12992/**
12993 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12994 * @wiphy: Pointer to wiphy
12995 * @dev: Pointer to network device
12996 * @reason: Disconnect reason code
12997 *
12998 * Return: 0 for success, non-zero for failure
12999 */
13000static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
13001 struct net_device *dev, u16 reason)
13002{
13003 int ret;
13004 cds_ssr_protect(__func__);
13005 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
13006 cds_ssr_unprotect(__func__);
13007
13008 return ret;
13009}
13010
13011/**
13012 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
13013 * @pAdapter: Pointer to adapter
13014 * @param: Pointer to IBSS parameters
13015 *
13016 * This function is used to initialize the security settings in IBSS mode
13017 *
13018 * Return: 0 for success, non-zero for failure
13019 */
13020static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
13021 struct cfg80211_ibss_params
13022 *params)
13023{
13024 int status = 0;
13025 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13026 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
13027 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13028
13029 ENTER();
13030
13031 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013032 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013033 pHddStaCtx->ibss_enc_key_installed = 0;
13034
13035 if (params->ie_len && (NULL != params->ie)) {
13036 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
13037 params->ie_len, WLAN_EID_RSN)) {
13038 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
13039 encryptionType = eCSR_ENCRYPT_TYPE_AES;
13040 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
13041 tDot11fIEWPA dot11WPAIE;
13042 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13043 u8 *ie;
13044
13045 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
13046 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
13047 params->ie_len,
13048 DOT11F_EID_WPA);
13049 if (NULL != ie) {
13050 pWextState->wpaVersion =
13051 IW_AUTH_WPA_VERSION_WPA;
13052 /* Unpack the WPA IE */
13053 /* Skip past the EID byte and length byte - and four byte WiFi OUI */
13054 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
13055 &ie[2 + 4],
13056 ie[1] - 4, &dot11WPAIE);
13057 /*Extract the multicast cipher, the encType for unicast
13058 cipher for wpa-none is none */
13059 encryptionType =
13060 hdd_translate_wpa_to_csr_encryption_type
13061 (dot11WPAIE.multicast_cipher);
13062 }
13063 }
13064
13065 status =
13066 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
13067 params->ie_len);
13068
13069 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013070 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013071 return status;
13072 }
13073 }
13074
13075 pWextState->roamProfile.AuthType.authType[0] =
13076 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
13077
13078 if (params->privacy) {
13079 /* Security enabled IBSS, At this time there is no information
13080 * available about the security paramters, so initialise the
13081 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
13082 * The correct security parameters will be updated later in
13083 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
13084 * set inorder enable privacy bit in beacons
13085 */
13086
13087 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
13088 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013089 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013090 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
13091 pWextState->roamProfile.EncryptionType.numEntries = 1;
13092 pWextState->roamProfile.EncryptionType.encryptionType[0] =
13093 encryptionType;
13094 return status;
13095}
13096
13097/**
13098 * __wlan_hdd_cfg80211_join_ibss() - join ibss
13099 * @wiphy: Pointer to wiphy
13100 * @dev: Pointer to network device
13101 * @param: Pointer to IBSS join parameters
13102 *
13103 * This function is used to create/join an IBSS network
13104 *
13105 * Return: 0 for success, non-zero for failure
13106 */
13107static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13108 struct net_device *dev,
13109 struct cfg80211_ibss_params *params)
13110{
13111 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13112 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13113 tCsrRoamProfile *pRoamProfile;
13114 int status;
13115 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13116 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053013117 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013118 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013119
13120 ENTER();
13121
Anurag Chouhan6d760662016-02-20 16:05:43 +053013122 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013123 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013124 return -EINVAL;
13125 }
13126
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013127 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13128 hdd_err("invalid session id: %d", pAdapter->sessionId);
13129 return -EINVAL;
13130 }
13131
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013132 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013133 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
13134 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013135 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013136 hdd_device_mode_to_string(pAdapter->device_mode),
13137 pAdapter->device_mode);
13138
13139 status = wlan_hdd_validate_context(pHddCtx);
13140
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013141 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013142 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013143
13144 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053013145 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013146 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
13147 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
13148 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13149 int indx;
13150
13151 /* Get channel number */
13152 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013153 params->
13154 chandef.
13155 chan->
13156 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013157
13158 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
13159 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013160 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013161 return -EOPNOTSUPP;
13162 }
13163
13164 for (indx = 0; indx < numChans; indx++) {
13165 if (channelNum == validChan[indx]) {
13166 break;
13167 }
13168 }
13169 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013170 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013171 return -EINVAL;
13172 }
13173 }
13174
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080013175 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013176 HW_MODE_20_MHZ)) {
13177 hdd_err("This concurrency combination is not allowed");
13178 return -ECONNREFUSED;
13179 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013180
Krunal Soni3091bcc2016-06-23 12:28:21 -070013181 status = qdf_reset_connection_update();
13182 if (!QDF_IS_STATUS_SUCCESS(status))
13183 hdd_err("ERR: clear event failed");
13184
13185 status = cds_current_connections_update(pAdapter->sessionId,
13186 channelNum,
13187 SIR_UPDATE_REASON_JOIN_IBSS);
13188 if (QDF_STATUS_E_FAILURE == status) {
13189 hdd_err("ERROR: connections update failed!!");
13190 return -EINVAL;
13191 }
13192
13193 if (QDF_STATUS_SUCCESS == status) {
13194 status = qdf_wait_for_connection_update();
13195 if (!QDF_IS_STATUS_SUCCESS(status)) {
13196 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013197 return -EINVAL;
13198 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013199 }
13200
13201 /*Try disconnecting if already in connected state */
13202 status = wlan_hdd_try_disconnect(pAdapter);
13203 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013204 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013205 return -EALREADY;
13206 }
13207
13208 pRoamProfile = &pWextState->roamProfile;
13209
13210 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013211 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013212 return -EINVAL;
13213 }
13214
13215 /* enable selected protection checks in IBSS mode */
13216 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
13217
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013218 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013219 WNI_CFG_IBSS_ATIM_WIN_SIZE,
13220 pHddCtx->config->
13221 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013222 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013223 }
13224
13225 /* BSSID is provided by upper layers hence no need to AUTO generate */
13226 if (NULL != params->bssid) {
13227 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013228 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013229 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013230 return -EIO;
13231 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013232 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013233 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
13234 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013235 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013236 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013237 return -EIO;
13238 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053013239 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013240 }
13241 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
13242 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
13243 pRoamProfile->beaconInterval = params->beacon_interval;
13244 else {
13245 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013246 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013247 params->beacon_interval, pRoamProfile->beaconInterval);
13248 }
13249
13250 /* Set Channel */
13251 if (channelNum) {
13252 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013253 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013254 pRoamProfile->ChannelInfo.numOfChannels = 1;
13255 pHddStaCtx->conn_info.operationChannel = channelNum;
13256 pRoamProfile->ChannelInfo.ChannelList =
13257 &pHddStaCtx->conn_info.operationChannel;
13258 }
13259
13260 /* Initialize security parameters */
13261 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
13262 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013263 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013264 return status;
13265 }
13266
13267 /* Issue connect start */
13268 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
13269 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013270 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013271 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013272 operationChannel,
13273 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013274
13275 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013276 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013277 return status;
13278 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013279 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013280 return 0;
13281}
13282
13283/**
13284 * wlan_hdd_cfg80211_join_ibss() - join ibss
13285 * @wiphy: Pointer to wiphy
13286 * @dev: Pointer to network device
13287 * @param: Pointer to IBSS join parameters
13288 *
13289 * This function is used to create/join an IBSS network
13290 *
13291 * Return: 0 for success, non-zero for failure
13292 */
13293static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13294 struct net_device *dev,
13295 struct cfg80211_ibss_params *params)
13296{
13297 int ret = 0;
13298
13299 cds_ssr_protect(__func__);
13300 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
13301 cds_ssr_unprotect(__func__);
13302
13303 return ret;
13304}
13305
13306/**
13307 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
13308 * @wiphy: Pointer to wiphy
13309 * @dev: Pointer to network device
13310 *
13311 * This function is used to leave an IBSS network
13312 *
13313 * Return: 0 for success, non-zero for failure
13314 */
13315static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13316 struct net_device *dev)
13317{
13318 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13319 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13320 tCsrRoamProfile *pRoamProfile;
13321 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13322 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013323 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013324 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013325 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013326
13327 ENTER();
13328
Anurag Chouhan6d760662016-02-20 16:05:43 +053013329 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013330 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013331 return -EINVAL;
13332 }
13333
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013334 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13335 hdd_err("invalid session id: %d", pAdapter->sessionId);
13336 return -EINVAL;
13337 }
13338
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013339 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013340 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
13341 pAdapter->sessionId,
13342 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
13343 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013344 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013345 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013346
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013347 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013348 hdd_device_mode_to_string(pAdapter->device_mode),
13349 pAdapter->device_mode);
13350 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013351 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013352 return -EIO;
13353 }
13354
13355 pRoamProfile = &pWextState->roamProfile;
13356
13357 /* Issue disconnect only if interface type is set to IBSS */
13358 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013359 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013360 return -EINVAL;
13361 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013362 /* Clearing add IE of beacon */
13363 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
13364 sizeof(tSirMacAddr));
13365 updateIE.smeSessionId = pAdapter->sessionId;
13366 updateIE.ieBufferlength = 0;
13367 updateIE.pAdditionIEBuffer = NULL;
13368 updateIE.append = true;
13369 updateIE.notify = true;
13370 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
13371 &updateIE,
13372 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013373 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013374 }
13375
13376 /* Reset WNI_CFG_PROBE_RSP Flags */
13377 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013378
13379 /* Issue Disconnect request */
13380 INIT_COMPLETION(pAdapter->disconnect_comp_var);
13381 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13382 pAdapter->sessionId,
13383 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013384 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013385 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013386 hal_status);
13387 return -EAGAIN;
13388 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013389
13390 /* wait for mc thread to cleanup and then return to upper stack
13391 * so by the time upper layer calls the change interface, we are
13392 * all set to proceed further
13393 */
13394 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
13395 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
13396 if (!rc) {
13397 hdd_err("Failed to disconnect, timed out");
13398 return -ETIMEDOUT;
13399 }
13400
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013401 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013402 return 0;
13403}
13404
13405/**
13406 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
13407 * @wiphy: Pointer to wiphy
13408 * @dev: Pointer to network device
13409 *
13410 * This function is used to leave an IBSS network
13411 *
13412 * Return: 0 for success, non-zero for failure
13413 */
13414static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13415 struct net_device *dev)
13416{
13417 int ret = 0;
13418
13419 cds_ssr_protect(__func__);
13420 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
13421 cds_ssr_unprotect(__func__);
13422
13423 return ret;
13424}
13425
13426/**
13427 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13428 * @wiphy: Pointer to wiphy
13429 * @changed: Parameters changed
13430 *
13431 * This function is used to set the phy parameters. RTS Threshold/FRAG
13432 * Threshold/Retry Count etc.
13433 *
13434 * Return: 0 for success, non-zero for failure
13435 */
13436static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
13437 u32 changed)
13438{
13439 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13440 tHalHandle hHal = pHddCtx->hHal;
13441 int status;
13442
13443 ENTER();
13444
Anurag Chouhan6d760662016-02-20 16:05:43 +053013445 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013446 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013447 return -EINVAL;
13448 }
13449
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013450 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013451 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
13452 NO_SESSION, wiphy->rts_threshold));
13453 status = wlan_hdd_validate_context(pHddCtx);
13454
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013455 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013456 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013457
13458 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
13459 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
13460 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
13461
13462 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
13463 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013464 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013465 rts_threshold);
13466 return -EINVAL;
13467 }
13468
13469 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
13470 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013471 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013472 rts_threshold);
13473 return -EIO;
13474 }
13475
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013476 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013477 }
13478
13479 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
13480 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
13481 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
13482 wiphy->frag_threshold;
13483
13484 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
13485 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013486 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013487 frag_threshold);
13488 return -EINVAL;
13489 }
13490
13491 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
13492 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013493 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013494 frag_threshold);
13495 return -EIO;
13496 }
13497
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013498 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013499 }
13500
13501 if ((changed & WIPHY_PARAM_RETRY_SHORT)
13502 || (changed & WIPHY_PARAM_RETRY_LONG)) {
13503 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
13504 wiphy->retry_short : wiphy->retry_long;
13505
13506 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
13507 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013508 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013509 return -EINVAL;
13510 }
13511
13512 if (changed & WIPHY_PARAM_RETRY_SHORT) {
13513 if (0 != sme_cfg_set_int(hHal,
13514 WNI_CFG_LONG_RETRY_LIMIT,
13515 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013516 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013517 retry_value);
13518 return -EIO;
13519 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013520 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013521 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
13522 if (0 != sme_cfg_set_int(hHal,
13523 WNI_CFG_SHORT_RETRY_LIMIT,
13524 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013525 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013526 retry_value);
13527 return -EIO;
13528 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013529 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013530 }
13531 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013532 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013533 return 0;
13534}
13535
13536/**
13537 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13538 * @wiphy: Pointer to wiphy
13539 * @changed: Parameters changed
13540 *
13541 * Return: 0 for success, non-zero for failure
13542 */
13543static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
13544{
13545 int ret;
13546
13547 cds_ssr_protect(__func__);
13548 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
13549 cds_ssr_unprotect(__func__);
13550
13551 return ret;
13552}
13553
13554/**
13555 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
13556 * key
13557 * @wiphy: Pointer to wiphy
13558 * @dev: Pointer to network device
13559 * @key_index: Key index
13560 *
13561 * Return: 0
13562 */
13563static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13564 struct net_device *netdev,
13565 u8 key_index)
13566{
13567 ENTER();
13568 return 0;
13569}
13570
13571/**
13572 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
13573 * wlan_hdd_set_default_mgmt_key
13574 * @wiphy: pointer to wiphy
13575 * @netdev: pointer to net_device structure
13576 * @key_index: key index
13577 *
13578 * Return: 0 on success, error number on failure
13579 */
13580static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13581 struct net_device *netdev,
13582 u8 key_index)
13583{
13584 int ret;
13585
13586 cds_ssr_protect(__func__);
13587 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
13588 cds_ssr_unprotect(__func__);
13589
13590 return ret;
13591}
13592
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013593/**
13594 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
13595 * @wiphy: Pointer to wiphy
13596 * @dev: Pointer to network device
13597 * @params: Pointer to tx queue parameters
13598 *
13599 * Return: 0
13600 */
13601static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
13602 struct net_device *dev,
13603 struct ieee80211_txq_params *params)
13604{
13605 ENTER();
13606 return 0;
13607}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013608
13609/**
13610 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
13611 * @wiphy: pointer to wiphy
13612 * @netdev: pointer to net_device structure
13613 * @params: pointer to ieee80211_txq_params
13614 *
13615 * Return: 0 on success, error number on failure
13616 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013617static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
13618 struct net_device *dev,
13619 struct ieee80211_txq_params *params)
13620{
13621 int ret;
13622
13623 cds_ssr_protect(__func__);
13624 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
13625 cds_ssr_unprotect(__func__);
13626
13627 return ret;
13628}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013629
13630/**
13631 * __wlan_hdd_cfg80211_del_station() - delete station v2
13632 * @wiphy: Pointer to wiphy
13633 * @param: Pointer to delete station parameter
13634 *
13635 * Return: 0 for success, non-zero for failure
13636 */
13637static
13638int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13639 struct net_device *dev,
13640 struct tagCsrDelStaParams *pDelStaParams)
13641{
13642 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13643 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013644 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013645 hdd_hostapd_state_t *hapd_state;
13646 int status;
13647 uint8_t staId;
13648 uint8_t *mac;
13649
13650 ENTER();
13651
Anurag Chouhan6d760662016-02-20 16:05:43 +053013652 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013653 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013654 return -EINVAL;
13655 }
13656
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013657 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13658 hdd_err("invalid session id: %d", pAdapter->sessionId);
13659 return -EINVAL;
13660 }
13661
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013662 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013663 TRACE_CODE_HDD_CFG80211_DEL_STA,
13664 pAdapter->sessionId, pAdapter->device_mode));
13665
13666 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13667 status = wlan_hdd_validate_context(pHddCtx);
13668
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013669 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013670 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013671
13672 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
13673
Krunal Sonib4326f22016-03-10 13:05:51 -080013674 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
13675 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013676
13677 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
13678 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013679 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013680 return 0;
13681 }
13682
Anurag Chouhanc5548422016-02-24 18:33:27 +053013683 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013684 uint16_t i;
13685 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
13686 if ((pAdapter->aStaInfo[i].isUsed) &&
13687 (!pAdapter->aStaInfo[i].
13688 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013689 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013690 mac,
13691 pAdapter->aStaInfo[i].
13692 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013693 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013694 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13695 hdd_ipa_wlan_evt(pAdapter,
13696 pAdapter->
13697 aStaInfo[i].
13698 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013699 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013700 mac);
13701 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013702 hdd_notice("Delete STA with MAC::"
13703 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013704 MAC_ADDR_ARRAY(mac));
13705
13706 if (pHddCtx->dev_dfs_cac_status ==
13707 DFS_CAC_IN_PROGRESS)
13708 goto fn_end;
13709
Wei Song2f76f642016-11-18 16:32:53 +080013710 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013711 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053013712 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013713 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013714 hdd_softap_sta_deauth(pAdapter,
13715 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013716 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013717 pAdapter->aStaInfo[i].
13718 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013719 qdf_status =
13720 qdf_wait_single_event(
Wei Song2f76f642016-11-18 16:32:53 +080013721 &hapd_state->qdf_sta_disassoc_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013722 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013723 if (!QDF_IS_STATUS_SUCCESS(
13724 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013725 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013726 }
13727 }
13728 }
13729 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013730 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013731 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013732 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013733 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013734 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013735 hdd_notice("Skip DEL STA as this is not used::"
13736 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013737 MAC_ADDR_ARRAY(mac));
13738 return -ENOENT;
13739 }
13740
13741 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13742 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013743 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013744 }
13745
13746 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
13747 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013748 hdd_notice("Skip DEL STA as deauth is in progress::"
13749 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013750 MAC_ADDR_ARRAY(mac));
13751 return -ENOENT;
13752 }
13753
13754 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
13755
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013756 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013757 MAC_ADDR_ARRAY(mac));
13758
13759 /* Case: SAP in ACS selected DFS ch and client connected
13760 * Now Radar detected. Then if random channel is another
13761 * DFS ch then new CAC is initiated and no TX allowed.
13762 * So do not send any mgmt frames as it will timeout
13763 * during CAC.
13764 */
13765
13766 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
13767 goto fn_end;
13768
Wei Song2f76f642016-11-18 16:32:53 +080013769 qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053013770 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
13771 (pAdapter), pAdapter->sessionId,
13772 (uint8_t *)&pDelStaParams->peerMacAddr,
13773 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013774 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013775 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013776 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013777 pAdapter->aStaInfo[staId].isDeauthInProgress =
13778 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013779 hdd_notice("STA removal failed for ::"
13780 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013781 MAC_ADDR_ARRAY(mac));
13782 return -ENOENT;
13783 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053013784 qdf_status = qdf_wait_single_event(
Wei Song2f76f642016-11-18 16:32:53 +080013785 &hapd_state->qdf_sta_disassoc_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013786 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013787 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013788 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013789 }
13790 }
13791 }
13792
13793fn_end:
13794 EXIT();
13795 return 0;
13796}
13797
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013798#if defined(USE_CFG80211_DEL_STA_V2)
13799/**
13800 * wlan_hdd_del_station() - delete station wrapper
13801 * @adapter: pointer to the hdd adapter
13802 *
13803 * Return: None
13804 */
13805void wlan_hdd_del_station(hdd_adapter_t *adapter)
13806{
13807 struct station_del_parameters del_sta;
13808 del_sta.mac = NULL;
13809 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
13810 del_sta.reason_code = eCsrForcedDeauthSta;
13811
13812 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
13813 &del_sta);
13814}
13815#else
13816void wlan_hdd_del_station(hdd_adapter_t *adapter)
13817{
13818 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
13819}
13820#endif
13821
13822#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013823/**
13824 * wlan_hdd_cfg80211_del_station() - delete station v2
13825 * @wiphy: Pointer to wiphy
13826 * @param: Pointer to delete station parameter
13827 *
13828 * Return: 0 for success, non-zero for failure
13829 */
13830int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13831 struct net_device *dev,
13832 struct station_del_parameters *param)
13833#else
13834/**
13835 * wlan_hdd_cfg80211_del_station() - delete station
13836 * @wiphy: Pointer to wiphy
13837 * @mac: Pointer to station mac address
13838 *
13839 * Return: 0 for success, non-zero for failure
13840 */
13841#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13842int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13843 struct net_device *dev,
13844 const uint8_t *mac)
13845#else
13846int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13847 struct net_device *dev,
13848 uint8_t *mac)
13849#endif
13850#endif
13851{
13852 int ret;
13853 struct tagCsrDelStaParams delStaParams;
13854
13855 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013856#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013857 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013858 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013859 return -EINVAL;
13860 }
13861 wlansap_populate_del_sta_params(param->mac, param->reason_code,
13862 param->subtype, &delStaParams);
13863#else
13864 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
13865 (SIR_MAC_MGMT_DEAUTH >> 4),
13866 &delStaParams);
13867#endif
13868 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
13869 cds_ssr_unprotect(__func__);
13870
13871 return ret;
13872}
13873
13874/**
13875 * __wlan_hdd_cfg80211_add_station() - add station
13876 * @wiphy: Pointer to wiphy
13877 * @mac: Pointer to station mac address
13878 * @pmksa: Pointer to add station parameter
13879 *
13880 * Return: 0 for success, non-zero for failure
13881 */
13882static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13883 struct net_device *dev,
13884 const uint8_t *mac,
13885 struct station_parameters *params)
13886{
13887 int status = -EPERM;
13888#ifdef FEATURE_WLAN_TDLS
13889 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13890 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13891 u32 mask, set;
13892
13893 ENTER();
13894
Anurag Chouhan6d760662016-02-20 16:05:43 +053013895 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013896 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013897 return -EINVAL;
13898 }
13899
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013900 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13901 hdd_err("invalid session id: %d", pAdapter->sessionId);
13902 return -EINVAL;
13903 }
13904
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013905 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013906 TRACE_CODE_HDD_CFG80211_ADD_STA,
13907 pAdapter->sessionId, params->listen_interval));
13908
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013909 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013910 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013911
13912 mask = params->sta_flags_mask;
13913
13914 set = params->sta_flags_set;
13915
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013916 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013917 MAC_ADDR_ARRAY(mac));
13918
13919 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13920 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13921 status =
13922 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
13923 }
13924 }
13925#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013926 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013927 return status;
13928}
13929
13930/**
13931 * wlan_hdd_cfg80211_add_station() - add station
13932 * @wiphy: Pointer to wiphy
13933 * @mac: Pointer to station mac address
13934 * @pmksa: Pointer to add station parameter
13935 *
13936 * Return: 0 for success, non-zero for failure
13937 */
13938#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13939static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13940 struct net_device *dev,
13941 const uint8_t *mac,
13942 struct station_parameters *params)
13943#else
13944static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13945 struct net_device *dev, uint8_t *mac,
13946 struct station_parameters *params)
13947#endif
13948{
13949 int ret;
13950
13951 cds_ssr_protect(__func__);
13952 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
13953 cds_ssr_unprotect(__func__);
13954
13955 return ret;
13956}
13957
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013958/**
13959 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
13960 * @wiphy: Pointer to wiphy
13961 * @dev: Pointer to network device
13962 * @pmksa: Pointer to set pmksa parameter
13963 *
13964 * Return: 0 for success, non-zero for failure
13965 */
13966static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13967 struct net_device *dev,
13968 struct cfg80211_pmksa *pmksa)
13969{
13970 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13971 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13972 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013973 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013974 int status;
13975 tPmkidCacheInfo pmk_id;
13976
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013977 ENTER();
13978
Anurag Chouhan6d760662016-02-20 16:05:43 +053013979 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013980 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013981 return -EINVAL;
13982 }
13983
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053013984 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
13985 hdd_err("invalid session id: %d", pAdapter->sessionId);
13986 return -EINVAL;
13987 }
13988
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013989 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013990 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013991 return -EINVAL;
13992 }
13993
13994 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013995 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013996 pmksa->bssid, pmksa->pmkid);
13997 return -EINVAL;
13998 }
13999
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014000 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014001 MAC_ADDR_ARRAY(pmksa->bssid));
14002
14003 status = wlan_hdd_validate_context(pHddCtx);
14004
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014005 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014006 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014007
14008 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14009
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014010 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
14011 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014012
14013 /* Add to the PMKSA ID Cache in CSR */
14014 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
14015 &pmk_id, 1, false);
14016
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014017 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014018 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
14019 pAdapter->sessionId, result));
14020
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014021 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014022 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014023}
14024
14025/**
14026 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
14027 * @wiphy: Pointer to wiphy
14028 * @dev: Pointer to network device
14029 * @pmksa: Pointer to set pmksa parameter
14030 *
14031 * Return: 0 for success, non-zero for failure
14032 */
14033static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
14034 struct net_device *dev,
14035 struct cfg80211_pmksa *pmksa)
14036{
14037 int ret;
14038
14039 cds_ssr_protect(__func__);
14040 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
14041 cds_ssr_unprotect(__func__);
14042
14043 return ret;
14044}
14045
14046/**
14047 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
14048 * @wiphy: Pointer to wiphy
14049 * @dev: Pointer to network device
14050 * @pmksa: Pointer to pmksa parameter
14051 *
14052 * Return: 0 for success, non-zero for failure
14053 */
14054static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
14055 struct net_device *dev,
14056 struct cfg80211_pmksa *pmksa)
14057{
14058 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14059 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14060 tHalHandle halHandle;
14061 int status = 0;
14062
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014063 ENTER();
14064
Anurag Chouhan6d760662016-02-20 16:05:43 +053014065 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014066 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014067 return -EINVAL;
14068 }
14069
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014070 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14071 hdd_err("invalid session id: %d", pAdapter->sessionId);
14072 return -EINVAL;
14073 }
14074
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014075 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014076 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014077 return -EINVAL;
14078 }
14079
14080 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014081 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014082 return -EINVAL;
14083 }
14084
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014085 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014086 MAC_ADDR_ARRAY(pmksa->bssid));
14087
14088 status = wlan_hdd_validate_context(pHddCtx);
14089
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014090 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014091 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014092
14093 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14094
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014095 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014096 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
14097 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014098 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014099 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014100 sme_roam_del_pmkid_from_cache(halHandle,
14101 pAdapter->sessionId, pmksa->bssid,
14102 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014103 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014104 MAC_ADDR_ARRAY(pmksa->bssid));
14105 status = -EINVAL;
14106 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014107 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014108 return status;
14109}
14110
14111/**
14112 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
14113 * @wiphy: Pointer to wiphy
14114 * @dev: Pointer to network device
14115 * @pmksa: Pointer to pmksa parameter
14116 *
14117 * Return: 0 for success, non-zero for failure
14118 */
14119static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
14120 struct net_device *dev,
14121 struct cfg80211_pmksa *pmksa)
14122{
14123 int ret;
14124
14125 cds_ssr_protect(__func__);
14126 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
14127 cds_ssr_unprotect(__func__);
14128
14129 return ret;
14130
14131}
14132
14133/**
14134 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
14135 * @wiphy: Pointer to wiphy
14136 * @dev: Pointer to network device
14137 *
14138 * Return: 0 for success, non-zero for failure
14139 */
14140static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
14141 struct net_device *dev)
14142{
14143 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14144 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14145 tHalHandle halHandle;
14146 int status = 0;
14147
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014148 ENTER();
14149
Anurag Chouhan6d760662016-02-20 16:05:43 +053014150 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014151 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014152 return -EINVAL;
14153 }
14154
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014155 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14156 hdd_err("invalid session id: %d", pAdapter->sessionId);
14157 return -EINVAL;
14158 }
14159
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014160 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014161
14162 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14163 status = wlan_hdd_validate_context(pHddCtx);
14164
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014165 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014166 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014167
14168 /* Retrieve halHandle */
14169 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
14170
14171 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014172 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014173 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
14174 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014175 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014176 status = -EINVAL;
14177 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014178 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014179 return status;
14180}
14181
14182/**
14183 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
14184 * @wiphy: Pointer to wiphy
14185 * @dev: Pointer to network device
14186 *
14187 * Return: 0 for success, non-zero for failure
14188 */
14189static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
14190 struct net_device *dev)
14191{
14192 int ret;
14193
14194 cds_ssr_protect(__func__);
14195 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
14196 cds_ssr_unprotect(__func__);
14197
14198 return ret;
14199}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014200
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080014201#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014202/**
14203 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
14204 * @wiphy: Pointer to wiphy
14205 * @dev: Pointer to network device
14206 * @ftie: Pointer to fast transition ie parameter
14207 *
14208 * Return: 0 for success, non-zero for failure
14209 */
14210static int
14211__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14212 struct net_device *dev,
14213 struct cfg80211_update_ft_ies_params *ftie)
14214{
14215 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
14216 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14217 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14218 int status;
14219
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014220 ENTER();
14221
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014222 status = wlan_hdd_validate_context(hdd_ctx);
14223 if (status)
14224 return status;
14225
Anurag Chouhan6d760662016-02-20 16:05:43 +053014226 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014227 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014228 return -EINVAL;
14229 }
14230
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014231 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14232 hdd_err("invalid session id: %d", pAdapter->sessionId);
14233 return -EINVAL;
14234 }
14235
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014236 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014237 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
14238 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
14239 /* Added for debug on reception of Re-assoc Req. */
14240 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014241 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014242 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014243 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014244 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014245 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014246 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014247
14248 /* Pass the received FT IEs to SME */
14249 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
14250 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014251 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014252 return 0;
14253}
14254
14255/**
14256 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
14257 * @wiphy: Pointer to wiphy
14258 * @dev: Pointer to network device
14259 * @ftie: Pointer to fast transition ie parameter
14260 *
14261 * Return: 0 for success, non-zero for failure
14262 */
14263static int
14264wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
14265 struct net_device *dev,
14266 struct cfg80211_update_ft_ies_params *ftie)
14267{
14268 int ret;
14269
14270 cds_ssr_protect(__func__);
14271 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
14272 cds_ssr_unprotect(__func__);
14273
14274 return ret;
14275}
14276#endif
14277
14278#ifdef WLAN_FEATURE_GTK_OFFLOAD
14279/**
14280 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
14281 * @callbackContext: Callback context
14282 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
14283 *
14284 * Callback rountine called upon receiving response for get offload info
14285 *
14286 * Return: none
14287 */
14288void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
14289 tpSirGtkOffloadGetInfoRspParams
14290 pGtkOffloadGetInfoRsp)
14291{
14292 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
14293 uint8_t tempReplayCounter[8];
14294 hdd_station_ctx_t *pHddStaCtx;
14295
14296 ENTER();
14297
14298 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014299 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014300 return;
14301 }
14302
14303 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014304 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014305 return;
14306 }
14307
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014308 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014309 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014310 return;
14311 }
14312
14313 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14314 /* Update replay counter */
14315 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
14316 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14317
14318 {
14319 /* changing from little to big endian since supplicant
14320 * works on big endian format
14321 */
14322 int i;
14323 uint8_t *p =
14324 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14325
14326 for (i = 0; i < 8; i++) {
14327 tempReplayCounter[7 - i] = (uint8_t) p[i];
14328 }
14329 }
14330
14331 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014332 cfg80211_gtk_rekey_notify(pAdapter->dev,
14333 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014334 tempReplayCounter, GFP_KERNEL);
14335}
14336
14337/**
14338 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14339 * @wiphy: Pointer to wiphy
14340 * @dev: Pointer to network device
14341 * @data: Pointer to rekey data
14342 *
14343 * This function is used to offload GTK rekeying job to the firmware.
14344 *
14345 * Return: 0 for success, non-zero for failure
14346 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014347static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014348int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14349 struct net_device *dev,
14350 struct cfg80211_gtk_rekey_data *data)
14351{
14352 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14353 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14354 hdd_station_ctx_t *pHddStaCtx;
14355 tHalHandle hHal;
14356 int result;
14357 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014358 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014359
14360 ENTER();
14361
Anurag Chouhan6d760662016-02-20 16:05:43 +053014362 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014363 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014364 return -EINVAL;
14365 }
14366
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014367 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14368 hdd_err("invalid session id: %d", pAdapter->sessionId);
14369 return -EINVAL;
14370 }
14371
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014372 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014373 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
14374 pAdapter->sessionId, pAdapter->device_mode));
14375
14376 result = wlan_hdd_validate_context(pHddCtx);
14377
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014378 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014379 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014380
14381 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14382 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14383 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014384 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014385 return -EAGAIN;
14386 }
14387
14388 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
14389 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
14390 NL80211_KCK_LEN);
14391 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
14392 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053014393 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014394 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014395 {
14396 /* changing from big to little endian since driver
14397 * works on little endian format
14398 */
14399 uint8_t *p =
14400 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
14401 ullKeyReplayCounter;
14402 int i;
14403
14404 for (i = 0; i < 8; i++) {
14405 p[7 - i] = data->replay_ctr[i];
14406 }
14407 }
14408
14409 if (true == pHddCtx->hdd_wlan_suspended) {
14410 /* if wlan is suspended, enable GTK offload directly from here */
14411 memcpy(&hddGtkOffloadReqParams,
14412 &pHddStaCtx->gtkOffloadReqParams,
14413 sizeof(tSirGtkOffloadParams));
14414 status =
14415 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
14416 pAdapter->sessionId);
14417
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014418 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014419 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014420 status);
14421 return -EINVAL;
14422 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014423 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014424 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014425 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014426 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014427 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014428 return result;
14429}
14430
14431/**
14432 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14433 * @wiphy: Pointer to wiphy
14434 * @dev: Pointer to network device
14435 * @data: Pointer to rekey data
14436 *
14437 * This function is used to offload GTK rekeying job to the firmware.
14438 *
14439 * Return: 0 for success, non-zero for failure
14440 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014441static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014442int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14443 struct net_device *dev,
14444 struct cfg80211_gtk_rekey_data *data)
14445{
14446 int ret;
14447
14448 cds_ssr_protect(__func__);
14449 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
14450 cds_ssr_unprotect(__func__);
14451
14452 return ret;
14453}
14454#endif /*WLAN_FEATURE_GTK_OFFLOAD */
14455
14456/**
14457 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
14458 * @wiphy: Pointer to wiphy
14459 * @dev: Pointer to network device
14460 * @param: Pointer to access control parameter
14461 *
14462 * Return: 0 for success, non-zero for failure
14463 */
14464static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14465 struct net_device *dev,
14466 const struct cfg80211_acl_data *params)
14467{
14468 int i;
14469 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14470 hdd_hostapd_state_t *pHostapdState;
14471 tsap_Config_t *pConfig;
14472 v_CONTEXT_t p_cds_context = NULL;
14473 hdd_context_t *pHddCtx;
14474 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014475 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014476
14477 ENTER();
14478
Anurag Chouhan6d760662016-02-20 16:05:43 +053014479 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014480 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014481 return -EINVAL;
14482 }
14483
14484 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014485 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014486 return -EINVAL;
14487 }
14488
14489 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14490 status = wlan_hdd_validate_context(pHddCtx);
14491
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014492 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014493 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014494
14495 p_cds_context = pHddCtx->pcds_context;
14496 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14497
14498 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014499 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014500 return -EINVAL;
14501 }
14502
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014503 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014504 params->n_acl_entries);
14505
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014506 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014507 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
14508 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080014509 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014510 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
14511
14512 /* default value */
14513 pConfig->num_accept_mac = 0;
14514 pConfig->num_deny_mac = 0;
14515
14516 /**
14517 * access control policy
14518 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
14519 * listed in hostapd.deny file.
14520 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
14521 * listed in hostapd.accept file.
14522 */
14523 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
14524 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
14525 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
14526 params->acl_policy) {
14527 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
14528 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014529 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014530 params->acl_policy);
14531 return -ENOTSUPP;
14532 }
14533
14534 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
14535 pConfig->num_accept_mac = params->n_acl_entries;
14536 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014537 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
14538 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014539 MAC_ADDR_ARRAY(
14540 params->mac_addrs[i].addr));
14541
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014542 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014543 params->mac_addrs[i].addr,
14544 sizeof(qcmacaddr));
14545 }
14546 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
14547 pConfig->num_deny_mac = params->n_acl_entries;
14548 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014549 hdd_notice("** Add ACL MAC entry %i in BlackList :"
14550 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014551 MAC_ADDR_ARRAY(
14552 params->mac_addrs[i].addr));
14553
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014554 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014555 params->mac_addrs[i].addr,
14556 sizeof(qcmacaddr));
14557 }
14558 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070014559 qdf_status = wlansap_set_mac_acl(
14560 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014561 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014562 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014563 return -EINVAL;
14564 }
14565 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014566 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014567 hdd_device_mode_to_string(pAdapter->device_mode),
14568 pAdapter->device_mode);
14569 return -EINVAL;
14570 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014571 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014572 return 0;
14573}
14574
14575/**
14576 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
14577 * __wlan_hdd_cfg80211_set_mac_acl
14578 * @wiphy: pointer to wiphy structure
14579 * @dev: pointer to net_device
14580 * @params: pointer to cfg80211_acl_data
14581 *
14582 * Return; 0 on success, error number otherwise
14583 */
14584static int
14585wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14586 struct net_device *dev,
14587 const struct cfg80211_acl_data *params)
14588{
14589 int ret;
14590
14591 cds_ssr_protect(__func__);
14592 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
14593 cds_ssr_unprotect(__func__);
14594
14595 return ret;
14596}
14597
14598#ifdef WLAN_NL80211_TESTMODE
14599#ifdef FEATURE_WLAN_LPHB
14600/**
14601 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
14602 * @pHddCtx: Pointer to hdd context
14603 * @lphbInd: Pointer to low power heart beat indication parameter
14604 *
14605 * Return: none
14606 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014607static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
14608 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014609{
14610 struct sk_buff *skb;
14611
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014612 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014613
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014614 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014615 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014616
14617 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014618 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014619 return;
14620 }
14621
14622 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
14623 wiphy, sizeof(tSirLPHBInd),
14624 GFP_ATOMIC);
14625 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014626 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014627 return;
14628 }
14629
14630 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014631 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014632 goto nla_put_failure;
14633 }
14634 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014635 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014636 goto nla_put_failure;
14637 }
14638 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014639 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014640 goto nla_put_failure;
14641 }
14642 cfg80211_testmode_event(skb, GFP_ATOMIC);
14643 return;
14644
14645nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014646 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014647 kfree_skb(skb);
14648
14649 return;
14650}
14651#endif /* FEATURE_WLAN_LPHB */
14652
14653/**
14654 * __wlan_hdd_cfg80211_testmode() - test mode
14655 * @wiphy: Pointer to wiphy
14656 * @data: Data pointer
14657 * @len: Data length
14658 *
14659 * Return: 0 for success, non-zero for failure
14660 */
14661static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14662 void *data, int len)
14663{
14664 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
14665 int err;
14666 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14667
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014668 ENTER();
14669
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014670 err = wlan_hdd_validate_context(pHddCtx);
14671 if (err)
14672 return err;
14673
14674 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
14675 len, wlan_hdd_tm_policy);
14676 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014677 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014678 return err;
14679 }
14680
14681 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014682 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014683 return -EINVAL;
14684 }
14685
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014686 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014687 TRACE_CODE_HDD_CFG80211_TESTMODE,
14688 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014689 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
14690#ifdef FEATURE_WLAN_LPHB
14691 /* Low Power Heartbeat configuration request */
14692 case WLAN_HDD_TM_CMD_WLAN_HB:
14693 {
14694 int buf_len;
14695 void *buf;
14696 tSirLPHBReq *hb_params = NULL;
14697 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014698 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014699
14700 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014701 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014702 return -EINVAL;
14703 }
14704
14705 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14706 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14707
14708 hb_params_temp = (tSirLPHBReq *) buf;
14709 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
14710 && (hb_params_temp->params.lphbTcpParamReq.
14711 timePeriodSec == 0))
14712 return -EINVAL;
14713
14714 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014715 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014716 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014717 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014718 return -ENOMEM;
14719 }
14720
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014721 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014722 smeStatus =
14723 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
14724 hb_params,
14725 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014726 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014727 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014728 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014729 }
14730 return 0;
14731 }
14732#endif /* FEATURE_WLAN_LPHB */
14733
14734#if defined(QCA_WIFI_FTM)
14735 case WLAN_HDD_TM_CMD_WLAN_FTM:
14736 {
14737 int buf_len;
14738 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014739 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014740 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014741 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014742 return -EINVAL;
14743 }
14744
14745 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14746 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14747
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014748 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014749
14750 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
14751
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014752 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014753 err = -EBUSY;
14754 break;
14755 }
14756#endif
14757
14758 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014759 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014760 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
14761 return -EOPNOTSUPP;
14762 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014763 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014764 return err;
14765}
14766
14767/**
14768 * wlan_hdd_cfg80211_testmode() - test mode
14769 * @wiphy: Pointer to wiphy
14770 * @dev: Pointer to network device
14771 * @data: Data pointer
14772 * @len: Data length
14773 *
14774 * Return: 0 for success, non-zero for failure
14775 */
14776static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14777#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
14778 struct wireless_dev *wdev,
14779#endif
14780 void *data, int len)
14781{
14782 int ret;
14783
14784 cds_ssr_protect(__func__);
14785 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
14786 cds_ssr_unprotect(__func__);
14787
14788 return ret;
14789}
14790
14791#if defined(QCA_WIFI_FTM)
14792/**
14793 * wlan_hdd_testmode_rx_event() - test mode rx event handler
14794 * @buf: Pointer to buffer
14795 * @buf_len: Buffer length
14796 *
14797 * Return: none
14798 */
14799void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
14800{
14801 struct sk_buff *skb;
14802 hdd_context_t *hdd_ctx;
14803
14804 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014805 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014806 return;
14807 }
14808
Anurag Chouhan6d760662016-02-20 16:05:43 +053014809 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014810 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014811 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014812 return;
14813 }
14814
14815 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
14816 buf_len, GFP_KERNEL);
14817 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014818 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014819 return;
14820 }
14821
14822 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
14823 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
14824 goto nla_put_failure;
14825
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014826 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014827
14828 cfg80211_testmode_event(skb, GFP_KERNEL);
14829 return;
14830
14831nla_put_failure:
14832 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014833 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014834}
14835#endif
14836#endif /* CONFIG_NL80211_TESTMODE */
14837
14838#ifdef QCA_HT_2040_COEX
14839/**
14840 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14841 * @wiphy: Pointer to wiphy
14842 * @dev: Pointer to network device
14843 * @chandef: Pointer to channel definition parameter
14844 *
14845 * Return: 0 for success, non-zero for failure
14846 */
14847static int
14848__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14849 struct net_device *dev,
14850 struct cfg80211_chan_def *chandef)
14851{
14852 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14853 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014854 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014855 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053014856 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014857
Anurag Chouhan6d760662016-02-20 16:05:43 +053014858 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014859 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014860 return -EINVAL;
14861 }
14862
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014863 if (wlan_hdd_validate_session_id(pAdapter->sessionId)) {
14864 hdd_err("invalid session id: %d", pAdapter->sessionId);
14865 return -EINVAL;
14866 }
14867
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014868 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14869 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053014870 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014871 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014872
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014873 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014874 sme_get_config_param(pHddCtx->hHal, &sme_config);
14875 switch (chandef->width) {
14876 case NL80211_CHAN_WIDTH_20:
14877 if (sme_config.csrConfig.channelBondingMode24GHz !=
14878 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14879 sme_config.csrConfig.channelBondingMode24GHz =
14880 eCSR_INI_SINGLE_CHANNEL_CENTERED;
14881 sme_update_config(pHddCtx->hHal, &sme_config);
14882 cbModeChange = true;
14883 }
14884 break;
14885
14886 case NL80211_CHAN_WIDTH_40:
14887 if (sme_config.csrConfig.channelBondingMode24GHz ==
14888 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14889 if (NL80211_CHAN_HT40MINUS ==
14890 cfg80211_get_chandef_type(chandef))
14891 sme_config.csrConfig.channelBondingMode24GHz =
14892 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
14893 else
14894 sme_config.csrConfig.channelBondingMode24GHz =
14895 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
14896 sme_update_config(pHddCtx->hHal, &sme_config);
14897 cbModeChange = true;
14898 }
14899 break;
14900
14901 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014902 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014903 return -EINVAL;
14904 }
14905
14906 if (!cbModeChange)
14907 return 0;
14908
Krunal Sonib4326f22016-03-10 13:05:51 -080014909 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014910 return 0;
14911
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014912 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014913 sme_config.csrConfig.channelBondingMode24GHz);
14914
14915 /* Change SAP ht2040 mode */
14916 status = hdd_set_sap_ht2040_mode(pAdapter,
14917 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014918 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014919 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014920 return -EINVAL;
14921 }
14922
14923 return 0;
14924}
14925
14926/**
14927 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14928 * @wiphy: Pointer to wiphy
14929 * @dev: Pointer to network device
14930 * @chandef: Pointer to channel definition parameter
14931 *
14932 * Return: 0 for success, non-zero for failure
14933 */
14934static int
14935wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14936 struct net_device *dev,
14937 struct cfg80211_chan_def *chandef)
14938{
14939 int ret;
14940
14941 cds_ssr_protect(__func__);
14942 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
14943 cds_ssr_unprotect(__func__);
14944
14945 return ret;
14946}
14947#endif
14948
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014949#ifdef CHANNEL_SWITCH_SUPPORTED
14950/**
14951 * __wlan_hdd_cfg80211_channel_switch()- function to switch
14952 * channel in SAP/GO
14953 * @wiphy: wiphy pointer
14954 * @dev: dev pointer.
14955 * @csa_params: Change channel params
14956 *
14957 * This function is called to switch channel in SAP/GO
14958 *
14959 * Return: 0 if success else return non zero
14960 */
14961static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14962 struct net_device *dev,
14963 struct cfg80211_csa_settings *csa_params)
14964{
14965 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
14966 hdd_context_t *hdd_ctx;
14967 uint8_t channel;
14968 uint16_t freq;
14969 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080014970 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014971
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014972 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014973 csa_params->chandef.chan->center_freq);
14974
Hanumanth Reddy Pothulad9491f42016-10-24 19:08:38 +053014975 if (wlan_hdd_validate_session_id(adapter->sessionId)) {
14976 hdd_err("invalid session id: %d", adapter->sessionId);
14977 return -EINVAL;
14978 }
14979
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014980 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
14981 ret = wlan_hdd_validate_context(hdd_ctx);
14982
14983 if (0 != ret)
14984 return ret;
14985
Krunal Sonib4326f22016-03-10 13:05:51 -080014986 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
14987 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014988 return -ENOTSUPP;
14989
14990 freq = csa_params->chandef.chan->center_freq;
14991 channel = cds_freq_to_chan(freq);
14992
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053014993 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
14994
14995 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014996 return ret;
14997}
14998
14999/**
15000 * wlan_hdd_cfg80211_channel_switch()- function to switch
15001 * channel in SAP/GO
15002 * @wiphy: wiphy pointer
15003 * @dev: dev pointer.
15004 * @csa_params: Change channel params
15005 *
15006 * This function is called to switch channel in SAP/GO
15007 *
15008 * Return: 0 if success else return non zero
15009 */
15010static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
15011 struct net_device *dev,
15012 struct cfg80211_csa_settings *csa_params)
15013{
15014 int ret;
15015
15016 cds_ssr_protect(__func__);
15017 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
15018 cds_ssr_unprotect(__func__);
15019 return ret;
15020}
15021#endif
15022
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015023/**
15024 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
15025 * translation from NL to policy manager type
15026 * @type: Generic connection mode type defined in NL
15027 *
15028 *
15029 * This function provides the type translation
15030 *
15031 * Return: cds_con_mode enum
15032 */
15033enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
15034 enum nl80211_iftype type)
15035{
15036 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
15037 switch (type) {
15038 case NL80211_IFTYPE_STATION:
15039 mode = CDS_STA_MODE;
15040 break;
15041 case NL80211_IFTYPE_P2P_CLIENT:
15042 mode = CDS_P2P_CLIENT_MODE;
15043 break;
15044 case NL80211_IFTYPE_P2P_GO:
15045 mode = CDS_P2P_GO_MODE;
15046 break;
15047 case NL80211_IFTYPE_AP:
15048 mode = CDS_SAP_MODE;
15049 break;
15050 case NL80211_IFTYPE_ADHOC:
15051 mode = CDS_IBSS_MODE;
15052 break;
15053 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070015054 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015055 type);
15056 }
15057 return mode;
15058}
15059
15060/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015061 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
15062 * @wiphy: Handle to struct wiphy to get handle to module context.
15063 * @chandef: Contains information about the capture channel to be set.
15064 *
15065 * This interface is called if and only if monitor mode interface alone is
15066 * active.
15067 *
15068 * Return: 0 success or error code on failure.
15069 */
15070static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
15071 struct cfg80211_chan_def *chandef)
15072{
15073 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
15074 hdd_adapter_t *adapter;
15075 hdd_station_ctx_t *sta_ctx;
15076 struct hdd_mon_set_ch_info *ch_info;
15077 QDF_STATUS status;
15078 tHalHandle hal_hdl;
15079 struct qdf_mac_addr bssid;
15080 tCsrRoamProfile roam_profile;
15081 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070015082 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015083 int ret;
15084 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
15085
15086 ENTER();
15087
15088 ret = wlan_hdd_validate_context(hdd_ctx);
15089 if (ret)
15090 return ret;
15091
15092 hal_hdl = hdd_ctx->hHal;
15093
15094 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
15095 if (!adapter)
15096 return -EIO;
15097
15098 hdd_info("%s: set monitor mode Channel %d and freq %d",
15099 adapter->dev->name, chan_num, chandef->chan->center_freq);
15100
15101 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
15102 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015103 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
15104 roam_profile.ChannelInfo.numOfChannels = 1;
15105 roam_profile.phyMode = ch_info->phy_mode;
15106 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070015107 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015108
15109 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
15110 QDF_MAC_ADDR_SIZE);
15111
15112 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070015113 /*
15114 * CDS api expects secondary channel for calculating
15115 * the channel params
15116 */
15117 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
15118 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
15119 if (chan_num >= 1 && chan_num <= 5)
15120 sec_ch = chan_num + 4;
15121 else if (chan_num >= 6 && chan_num <= 13)
15122 sec_ch = chan_num - 4;
15123 }
15124 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015125 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
15126 &roam_profile);
15127 if (status) {
15128 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
15129 status);
15130 ret = qdf_status_to_os_return(status);
15131 return ret;
15132 }
15133 EXIT();
15134 return 0;
15135}
15136
15137/**
15138 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
15139 * @wiphy: Handle to struct wiphy to get handle to module context.
15140 * @chandef: Contains information about the capture channel to be set.
15141 *
15142 * This interface is called if and only if monitor mode interface alone is
15143 * active.
15144 *
15145 * Return: 0 success or error code on failure.
15146 */
15147static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
15148 struct cfg80211_chan_def *chandef)
15149{
15150 int ret;
15151
15152 cds_ssr_protect(__func__);
15153 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
15154 cds_ssr_unprotect(__func__);
15155 return ret;
15156}
15157
15158/**
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053015159 * wlan_hdd_clear_link_layer_stats() - clear link layer stats
15160 * @adapter: pointer to adapter
15161 *
15162 * Wrapper function to clear link layer stats.
15163 * return - void
15164 */
15165void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter)
15166{
15167 tSirLLStatsClearReq link_layer_stats_clear_req;
15168 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
15169
Mukul Sharma491021c2016-09-29 21:39:19 +053015170 link_layer_stats_clear_req.statsClearReqMask = WIFI_STATS_IFACE_AC |
15171 WIFI_STATS_IFACE_ALL_PEER;
Mahesh A Saptasagar6dda2022016-09-03 12:59:09 +053015172 link_layer_stats_clear_req.stopReq = 0;
15173 link_layer_stats_clear_req.reqId = 1;
15174 link_layer_stats_clear_req.staId = adapter->sessionId;
15175 sme_ll_stats_clear_req(hal, &link_layer_stats_clear_req);
15176
15177 return;
15178}
15179
15180/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015181 * struct cfg80211_ops - cfg80211_ops
15182 *
15183 * @add_virtual_intf: Add virtual interface
15184 * @del_virtual_intf: Delete virtual interface
15185 * @change_virtual_intf: Change virtual interface
15186 * @change_station: Change station
15187 * @add_beacon: Add beacon in sap mode
15188 * @del_beacon: Delete beacon in sap mode
15189 * @set_beacon: Set beacon in sap mode
15190 * @start_ap: Start ap
15191 * @change_beacon: Change beacon
15192 * @stop_ap: Stop ap
15193 * @change_bss: Change bss
15194 * @add_key: Add key
15195 * @get_key: Get key
15196 * @del_key: Delete key
15197 * @set_default_key: Set default key
15198 * @set_channel: Set channel
15199 * @scan: Scan
15200 * @connect: Connect
15201 * @disconnect: Disconnect
15202 * @join_ibss = Join ibss
15203 * @leave_ibss = Leave ibss
15204 * @set_wiphy_params = Set wiphy params
15205 * @set_tx_power = Set tx power
15206 * @get_tx_power = get tx power
15207 * @remain_on_channel = Remain on channel
15208 * @cancel_remain_on_channel = Cancel remain on channel
15209 * @mgmt_tx = Tx management frame
15210 * @mgmt_tx_cancel_wait = Cancel management tx wait
15211 * @set_default_mgmt_key = Set default management key
15212 * @set_txq_params = Set tx queue parameters
15213 * @get_station = Get station
15214 * @set_power_mgmt = Set power management
15215 * @del_station = Delete station
15216 * @add_station = Add station
15217 * @set_pmksa = Set pmksa
15218 * @del_pmksa = Delete pmksa
15219 * @flush_pmksa = Flush pmksa
15220 * @update_ft_ies = Update FT IEs
15221 * @tdls_mgmt = Tdls management
15222 * @tdls_oper = Tdls operation
15223 * @set_rekey_data = Set rekey data
15224 * @sched_scan_start = Scheduled scan start
15225 * @sched_scan_stop = Scheduled scan stop
15226 * @resume = Resume wlan
15227 * @suspend = Suspend wlan
15228 * @set_mac_acl = Set mac acl
15229 * @testmode_cmd = Test mode command
15230 * @set_ap_chanwidth = Set AP channel bandwidth
15231 * @dump_survey = Dump survey
15232 * @key_mgmt_set_pmk = Set pmk key management
15233 */
15234static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
15235 .add_virtual_intf = wlan_hdd_add_virtual_intf,
15236 .del_virtual_intf = wlan_hdd_del_virtual_intf,
15237 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
15238 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015239 .start_ap = wlan_hdd_cfg80211_start_ap,
15240 .change_beacon = wlan_hdd_cfg80211_change_beacon,
15241 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015242 .change_bss = wlan_hdd_cfg80211_change_bss,
15243 .add_key = wlan_hdd_cfg80211_add_key,
15244 .get_key = wlan_hdd_cfg80211_get_key,
15245 .del_key = wlan_hdd_cfg80211_del_key,
15246 .set_default_key = wlan_hdd_cfg80211_set_default_key,
15247 .scan = wlan_hdd_cfg80211_scan,
15248 .connect = wlan_hdd_cfg80211_connect,
15249 .disconnect = wlan_hdd_cfg80211_disconnect,
15250 .join_ibss = wlan_hdd_cfg80211_join_ibss,
15251 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
15252 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
15253 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
15254 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
15255 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
15256 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
15257 .mgmt_tx = wlan_hdd_mgmt_tx,
15258 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
15259 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
15260 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053015261 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015262 .get_station = wlan_hdd_cfg80211_get_station,
15263 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
15264 .del_station = wlan_hdd_cfg80211_del_station,
15265 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015266 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
15267 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
15268 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080015269#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015270 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
15271#endif
15272#ifdef FEATURE_WLAN_TDLS
15273 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
15274 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
15275#endif
15276#ifdef WLAN_FEATURE_GTK_OFFLOAD
15277 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
15278#endif /* WLAN_FEATURE_GTK_OFFLOAD */
15279#ifdef FEATURE_WLAN_SCAN_PNO
15280 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
15281 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
15282#endif /*FEATURE_WLAN_SCAN_PNO */
15283 .resume = wlan_hdd_cfg80211_resume_wlan,
15284 .suspend = wlan_hdd_cfg80211_suspend_wlan,
15285 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
15286#ifdef WLAN_NL80211_TESTMODE
15287 .testmode_cmd = wlan_hdd_cfg80211_testmode,
15288#endif
15289#ifdef QCA_HT_2040_COEX
15290 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
15291#endif
15292 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053015293#ifdef CHANNEL_SWITCH_SUPPORTED
15294 .channel_switch = wlan_hdd_cfg80211_channel_switch,
15295#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070015296 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053015297#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
15298 defined(CFG80211_ABORT_SCAN)
15299 .abort_scan = wlan_hdd_cfg80211_abort_scan,
15300#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080015301};