blob: 991b36cecef3f9945a8068ded8ffb5dcba39214d [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08002 * Copyright (c) 2012-2016 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"
77
78#ifdef FEATURE_WLAN_EXTSCAN
79#include "wlan_hdd_ext_scan.h"
80#endif
81
82#ifdef WLAN_FEATURE_LINK_LAYER_STATS
83#include "wlan_hdd_stats.h"
84#endif
85#include "cds_concurrency.h"
86#include "qwlan_version.h"
87#include "wlan_hdd_memdump.h"
88
89#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070090#include "wlan_hdd_tsf.h"
Manikandan Mohanb6315dd2016-05-10 16:16:36 -070091#include "ol_txrx.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080092
Ravi Joshideb5a8d2015-11-09 19:11:43 -080093#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +053094#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070095#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -070096#include "wlan_hdd_nan_datapath.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -080097
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080098#define g_mode_rates_size (12)
99#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800100#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
101 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
102
103/*
104 * Android CTS verifier needs atleast this much wait time (in msec)
105 */
106#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
107
108/*
109 * Refer @tCfgProtection structure for definition of the bit map.
110 * below value is obtained by setting the following bit-fields.
111 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
112 */
113#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
114
115#define HDD2GHZCHAN(freq, chan, flag) { \
116 .band = IEEE80211_BAND_2GHZ, \
117 .center_freq = (freq), \
118 .hw_value = (chan), \
119 .flags = (flag), \
120 .max_antenna_gain = 0, \
121 .max_power = 30, \
122}
123
124#define HDD5GHZCHAN(freq, chan, flag) { \
125 .band = IEEE80211_BAND_5GHZ, \
126 .center_freq = (freq), \
127 .hw_value = (chan), \
128 .flags = (flag), \
129 .max_antenna_gain = 0, \
130 .max_power = 30, \
131}
132
133#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
134 { \
135 .bitrate = rate, \
136 .hw_value = rate_id, \
137 .flags = flag, \
138 }
139
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800140#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
141#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800142
143#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800144
Peng Xu4d67c8f2015-10-16 16:02:26 -0700145#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530146#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700147
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800148static const u32 hdd_cipher_suites[] = {
149 WLAN_CIPHER_SUITE_WEP40,
150 WLAN_CIPHER_SUITE_WEP104,
151 WLAN_CIPHER_SUITE_TKIP,
152#ifdef FEATURE_WLAN_ESE
153#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
154#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
155 WLAN_CIPHER_SUITE_BTK,
156 WLAN_CIPHER_SUITE_KRK,
157 WLAN_CIPHER_SUITE_CCMP,
158#else
159 WLAN_CIPHER_SUITE_CCMP,
160#endif
161#ifdef FEATURE_WLAN_WAPI
162 WLAN_CIPHER_SUITE_SMS4,
163#endif
164#ifdef WLAN_FEATURE_11W
165 WLAN_CIPHER_SUITE_AES_CMAC,
166#endif
167};
168
Abhishek Singhf512bf32016-05-04 16:47:46 +0530169static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800170 HDD2GHZCHAN(2412, 1, 0),
171 HDD2GHZCHAN(2417, 2, 0),
172 HDD2GHZCHAN(2422, 3, 0),
173 HDD2GHZCHAN(2427, 4, 0),
174 HDD2GHZCHAN(2432, 5, 0),
175 HDD2GHZCHAN(2437, 6, 0),
176 HDD2GHZCHAN(2442, 7, 0),
177 HDD2GHZCHAN(2447, 8, 0),
178 HDD2GHZCHAN(2452, 9, 0),
179 HDD2GHZCHAN(2457, 10, 0),
180 HDD2GHZCHAN(2462, 11, 0),
181 HDD2GHZCHAN(2467, 12, 0),
182 HDD2GHZCHAN(2472, 13, 0),
183 HDD2GHZCHAN(2484, 14, 0),
184};
185
Abhishek Singhf512bf32016-05-04 16:47:46 +0530186static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800187 HDD5GHZCHAN(5180, 36, 0),
188 HDD5GHZCHAN(5200, 40, 0),
189 HDD5GHZCHAN(5220, 44, 0),
190 HDD5GHZCHAN(5240, 48, 0),
191 HDD5GHZCHAN(5260, 52, 0),
192 HDD5GHZCHAN(5280, 56, 0),
193 HDD5GHZCHAN(5300, 60, 0),
194 HDD5GHZCHAN(5320, 64, 0),
195 HDD5GHZCHAN(5500, 100, 0),
196 HDD5GHZCHAN(5520, 104, 0),
197 HDD5GHZCHAN(5540, 108, 0),
198 HDD5GHZCHAN(5560, 112, 0),
199 HDD5GHZCHAN(5580, 116, 0),
200 HDD5GHZCHAN(5600, 120, 0),
201 HDD5GHZCHAN(5620, 124, 0),
202 HDD5GHZCHAN(5640, 128, 0),
203 HDD5GHZCHAN(5660, 132, 0),
204 HDD5GHZCHAN(5680, 136, 0),
205 HDD5GHZCHAN(5700, 140, 0),
206 HDD5GHZCHAN(5720, 144, 0),
207 HDD5GHZCHAN(5745, 149, 0),
208 HDD5GHZCHAN(5765, 153, 0),
209 HDD5GHZCHAN(5785, 157, 0),
210 HDD5GHZCHAN(5805, 161, 0),
211 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800212 HDD5GHZCHAN(5852, 170, 0),
213 HDD5GHZCHAN(5855, 171, 0),
214 HDD5GHZCHAN(5860, 172, 0),
215 HDD5GHZCHAN(5865, 173, 0),
216 HDD5GHZCHAN(5870, 174, 0),
217 HDD5GHZCHAN(5875, 175, 0),
218 HDD5GHZCHAN(5880, 176, 0),
219 HDD5GHZCHAN(5885, 177, 0),
220 HDD5GHZCHAN(5890, 178, 0),
221 HDD5GHZCHAN(5895, 179, 0),
222 HDD5GHZCHAN(5900, 180, 0),
223 HDD5GHZCHAN(5905, 181, 0),
224 HDD5GHZCHAN(5910, 182, 0),
225 HDD5GHZCHAN(5915, 183, 0),
226 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800227};
228
229static struct ieee80211_rate g_mode_rates[] = {
230 HDD_G_MODE_RATETAB(10, 0x1, 0),
231 HDD_G_MODE_RATETAB(20, 0x2, 0),
232 HDD_G_MODE_RATETAB(55, 0x4, 0),
233 HDD_G_MODE_RATETAB(110, 0x8, 0),
234 HDD_G_MODE_RATETAB(60, 0x10, 0),
235 HDD_G_MODE_RATETAB(90, 0x20, 0),
236 HDD_G_MODE_RATETAB(120, 0x40, 0),
237 HDD_G_MODE_RATETAB(180, 0x80, 0),
238 HDD_G_MODE_RATETAB(240, 0x100, 0),
239 HDD_G_MODE_RATETAB(360, 0x200, 0),
240 HDD_G_MODE_RATETAB(480, 0x400, 0),
241 HDD_G_MODE_RATETAB(540, 0x800, 0),
242};
243
244static struct ieee80211_rate a_mode_rates[] = {
245 HDD_G_MODE_RATETAB(60, 0x10, 0),
246 HDD_G_MODE_RATETAB(90, 0x20, 0),
247 HDD_G_MODE_RATETAB(120, 0x40, 0),
248 HDD_G_MODE_RATETAB(180, 0x80, 0),
249 HDD_G_MODE_RATETAB(240, 0x100, 0),
250 HDD_G_MODE_RATETAB(360, 0x200, 0),
251 HDD_G_MODE_RATETAB(480, 0x400, 0),
252 HDD_G_MODE_RATETAB(540, 0x800, 0),
253};
254
255static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530256 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800257 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
258 .band = IEEE80211_BAND_2GHZ,
259 .bitrates = g_mode_rates,
260 .n_bitrates = g_mode_rates_size,
261 .ht_cap.ht_supported = 1,
262 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
263 | IEEE80211_HT_CAP_GRN_FLD
264 | IEEE80211_HT_CAP_DSSSCCK40
265 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
266 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
267 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
268 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
269 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
270 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
271 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
272};
273
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800274static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530275 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800276 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
277 .band = IEEE80211_BAND_5GHZ,
278 .bitrates = a_mode_rates,
279 .n_bitrates = a_mode_rates_size,
280 .ht_cap.ht_supported = 1,
281 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
282 | IEEE80211_HT_CAP_GRN_FLD
283 | IEEE80211_HT_CAP_DSSSCCK40
284 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
285 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
286 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
287 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
288 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
289 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
290 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
291 .vht_cap.vht_supported = 1,
292};
293
294/* This structure contain information what kind of frame are expected in
295 TX/RX direction for each kind of interface */
296static const struct ieee80211_txrx_stypes
297 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
298 [NL80211_IFTYPE_STATION] = {
299 .tx = 0xffff,
300 .rx = BIT(SIR_MAC_MGMT_ACTION) |
301 BIT(SIR_MAC_MGMT_PROBE_REQ),
302 },
303 [NL80211_IFTYPE_AP] = {
304 .tx = 0xffff,
305 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
306 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
307 BIT(SIR_MAC_MGMT_PROBE_REQ) |
308 BIT(SIR_MAC_MGMT_DISASSOC) |
309 BIT(SIR_MAC_MGMT_AUTH) |
310 BIT(SIR_MAC_MGMT_DEAUTH) |
311 BIT(SIR_MAC_MGMT_ACTION),
312 },
313 [NL80211_IFTYPE_ADHOC] = {
314 .tx = 0xffff,
315 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
316 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
317 BIT(SIR_MAC_MGMT_PROBE_REQ) |
318 BIT(SIR_MAC_MGMT_DISASSOC) |
319 BIT(SIR_MAC_MGMT_AUTH) |
320 BIT(SIR_MAC_MGMT_DEAUTH) |
321 BIT(SIR_MAC_MGMT_ACTION),
322 },
323 [NL80211_IFTYPE_P2P_CLIENT] = {
324 .tx = 0xffff,
325 .rx = BIT(SIR_MAC_MGMT_ACTION) |
326 BIT(SIR_MAC_MGMT_PROBE_REQ),
327 },
328 [NL80211_IFTYPE_P2P_GO] = {
329 /* This is also same as for SoftAP */
330 .tx = 0xffff,
331 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
332 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
333 BIT(SIR_MAC_MGMT_PROBE_REQ) |
334 BIT(SIR_MAC_MGMT_DISASSOC) |
335 BIT(SIR_MAC_MGMT_AUTH) |
336 BIT(SIR_MAC_MGMT_DEAUTH) |
337 BIT(SIR_MAC_MGMT_ACTION),
338 },
339};
340
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800341/* Interface limits and combinations registered by the driver */
342
343/* STA ( + STA ) combination */
344static const struct ieee80211_iface_limit
345 wlan_hdd_sta_iface_limit[] = {
346 {
347 .max = 3, /* p2p0 is a STA as well */
348 .types = BIT(NL80211_IFTYPE_STATION),
349 },
350};
351
352/* ADHOC (IBSS) limit */
353static const struct ieee80211_iface_limit
354 wlan_hdd_adhoc_iface_limit[] = {
355 {
356 .max = 1,
357 .types = BIT(NL80211_IFTYPE_STATION),
358 },
359 {
360 .max = 1,
361 .types = BIT(NL80211_IFTYPE_ADHOC),
362 },
363};
364
365/* AP ( + AP ) combination */
366static const struct ieee80211_iface_limit
367 wlan_hdd_ap_iface_limit[] = {
368 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530369 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800370 .types = BIT(NL80211_IFTYPE_AP),
371 },
372};
373
374/* P2P limit */
375static const struct ieee80211_iface_limit
376 wlan_hdd_p2p_iface_limit[] = {
377 {
378 .max = 1,
379 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
380 },
381 {
382 .max = 1,
383 .types = BIT(NL80211_IFTYPE_P2P_GO),
384 },
385};
386
387static const struct ieee80211_iface_limit
388 wlan_hdd_sta_ap_iface_limit[] = {
389 {
390 /* We need 1 extra STA interface for OBSS scan when SAP starts
391 * with HT40 in STA+SAP concurrency mode
392 */
393 .max = (1 + SAP_MAX_OBSS_STA_CNT),
394 .types = BIT(NL80211_IFTYPE_STATION),
395 },
396 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530397 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800398 .types = BIT(NL80211_IFTYPE_AP),
399 },
400};
401
402/* STA + P2P combination */
403static const struct ieee80211_iface_limit
404 wlan_hdd_sta_p2p_iface_limit[] = {
405 {
406 /* One reserved for dedicated P2PDEV usage */
407 .max = 2,
408 .types = BIT(NL80211_IFTYPE_STATION)
409 },
410 {
411 /* Support for two identical (GO + GO or CLI + CLI)
412 * or dissimilar (GO + CLI) P2P interfaces
413 */
414 .max = 2,
415 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
416 },
417};
418
419/* STA + AP + P2PGO combination */
420static const struct ieee80211_iface_limit
421wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
422 /* Support for AP+P2PGO interfaces */
423 {
424 .max = 2,
425 .types = BIT(NL80211_IFTYPE_STATION)
426 },
427 {
428 .max = 1,
429 .types = BIT(NL80211_IFTYPE_P2P_GO)
430 },
431 {
432 .max = 1,
433 .types = BIT(NL80211_IFTYPE_AP)
434 }
435};
436
437/* SAP + P2P combination */
438static const struct ieee80211_iface_limit
439wlan_hdd_sap_p2p_iface_limit[] = {
440 {
441 /* 1 dedicated for p2p0 which is a STA type */
442 .max = 1,
443 .types = BIT(NL80211_IFTYPE_STATION)
444 },
445 {
446 /* The p2p interface in SAP+P2P can be GO/CLI.
447 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
448 */
449 .max = 1,
450 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
451 },
452 {
453 /* SAP+GO to support only one SAP interface */
454 .max = 1,
455 .types = BIT(NL80211_IFTYPE_AP)
456 }
457};
458
459/* P2P + P2P combination */
460static const struct ieee80211_iface_limit
461wlan_hdd_p2p_p2p_iface_limit[] = {
462 {
463 /* 1 dedicated for p2p0 which is a STA type */
464 .max = 1,
465 .types = BIT(NL80211_IFTYPE_STATION)
466 },
467 {
468 /* The p2p interface in P2P+P2P can be GO/CLI.
469 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
470 */
471 .max = 2,
472 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
473 },
474};
475
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700476static const struct ieee80211_iface_limit
477 wlan_hdd_mon_iface_limit[] = {
478 {
479 .max = 3, /* Monitor interface */
480 .types = BIT(NL80211_IFTYPE_MONITOR),
481 },
482};
483
484static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800485 wlan_hdd_iface_combination[] = {
486 /* STA */
487 {
488 .limits = wlan_hdd_sta_iface_limit,
489 .num_different_channels = 2,
490 .max_interfaces = 3,
491 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
492 },
493 /* ADHOC */
494 {
495 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700496 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800497 .max_interfaces = 2,
498 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
499 },
500 /* AP */
501 {
502 .limits = wlan_hdd_ap_iface_limit,
503 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530504 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800505 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
506 },
507 /* P2P */
508 {
509 .limits = wlan_hdd_p2p_iface_limit,
510 .num_different_channels = 2,
511 .max_interfaces = 2,
512 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
513 },
514 /* STA + AP */
515 {
516 .limits = wlan_hdd_sta_ap_iface_limit,
517 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530518 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800519 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
520 .beacon_int_infra_match = true,
521 },
522 /* STA + P2P */
523 {
524 .limits = wlan_hdd_sta_p2p_iface_limit,
525 .num_different_channels = 2,
526 /* one interface reserved for P2PDEV dedicated usage */
527 .max_interfaces = 4,
528 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
529 .beacon_int_infra_match = true,
530 },
531 /* STA + P2P GO + SAP */
532 {
533 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
534 /* we can allow 3 channels for three different persona
535 * but due to firmware limitation, allow max 2 concrnt channels.
536 */
537 .num_different_channels = 2,
538 /* one interface reserved for P2PDEV dedicated usage */
539 .max_interfaces = 4,
540 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
541 .beacon_int_infra_match = true,
542 },
543 /* SAP + P2P */
544 {
545 .limits = wlan_hdd_sap_p2p_iface_limit,
546 .num_different_channels = 2,
547 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
548 .max_interfaces = 3,
549 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
550 .beacon_int_infra_match = true,
551 },
552 /* P2P + P2P */
553 {
554 .limits = wlan_hdd_p2p_p2p_iface_limit,
555 .num_different_channels = 2,
556 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
557 .max_interfaces = 3,
558 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
559 .beacon_int_infra_match = true,
560 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530561 /* Monitor */
562 {
563 .limits = wlan_hdd_mon_iface_limit,
564 .max_interfaces = 3,
565 .num_different_channels = 2,
566 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
567 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800568};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800569
570static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Arun Khandavalli2476ef52016-04-26 20:19:43 +0530571struct hdd_bpf_context bpf_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800572
573#ifdef WLAN_NL80211_TESTMODE
574enum wlan_hdd_tm_attr {
575 WLAN_HDD_TM_ATTR_INVALID = 0,
576 WLAN_HDD_TM_ATTR_CMD = 1,
577 WLAN_HDD_TM_ATTR_DATA = 2,
578 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
579 WLAN_HDD_TM_ATTR_TYPE = 4,
580 /* keep last */
581 WLAN_HDD_TM_ATTR_AFTER_LAST,
582 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
583};
584
585enum wlan_hdd_tm_cmd {
586 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
587 WLAN_HDD_TM_CMD_WLAN_HB = 1,
588};
589
590#define WLAN_HDD_TM_DATA_MAX_LEN 5000
591
592static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
593 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
594 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
595 .len = WLAN_HDD_TM_DATA_MAX_LEN},
596};
597#endif /* WLAN_NL80211_TESTMODE */
598
599#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
600static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
601 .flags = WIPHY_WOWLAN_MAGIC_PKT,
602 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
603 .pattern_min_len = 1,
604 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
605};
606#endif
607
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800608/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530609 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
610 * @flags: Pointer to the flags to Add channel switch flag.
611 *
612 * This Function adds Channel Switch support flag, if channel switch is
613 * supported by kernel.
614 * Return: void.
615 */
616#ifdef CHANNEL_SWITCH_SUPPORTED
617static inline void hdd_add_channel_switch_support(uint32_t *flags)
618{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800619 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530620 return;
621}
622#else
623static inline void hdd_add_channel_switch_support(uint32_t *flags)
624{
625 return;
626}
627#endif
628
Manikandan Mohan22b83722015-12-15 15:03:23 -0800629#ifdef FEATURE_WLAN_TDLS
630
631/* TDLS capabilities params */
632#define PARAM_MAX_TDLS_SESSION \
633 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
634#define PARAM_TDLS_FEATURE_SUPPORT \
635 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
636
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530637/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800638 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
639 * @wiphy: WIPHY structure pointer
640 * @wdev: Wireless device structure pointer
641 * @data: Pointer to the data received
642 * @data_len: Length of the data received
643 *
644 * This function provides TDLS capabilities
645 *
646 * Return: 0 on success and errno on failure
647 */
648static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
649 struct wireless_dev *wdev,
650 const void *data,
651 int data_len)
652{
653 int status;
654 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
655 struct sk_buff *skb;
656 uint32_t set = 0;
657
Jeff Johnson1f61b612016-02-12 16:28:33 -0800658 ENTER_DEV(wdev->netdev);
659
Anurag Chouhan6d760662016-02-20 16:05:43 +0530660 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800661 hdd_err("Command not allowed in FTM mode");
662 return -EPERM;
663 }
664
665 status = wlan_hdd_validate_context(hdd_ctx);
666 if (status)
667 return status;
668
669 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
670 NLMSG_HDRLEN);
671 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700672 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800673 goto fail;
674 }
675
676 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Jeff Johnson020db452016-06-29 14:37:26 -0700677 hdd_err("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800678 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
679 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700680 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800681 goto fail;
682 }
683 } else {
684 set = set | WIFI_TDLS_SUPPORT;
685 set = set | (hdd_ctx->config->fTDLSExternalControl ?
686 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
687 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
688 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Jeff Johnson020db452016-06-29 14:37:26 -0700689 hdd_notice("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800690 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
691 hdd_ctx->max_num_tdls_sta) ||
692 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
693 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700694 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800695 goto fail;
696 }
697 }
698 return cfg80211_vendor_cmd_reply(skb);
699fail:
700 if (skb)
701 kfree_skb(skb);
702 return -EINVAL;
703}
704
705/**
706 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
707 * @wiphy: WIPHY structure pointer
708 * @wdev: Wireless device structure pointer
709 * @data: Pointer to the data received
710 * @data_len: Length of the data received
711 *
712 * This function provides TDLS capabilities
713 *
714 * Return: 0 on success and errno on failure
715 */
716static int
717wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
718 struct wireless_dev *wdev,
719 const void *data,
720 int data_len)
721{
722 int ret;
723
724 cds_ssr_protect(__func__);
725 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
726 data, data_len);
727 cds_ssr_unprotect(__func__);
728
729 return ret;
730}
731#endif
732
733#ifdef QCA_HT_2040_COEX
734static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
735#endif
736
737#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
738/*
739 * FUNCTION: wlan_hdd_send_avoid_freq_event
740 * This is called when wlan driver needs to send vendor specific
741 * avoid frequency range event to userspace
742 */
743int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
744 tHddAvoidFreqList *pAvoidFreqList)
745{
746 struct sk_buff *vendor_event;
747
748 ENTER();
749
750 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700751 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800752 return -EINVAL;
753 }
754
755 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700756 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800757 return -EINVAL;
758 }
759
760 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
761 NULL,
762 sizeof(tHddAvoidFreqList),
763 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
764 GFP_KERNEL);
765 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700766 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800767 return -EINVAL;
768 }
769
770 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
771 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
772
773 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
774
775 EXIT();
776 return 0;
777}
778#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
779
780/* vendor specific events */
781static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
782#ifdef FEATURE_WLAN_CH_AVOID
783 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
784 .vendor_id =
785 QCA_NL80211_VENDOR_ID,
786 .subcmd =
787 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
788 },
789#endif /* FEATURE_WLAN_CH_AVOID */
790
791#ifdef WLAN_FEATURE_NAN
792 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
793 .vendor_id =
794 QCA_NL80211_VENDOR_ID,
795 .subcmd =
796 QCA_NL80211_VENDOR_SUBCMD_NAN
797 },
798#endif
799
800#ifdef WLAN_FEATURE_STATS_EXT
801 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
802 .vendor_id =
803 QCA_NL80211_VENDOR_ID,
804 .subcmd =
805 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
806 },
807#endif /* WLAN_FEATURE_STATS_EXT */
808#ifdef FEATURE_WLAN_EXTSCAN
809 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
810 .vendor_id =
811 QCA_NL80211_VENDOR_ID,
812 .subcmd =
813 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
814 },
815 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
816 .vendor_id =
817 QCA_NL80211_VENDOR_ID,
818 .subcmd =
819 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
820 },
821 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
822 .
823 vendor_id
824 =
825 QCA_NL80211_VENDOR_ID,
826 .subcmd =
827 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
828 },
829 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
830 .
831 vendor_id
832 =
833 QCA_NL80211_VENDOR_ID,
834 .
835 subcmd =
836 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
837 },
838 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
839 .
840 vendor_id
841 =
842 QCA_NL80211_VENDOR_ID,
843 .
844 subcmd
845 =
846 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
847 },
848 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
849 .
850 vendor_id
851 =
852 QCA_NL80211_VENDOR_ID,
853 .subcmd =
854 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
855 },
856 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
857 .vendor_id =
858 QCA_NL80211_VENDOR_ID,
859 .subcmd =
860 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
861 },
862 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
863 .
864 vendor_id
865 =
866 QCA_NL80211_VENDOR_ID,
867 .subcmd =
868 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
869 },
870 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
871 .
872 vendor_id
873 =
874 QCA_NL80211_VENDOR_ID,
875 .subcmd =
876 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
877 },
878 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
879 .
880 vendor_id
881 =
882 QCA_NL80211_VENDOR_ID,
883 .
884 subcmd
885 =
886 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
887 },
888 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
889 .
890 vendor_id
891 =
892 QCA_NL80211_VENDOR_ID,
893 .
894 subcmd =
895 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
896 },
897 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
898 .
899 vendor_id
900 =
901 QCA_NL80211_VENDOR_ID,
902 .
903 subcmd
904 =
905 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
906 },
907 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
908 .
909 vendor_id
910 =
911 QCA_NL80211_VENDOR_ID,
912 .
913 subcmd
914 =
915 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
916 },
917 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
918 .vendor_id = QCA_NL80211_VENDOR_ID,
919 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
920 },
921 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
922 .vendor_id = QCA_NL80211_VENDOR_ID,
923 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
924 },
925#endif /* FEATURE_WLAN_EXTSCAN */
926
927#ifdef WLAN_FEATURE_LINK_LAYER_STATS
928 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
929 .vendor_id =
930 QCA_NL80211_VENDOR_ID,
931 .subcmd =
932 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
933 },
934 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
935 .vendor_id =
936 QCA_NL80211_VENDOR_ID,
937 .subcmd =
938 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
939 },
940 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
941 .vendor_id =
942 QCA_NL80211_VENDOR_ID,
943 .subcmd =
944 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
945 },
946 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
947 .vendor_id =
948 QCA_NL80211_VENDOR_ID,
949 .subcmd =
950 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
951 },
952 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
953 .vendor_id =
954 QCA_NL80211_VENDOR_ID,
955 .subcmd =
956 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
957 },
958 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
959 .vendor_id =
960 QCA_NL80211_VENDOR_ID,
961 .subcmd =
962 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
963 },
964#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
965 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
966 .vendor_id =
967 QCA_NL80211_VENDOR_ID,
968 .subcmd =
969 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
970 },
971 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
972 .vendor_id = QCA_NL80211_VENDOR_ID,
973 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
974 },
975#ifdef WLAN_FEATURE_ROAM_OFFLOAD
976 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
977 .vendor_id =
978 QCA_NL80211_VENDOR_ID,
979 .subcmd =
980 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
981 },
982#endif
983 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
984 .vendor_id =
985 QCA_NL80211_VENDOR_ID,
986 .subcmd =
987 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
988 },
989 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
990 .vendor_id =
991 QCA_NL80211_VENDOR_ID,
992 .subcmd =
993 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
994 },
995 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
996 .vendor_id =
997 QCA_NL80211_VENDOR_ID,
998 .subcmd =
999 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1000 },
1001 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1002 .vendor_id =
1003 QCA_NL80211_VENDOR_ID,
1004 .subcmd =
1005 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1006 },
1007 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1008 .vendor_id =
1009 QCA_NL80211_VENDOR_ID,
1010 .subcmd =
1011 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1012 },
1013#ifdef FEATURE_WLAN_EXTSCAN
1014 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1015 .vendor_id = QCA_NL80211_VENDOR_ID,
1016 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1017 },
1018 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1019 .vendor_id = QCA_NL80211_VENDOR_ID,
1020 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1021 },
1022 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1023 .vendor_id = QCA_NL80211_VENDOR_ID,
1024 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1025 },
1026 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1027 .vendor_id = QCA_NL80211_VENDOR_ID,
1028 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1029 },
1030 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1031 .vendor_id = QCA_NL80211_VENDOR_ID,
1032 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1033 },
1034#endif /* FEATURE_WLAN_EXTSCAN */
1035 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1036 .vendor_id = QCA_NL80211_VENDOR_ID,
1037 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1038 },
1039#ifdef WLAN_FEATURE_MEMDUMP
1040 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1041 .vendor_id = QCA_NL80211_VENDOR_ID,
1042 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1043 },
1044#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001045#ifdef WLAN_FEATURE_TSF
1046 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1047 .vendor_id = QCA_NL80211_VENDOR_ID,
1048 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1049 },
1050#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001051 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1052 .vendor_id = QCA_NL80211_VENDOR_ID,
1053 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1054 },
1055 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1056 .vendor_id = QCA_NL80211_VENDOR_ID,
1057 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1058 },
1059 /* OCB events */
1060 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1061 .vendor_id = QCA_NL80211_VENDOR_ID,
1062 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1063 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001064#ifdef FEATURE_LFR_SUBNET_DETECTION
1065 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1066 .vendor_id = QCA_NL80211_VENDOR_ID,
1067 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1068 },
1069#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001070
1071#ifdef WLAN_FEATURE_NAN_DATAPATH
1072 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1073 .vendor_id = QCA_NL80211_VENDOR_ID,
1074 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1075 },
1076#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001077
1078 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1079 .vendor_id = QCA_NL80211_VENDOR_ID,
1080 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1081 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301082 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1083 .vendor_id = QCA_NL80211_VENDOR_ID,
1084 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1085 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001086};
1087
1088/**
1089 * __is_driver_dfs_capable() - get driver DFS capability
1090 * @wiphy: pointer to wireless wiphy structure.
1091 * @wdev: pointer to wireless_dev structure.
1092 * @data: Pointer to the data to be passed via vendor interface
1093 * @data_len:Length of the data to be passed
1094 *
1095 * This function is called by userspace to indicate whether or not
1096 * the driver supports DFS offload.
1097 *
1098 * Return: 0 on success, negative errno on failure
1099 */
1100static int __is_driver_dfs_capable(struct wiphy *wiphy,
1101 struct wireless_dev *wdev,
1102 const void *data,
1103 int data_len)
1104{
1105 u32 dfs_capability = 0;
1106 struct sk_buff *temp_skbuff;
1107 int ret_val;
1108 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1109
Jeff Johnson1f61b612016-02-12 16:28:33 -08001110 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001111
1112 ret_val = wlan_hdd_validate_context(hdd_ctx);
1113 if (ret_val)
1114 return ret_val;
1115
Anurag Chouhan6d760662016-02-20 16:05:43 +05301116 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001117 hdd_err("Command not allowed in FTM mode");
1118 return -EPERM;
1119 }
1120
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001121 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001122
1123 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1124 NLMSG_HDRLEN);
1125
1126 if (temp_skbuff != NULL) {
1127 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1128 dfs_capability);
1129 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001130 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001131 kfree_skb(temp_skbuff);
1132
1133 return ret_val;
1134 }
1135
1136 return cfg80211_vendor_cmd_reply(temp_skbuff);
1137 }
1138
Jeff Johnson020db452016-06-29 14:37:26 -07001139 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001140 return -ENOMEM;
1141}
1142
1143/**
1144 * is_driver_dfs_capable() - get driver DFS capability
1145 * @wiphy: pointer to wireless wiphy structure.
1146 * @wdev: pointer to wireless_dev structure.
1147 * @data: Pointer to the data to be passed via vendor interface
1148 * @data_len:Length of the data to be passed
1149 *
1150 * This function is called by userspace to indicate whether or not
1151 * the driver supports DFS offload. This is an SSR-protected
1152 * wrapper function.
1153 *
1154 * Return: 0 on success, negative errno on failure
1155 */
1156static int is_driver_dfs_capable(struct wiphy *wiphy,
1157 struct wireless_dev *wdev,
1158 const void *data,
1159 int data_len)
1160{
1161 int ret;
1162
1163 cds_ssr_protect(__func__);
1164 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1165 cds_ssr_unprotect(__func__);
1166
1167 return ret;
1168}
1169
1170/**
1171 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1172 *
1173 * @adapter: SAP adapter pointer
1174 *
1175 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1176 * radio. So in case of DFS MCC scenario override current SAP given config
1177 * to follow concurrent SAP DFS config
1178 *
1179 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1180 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001181int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1182{
1183 hdd_adapter_t *con_sap_adapter;
1184 tsap_Config_t *sap_config, *con_sap_config;
1185 int con_ch;
1186
1187 /*
1188 * Check if AP+AP case, once primary AP chooses a DFS
1189 * channel secondary AP should always follow primary APs channel
1190 */
1191 if (!cds_concurrent_beaconing_sessions_running())
1192 return 0;
1193
1194 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1195 if (!con_sap_adapter)
1196 return 0;
1197
1198 sap_config = &adapter->sessionCtx.ap.sapConfig;
1199 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1200 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1201
1202 if (!CDS_IS_DFS_CH(con_ch))
1203 return 0;
1204
Jeff Johnson020db452016-06-29 14:37:26 -07001205 hdd_err("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001206 sap_config->channel, con_ch);
Jeff Johnson020db452016-06-29 14:37:26 -07001207 hdd_notice("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001208 sap_config->channel = con_ch;
1209
1210 if (con_sap_config->acs_cfg.acs_mode == true) {
1211 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1212 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001213 hdd_err("Primary AP channel config error");
1214 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001215 con_ch, con_sap_config->acs_cfg.pri_ch,
1216 con_sap_config->acs_cfg.ht_sec_ch);
1217 return -EINVAL;
1218 }
1219 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1220 * MCC restriction. So free ch list allocated in do_acs
1221 * func for Sec AP and realloc for Pri AP ch list size
1222 */
1223 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301224 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001225
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301226 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001227 &con_sap_config->acs_cfg,
1228 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301229 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001230 sizeof(uint8_t) *
1231 con_sap_config->acs_cfg.ch_list_count);
1232 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001233 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001234 return -ENOMEM;
1235 }
1236
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301237 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001238 con_sap_config->acs_cfg.ch_list,
1239 con_sap_config->acs_cfg.ch_list_count);
1240
1241 } else {
1242 sap_config->acs_cfg.pri_ch = con_ch;
1243 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1244 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1245 }
1246
1247 return con_ch;
1248}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001249
1250/**
1251 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1252 * @sap_cfg: pointer to SAP config struct
1253 *
1254 * This function sets the default ACS start and end channel for the given band
1255 * and also parses the given ACS channel list.
1256 *
1257 * Return: None
1258 */
1259
1260static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1261 bool vht_enabled)
1262{
1263 int i;
1264 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1265 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001266 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1267 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001268 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1269 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001270 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1271 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001272 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1273 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001274 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1275 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001276 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1277 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001278 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1279 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001280 }
1281
1282 if (ht_enabled)
1283 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1284
1285 if (vht_enabled)
1286 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1287
1288
1289 /* Parse ACS Chan list from hostapd */
1290 if (!sap_cfg->acs_cfg.ch_list)
1291 return;
1292
1293 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1294 sap_cfg->acs_cfg.end_ch =
1295 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1296 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301297 /* avoid channel as start channel */
1298 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1299 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001300 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1301 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1302 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1303 }
1304}
1305
1306
1307static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1308
1309/**
1310 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1311 * @adapter: pointer to SAP adapter struct
1312 *
1313 * This function starts the ACS procedure if there are no
1314 * constraints like MBSSID DFS restrictions.
1315 *
1316 * Return: Status of ACS Start procedure
1317 */
1318
1319static int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
1320{
1321
1322 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1323 tsap_Config_t *sap_config;
1324 tpWLAN_SAPEventCB acs_event_callback;
1325 int status;
1326
1327 sap_config = &adapter->sessionCtx.ap.sapConfig;
1328 sap_config->channel = AUTO_CHANNEL_SELECT;
1329
1330 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1331 if (status < 0) {
1332 return status;
1333 } else {
1334 if (status > 0) {
1335 /*notify hostapd about channel override */
1336 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1337 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1338 return 0;
1339 }
1340 }
1341 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1342 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001343 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001344 return -EINVAL;
1345 }
1346
1347 acs_event_callback = hdd_hostapd_sap_event_cb;
1348
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301349 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301350 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Jeff Johnson020db452016-06-29 14:37:26 -07001351 hdd_notice("ACS Started for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001352 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001353 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001354 acs_event_callback, sap_config, adapter->dev);
1355
1356
1357 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001358 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001359 return -EINVAL;
1360 }
1361 sap_config->acs_cfg.acs_mode = true;
1362 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1363
1364 return 0;
1365}
1366
1367/**
1368 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1369 * @wiphy: Linux wiphy struct pointer
1370 * @wdev: Linux wireless device struct pointer
1371 * @data: ACS information from hostapd
1372 * @data_len: ACS information length
1373 *
1374 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1375 * and starts ACS procedure.
1376 *
1377 * Return: ACS procedure start status
1378 */
1379
1380static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1381 struct wireless_dev *wdev,
1382 const void *data, int data_len)
1383{
1384 struct net_device *ndev = wdev->netdev;
1385 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1386 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1387 tsap_Config_t *sap_config;
1388 struct sk_buff *temp_skbuff;
1389 int status = -EINVAL, i = 0;
1390 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1391 bool ht_enabled, ht40_enabled, vht_enabled;
1392 uint8_t ch_width;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05301393 uint8_t weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001394
1395 /* ***Note*** Donot set SME config related to ACS operation here because
1396 * ACS operation is not synchronouse and ACS for Second AP may come when
1397 * ACS operation for first AP is going on. So only do_acs is split to
1398 * seperate start_acs routine. Also SME-PMAC struct that is used to
1399 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1400 * config shall be set only from start_acs.
1401 */
1402
1403 /* nla_policy Policy template. Policy not applied as some attributes are
1404 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1405 *
1406 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1407 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1408 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1409 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1410 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1411 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1412 */
1413
Jeff Johnson1f61b612016-02-12 16:28:33 -08001414 ENTER_DEV(ndev);
1415
Anurag Chouhan6d760662016-02-20 16:05:43 +05301416 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001417 hdd_err("Command not allowed in FTM mode");
1418 return -EPERM;
1419 }
1420
1421 if (hdd_ctx->config->force_sap_acs) {
Jeff Johnson020db452016-06-29 14:37:26 -07001422 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001423 return -EPERM;
1424 }
1425
1426 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301427 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001428 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301429
Naveen Rawat64e477e2016-05-20 10:34:56 -07001430 if (cds_is_sub_20_mhz_enabled()) {
1431 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1432 status = -EINVAL;
1433 goto out;
1434 }
1435
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001436 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301437 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001438
1439 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1440 NULL);
1441 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001442 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001443 goto out;
1444 }
1445
1446 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001447 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001448 goto out;
1449 }
1450 sap_config->acs_cfg.hw_mode = nla_get_u8(
1451 tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1452
1453 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1454 ht_enabled =
1455 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1456 else
1457 ht_enabled = 0;
1458
1459 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1460 ht40_enabled =
1461 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1462 else
1463 ht40_enabled = 0;
1464
1465 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1466 vht_enabled =
1467 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1468 else
1469 vht_enabled = 0;
1470
1471 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1472 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1473 } else {
1474 if (ht_enabled && ht40_enabled)
1475 ch_width = 40;
1476 else
1477 ch_width = 20;
1478 }
1479 if (ch_width == 80)
1480 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1481 else if (ch_width == 40)
1482 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1483 else
1484 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1485
1486 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1487 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1488 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1489 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1490 * since it contains the frequency values of the channels in
1491 * the channel list.
1492 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1493 * is present
1494 */
1495 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1496 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1497 sap_config->acs_cfg.ch_list_count = nla_len(
1498 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1499 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301500 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001501 sizeof(uint8_t) *
1502 sap_config->acs_cfg.ch_list_count);
1503 if (sap_config->acs_cfg.ch_list == NULL)
1504 goto out;
1505
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301506 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001507 sap_config->acs_cfg.ch_list_count);
1508 }
1509 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1510 uint32_t *freq =
1511 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1512 sap_config->acs_cfg.ch_list_count = nla_len(
1513 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1514 sizeof(uint32_t);
1515 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301516 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001517 sap_config->acs_cfg.ch_list_count);
1518 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001519 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001520 status = -ENOMEM;
1521 goto out;
1522 }
1523
1524 /* convert frequency to channel */
1525 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1526 sap_config->acs_cfg.ch_list[i] =
1527 ieee80211_frequency_to_channel(freq[i]);
1528 }
1529 }
1530
1531 hdd_debug("get pcl for DO_ACS vendor command");
1532
1533 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08001534 status = cds_get_pcl(CDS_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05301535 sap_config->acs_cfg.pcl_channels,
1536 &sap_config->acs_cfg.pcl_ch_count,
1537 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301538 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07001539 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001540
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001541 /* ACS override for android */
1542 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled) {
Jeff Johnson020db452016-06-29 14:37:26 -07001543 hdd_notice("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001544 vht_enabled = 1;
1545 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1546 sap_config->acs_cfg.ch_width =
1547 hdd_ctx->config->vhtChannelWidth;
1548 /* No VHT80 in 2.4G so perform ACS accordingly */
1549 if (sap_config->acs_cfg.end_ch <= 14 &&
1550 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ)
1551 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
1552 }
1553
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05301554 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
1555
Jeff Johnson020db452016-06-29 14:37:26 -07001556 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 -08001557 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
1558 ch_width, ht_enabled, vht_enabled,
1559 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
1560
1561 if (sap_config->acs_cfg.ch_list_count) {
Jeff Johnson020db452016-06-29 14:37:26 -07001562 hdd_notice("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001563 sap_config->acs_cfg.ch_list_count);
1564 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Jeff Johnson020db452016-06-29 14:37:26 -07001565 hdd_notice("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001566 }
1567 sap_config->acs_cfg.acs_mode = true;
1568 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001569 /* ***Note*** Completion variable usage is not allowed
1570 * here since ACS scan operation may take max 2.2 sec
1571 * for 5G band:
1572 * 9 Active channel X 40 ms active scan time +
1573 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001574 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
1575 * for this long. So we split up the scanning part.
1576 */
1577 set_bit(ACS_PENDING, &adapter->event_flags);
Jeff Johnson020db452016-06-29 14:37:26 -07001578 hdd_notice("ACS Pending for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001579 status = 0;
1580 } else {
1581 status = wlan_hdd_cfg80211_start_acs(adapter);
1582 }
1583
1584out:
1585 if (0 == status) {
1586 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1587 NLMSG_HDRLEN);
1588 if (temp_skbuff != NULL)
1589 return cfg80211_vendor_cmd_reply(temp_skbuff);
1590 }
1591
1592 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1593
1594 return status;
1595}
1596
1597 /**
1598 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1599 * @wiphy: Linux wiphy struct pointer
1600 * @wdev: Linux wireless device struct pointer
1601 * @data: ACS information from hostapd
1602 * @data_len: ACS information len
1603 *
1604 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1605 * and starts ACS procedure.
1606 *
1607 * Return: ACS procedure start status
1608 */
1609
1610static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1611 struct wireless_dev *wdev,
1612 const void *data, int data_len)
1613{
1614 int ret;
1615
1616 cds_ssr_protect(__func__);
1617 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
1618 cds_ssr_unprotect(__func__);
1619
1620 return ret;
1621}
1622
1623/**
1624 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
1625 * @work: Linux workqueue struct pointer for ACS work
1626 *
1627 * This function starts the ACS procedure which was marked pending when an ACS
1628 * procedure was in progress for a concurrent SAP interface.
1629 *
1630 * Return: None
1631 */
1632
1633static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
1634{
1635 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
1636 acs_pending_work.work);
1637 wlan_hdd_cfg80211_start_acs(adapter);
1638}
1639
1640/**
1641 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
1642 * @adapter: Pointer to SAP adapter struct
1643 * @pri_channel: SAP ACS procedure selected Primary channel
1644 * @sec_channel: SAP ACS procedure selected secondary channel
1645 *
1646 * This is a callback function from SAP module on ACS procedure is completed.
1647 * This function send the ACS selected channel information to hostapd
1648 *
1649 * Return: None
1650 */
1651
1652void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
1653{
1654 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1655 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
1656 struct sk_buff *vendor_event;
1657 int ret_val;
1658 hdd_adapter_t *con_sap_adapter;
1659 uint16_t ch_width;
1660
1661 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08001662 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001663 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
1664 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
1665 GFP_KERNEL);
1666
1667 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001668 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001669 return;
1670 }
1671
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001672 ret_val = nla_put_u8(vendor_event,
1673 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
1674 sap_cfg->acs_cfg.pri_ch);
1675 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001676 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001677 kfree_skb(vendor_event);
1678 return;
1679 }
1680
1681 ret_val = nla_put_u8(vendor_event,
1682 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
1683 sap_cfg->acs_cfg.ht_sec_ch);
1684 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001685 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001686 kfree_skb(vendor_event);
1687 return;
1688 }
1689
1690 ret_val = nla_put_u8(vendor_event,
1691 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
1692 sap_cfg->acs_cfg.vht_seg0_center_ch);
1693 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001694 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001695 kfree_skb(vendor_event);
1696 return;
1697 }
1698
1699 ret_val = nla_put_u8(vendor_event,
1700 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
1701 sap_cfg->acs_cfg.vht_seg1_center_ch);
1702 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001703 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001704 kfree_skb(vendor_event);
1705 return;
1706 }
1707
1708 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
1709 ch_width = 80;
1710 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1711 ch_width = 40;
1712 else
1713 ch_width = 20;
1714
1715 ret_val = nla_put_u16(vendor_event,
1716 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
1717 ch_width);
1718 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001719 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001720 kfree_skb(vendor_event);
1721 return;
1722 }
1723 if (sap_cfg->acs_cfg.pri_ch > 14)
1724 ret_val = nla_put_u8(vendor_event,
1725 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1726 QCA_ACS_MODE_IEEE80211A);
1727 else
1728 ret_val = nla_put_u8(vendor_event,
1729 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1730 QCA_ACS_MODE_IEEE80211G);
1731
1732 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001733 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001734 kfree_skb(vendor_event);
1735 return;
1736 }
1737
Jeff Johnson46b40792016-06-29 14:03:14 -07001738 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 -08001739 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
1740 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
1741 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
1742
1743 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1744 /* ***Note*** As already mentioned Completion variable usage is not
1745 * allowed here since ACS scan operation may take max 2.2 sec.
1746 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
1747 * operation.
1748 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
1749 * when Primary AP ACS is complete and secondary AP ACS is started here
1750 * immediately, Primary AP start_bss may come inbetween ACS operation
1751 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
1752 * delay. This path and below constraint will be removed on sessionizing
1753 * SAP acs parameters and decoupling SAP from PMAC (WIP).
1754 * As per design constraint user space control application must take
1755 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
1756 * this code path. Sec AP hostapd should be started after Primary AP
1757 * start beaconing which can be confirmed by getchannel iwpriv command
1758 */
1759
1760 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
1761 if (con_sap_adapter &&
1762 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001763 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
1764 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001765 /* Lets give 500ms for OBSS + START_BSS to complete */
1766 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
1767 msecs_to_jiffies(500));
1768 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
1769 }
1770
1771 return;
1772}
1773
1774static int
1775__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1776 struct wireless_dev *wdev,
1777 const void *data,
1778 int data_len)
1779{
1780 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1781 struct sk_buff *skb = NULL;
1782 uint32_t fset = 0;
1783 int ret;
1784
Jeff Johnson1f61b612016-02-12 16:28:33 -08001785 ENTER_DEV(wdev->netdev);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301786
Anurag Chouhan6d760662016-02-20 16:05:43 +05301787 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001788 hdd_err("Command not allowed in FTM mode");
1789 return -EPERM;
1790 }
1791
1792 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301793 if (ret)
1794 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001795
1796 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001797 hdd_notice("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001798 fset |= WIFI_FEATURE_INFRA;
1799 }
1800 if (true == hdd_is_5g_supported(pHddCtx)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001801 hdd_notice("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001802 fset |= WIFI_FEATURE_INFRA_5G;
1803 }
1804#ifdef WLAN_FEATURE_P2P
1805 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
1806 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Jeff Johnson020db452016-06-29 14:37:26 -07001807 hdd_notice("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001808 fset |= WIFI_FEATURE_P2P;
1809 }
1810#endif
1811 fset |= WIFI_FEATURE_SOFT_AP;
1812
1813 /* HOTSPOT is a supplicant feature, enable it by default */
1814 fset |= WIFI_FEATURE_HOTSPOT;
1815
1816#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301817 if (pHddCtx->config->extscan_enabled &&
1818 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001819 hdd_notice("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001820 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
1821 }
1822#endif
1823 if (wlan_hdd_nan_is_supported()) {
Jeff Johnson020db452016-06-29 14:37:26 -07001824 hdd_notice("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001825 fset |= WIFI_FEATURE_NAN;
1826 }
1827 if (sme_is_feature_supported_by_fw(RTT)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001828 hdd_notice("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001829 fset |= WIFI_FEATURE_D2D_RTT;
1830 fset |= WIFI_FEATURE_D2AP_RTT;
1831 }
1832#ifdef FEATURE_WLAN_SCAN_PNO
1833 if (pHddCtx->config->configPNOScanSupport &&
1834 sme_is_feature_supported_by_fw(PNO)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001835 hdd_notice("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001836 fset |= WIFI_FEATURE_PNO;
1837 }
1838#endif
1839 fset |= WIFI_FEATURE_ADDITIONAL_STA;
1840#ifdef FEATURE_WLAN_TDLS
1841 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
1842 sme_is_feature_supported_by_fw(TDLS)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001843 hdd_notice("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001844 fset |= WIFI_FEATURE_TDLS;
1845 }
1846 if (sme_is_feature_supported_by_fw(TDLS) &&
1847 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
1848 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001849 hdd_notice("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001850 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
1851 }
1852#endif
1853#ifdef WLAN_AP_STA_CONCURRENCY
1854 fset |= WIFI_FEATURE_AP_STA;
1855#endif
1856 fset |= WIFI_FEATURE_RSSI_MONITOR;
1857
1858 if (hdd_link_layer_stats_supported())
1859 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
1860
1861 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
1862 NLMSG_HDRLEN);
1863 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07001864 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001865 return -EINVAL;
1866 }
Jeff Johnson020db452016-06-29 14:37:26 -07001867 hdd_notice("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001868 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001869 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001870 goto nla_put_failure;
1871 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301872 ret = cfg80211_vendor_cmd_reply(skb);
1873 EXIT();
1874 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001875nla_put_failure:
1876 kfree_skb(skb);
1877 return -EINVAL;
1878}
1879
1880/**
1881 * wlan_hdd_cfg80211_get_supported_features() - get supported features
1882 * @wiphy: pointer to wireless wiphy structure.
1883 * @wdev: pointer to wireless_dev structure.
1884 * @data: Pointer to the data to be passed via vendor interface
1885 * @data_len:Length of the data to be passed
1886 *
1887 * Return: Return the Success or Failure code.
1888 */
1889static int
1890wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1891 struct wireless_dev *wdev,
1892 const void *data, int data_len)
1893{
1894 int ret = 0;
1895
1896 cds_ssr_protect(__func__);
1897 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
1898 data, data_len);
1899 cds_ssr_unprotect(__func__);
1900
1901 return ret;
1902}
1903
1904/**
1905 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1906 * @wiphy: pointer to wireless wiphy structure.
1907 * @wdev: pointer to wireless_dev structure.
1908 * @data: Pointer to the data to be passed via vendor interface
1909 * @data_len:Length of the data to be passed
1910 *
1911 * Set the MAC address that is to be used for scanning.
1912 *
1913 * Return: Return the Success or Failure code.
1914 */
1915static int
1916__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
1917 struct wireless_dev *wdev,
1918 const void *data,
1919 int data_len)
1920{
1921 tpSirScanMacOui pReqMsg = NULL;
1922 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1923 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301924 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001925 int ret;
1926
Jeff Johnson1f61b612016-02-12 16:28:33 -08001927 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001928
Anurag Chouhan6d760662016-02-20 16:05:43 +05301929 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001930 hdd_err("Command not allowed in FTM mode");
1931 return -EPERM;
1932 }
1933
1934 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301935 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001936 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001937
1938 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07001939 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001940 return -ENOTSUPP;
1941 }
1942
1943 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
1944 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001945 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001946 return -EINVAL;
1947 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301948 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001949 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07001950 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001951 return -ENOMEM;
1952 }
1953 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001954 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001955 goto fail;
1956 }
1957 nla_memcpy(&pReqMsg->oui[0],
1958 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
1959 sizeof(pReqMsg->oui));
Jeff Johnson020db452016-06-29 14:37:26 -07001960 hdd_notice("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001961 pReqMsg->oui[1], pReqMsg->oui[2]);
1962 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301963 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001964 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001965 goto fail;
1966 }
1967 return 0;
1968fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301969 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001970 return -EINVAL;
1971}
1972
1973/**
1974 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1975 * @wiphy: pointer to wireless wiphy structure.
1976 * @wdev: pointer to wireless_dev structure.
1977 * @data: Pointer to the data to be passed via vendor interface
1978 * @data_len:Length of the data to be passed
1979 *
1980 * Set the MAC address that is to be used for scanning. This is an
1981 * SSR-protecting wrapper function.
1982 *
1983 * Return: Return the Success or Failure code.
1984 */
1985static int
1986wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
1987 struct wireless_dev *wdev,
1988 const void *data,
1989 int data_len)
1990{
1991 int ret;
1992
1993 cds_ssr_protect(__func__);
1994 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
1995 data, data_len);
1996 cds_ssr_unprotect(__func__);
1997
1998 return ret;
1999}
2000
2001/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302002 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2003 * @wiphy: pointer phy adapter
2004 * @wdev: pointer to wireless device structure
2005 * @data: pointer to data buffer
2006 * @data_len: length of data
2007 *
2008 * This routine will give concurrency matrix
2009 *
2010 * Return: int status code
2011 */
2012static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2013 struct wireless_dev *wdev,
2014 const void *data,
2015 int data_len)
2016{
2017 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2018 uint8_t i, feature_sets, max_feature_sets;
2019 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2020 struct sk_buff *reply_skb;
2021 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2022 int ret;
2023
2024 ENTER_DEV(wdev->netdev);
2025
2026 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2027 hdd_err("Command not allowed in FTM mode");
2028 return -EPERM;
2029 }
2030
2031 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302032 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302033 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302034
2035 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2036 data, data_len, NULL)) {
2037 hdd_err("Invalid ATTR");
2038 return -EINVAL;
2039 }
2040
2041 /* Parse and fetch max feature set */
2042 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2043 hdd_err("Attr max feature set size failed");
2044 return -EINVAL;
2045 }
2046 max_feature_sets = nla_get_u32(tb[
2047 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2048 hdd_info("Max feature set size: %d", max_feature_sets);
2049
2050 /* Fill feature combination matrix */
2051 feature_sets = 0;
2052 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2053 WIFI_FEATURE_P2P;
2054 /* Add more feature combinations here */
2055
2056 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
2057 hdd_info("Number of feature sets:%d", feature_sets);
2058 hdd_info("Feature set matrix");
2059 for (i = 0; i < feature_sets; i++)
2060 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2061
2062 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2063 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2064 if (!reply_skb) {
2065 hdd_err("Feature set matrix: buffer alloc fail");
2066 return -ENOMEM;
2067 }
2068
2069 if (nla_put_u32(reply_skb,
2070 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2071 feature_sets) ||
2072 nla_put(reply_skb,
2073 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2074 sizeof(u32) * feature_sets,
2075 feature_set_matrix)) {
2076 hdd_err("nla put fail");
2077 kfree_skb(reply_skb);
2078 return -EINVAL;
2079 }
2080 return cfg80211_vendor_cmd_reply(reply_skb);
2081}
2082
2083/**
2084 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2085 * @wiphy: pointer to wireless wiphy structure.
2086 * @wdev: pointer to wireless_dev structure.
2087 * @data: Pointer to the data to be passed via vendor interface
2088 * @data_len:Length of the data to be passed
2089 *
2090 * Retrieves the concurrency feature set matrix
2091 *
2092 * Return: 0 on success, negative errno on failure
2093 */
2094static int
2095wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2096 struct wireless_dev *wdev,
2097 const void *data,
2098 int data_len)
2099{
2100 int ret;
2101
2102 cds_ssr_protect(__func__);
2103 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2104 data, data_len);
2105 cds_ssr_unprotect(__func__);
2106
2107 return ret;
2108}
2109
2110/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002111 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2112 * @feature_flags: pointer to the byte array of features.
2113 * @feature: Feature to be turned ON in the byte array.
2114 *
2115 * Return: None
2116 *
2117 * This is called to turn ON or SET the feature flag for the requested feature.
2118 **/
2119#define NUM_BITS_IN_BYTE 8
2120void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags, uint8_t feature)
2121{
2122 uint32_t index;
2123 uint8_t bit_mask;
2124
2125 index = feature / NUM_BITS_IN_BYTE;
2126 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2127 feature_flags[index] |= bit_mask;
2128}
2129
2130/**
2131 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2132 * @wiphy: pointer to wireless wiphy structure.
2133 * @wdev: pointer to wireless_dev structure.
2134 * @data: Pointer to the data to be passed via vendor interface
2135 * @data_len:Length of the data to be passed
2136 *
2137 * This is called when wlan driver needs to send supported feature set to
2138 * supplicant upon a request/query from the supplicant.
2139 *
2140 * Return: Return the Success or Failure code.
2141 **/
2142#define MAX_CONCURRENT_CHAN_ON_24G 2
2143#define MAX_CONCURRENT_CHAN_ON_5G 2
2144static int
2145__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2146 struct wireless_dev *wdev,
2147 const void *data, int data_len)
2148{
2149 struct sk_buff *skb = NULL;
2150 uint32_t dbs_capability = 0;
2151 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302152 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002153 int ret_val;
2154
2155 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2156 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2157
Jeff Johnson1f61b612016-02-12 16:28:33 -08002158 ENTER_DEV(wdev->netdev);
2159
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002160 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2161 if (ret_val)
2162 return ret_val;
2163
Anurag Chouhan6d760662016-02-20 16:05:43 +05302164 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002165 hdd_err("Command not allowed in FTM mode");
2166 return -EPERM;
2167 }
2168
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002169 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002170 hdd_notice("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002171 wlan_hdd_cfg80211_set_feature(feature_flags,
2172 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2173 }
2174
2175 wlan_hdd_cfg80211_set_feature(feature_flags,
2176 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2177 if (wma_is_scan_simultaneous_capable())
2178 wlan_hdd_cfg80211_set_feature(feature_flags,
2179 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002180
2181 if (wma_is_p2p_lo_capable())
2182 wlan_hdd_cfg80211_set_feature(feature_flags,
2183 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2184
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002185 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2186 NLMSG_HDRLEN);
2187
2188 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002189 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002190 return -ENOMEM;
2191 }
2192
2193 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2194 sizeof(feature_flags), feature_flags))
2195 goto nla_put_failure;
2196
2197 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302198 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002199 if (one_by_one_dbs)
2200 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2201
2202 if (two_by_two_dbs)
2203 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2204
2205 if (!one_by_one_dbs && !two_by_two_dbs)
2206 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2207 } else {
2208 hdd_err("wma_get_dbs_hw_mode failed");
2209 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2210 }
2211
2212 hdd_info("dbs_capability is %d", dbs_capability);
2213
2214 if (nla_put_u32(skb,
2215 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2216 MAX_CONCURRENT_CHAN_ON_24G))
2217 goto nla_put_failure;
2218
2219 if (nla_put_u32(skb,
2220 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2221 MAX_CONCURRENT_CHAN_ON_5G))
2222 goto nla_put_failure;
2223
2224 return cfg80211_vendor_cmd_reply(skb);
2225
2226nla_put_failure:
2227 kfree_skb(skb);
2228 return -EINVAL;
2229}
2230
2231/**
2232 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2233 * @wiphy: pointer to wireless wiphy structure.
2234 * @wdev: pointer to wireless_dev structure.
2235 * @data: Pointer to the data to be passed via vendor interface
2236 * @data_len:Length of the data to be passed
2237 *
2238 * This is called when wlan driver needs to send supported feature set to
2239 * supplicant upon a request/query from the supplicant.
2240 *
2241 * Return: Return the Success or Failure code.
2242 */
2243static int
2244wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2245 struct wireless_dev *wdev,
2246 const void *data, int data_len)
2247{
2248 int ret;
2249
2250 cds_ssr_protect(__func__);
2251 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2252 data, data_len);
2253 cds_ssr_unprotect(__func__);
2254
2255 return ret;
2256}
2257
2258
2259/**
2260 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2261 * @wiphy: The wiphy structure
2262 * @wdev: The wireless device
2263 * @data: Data passed by framework
2264 * @data_len: Parameters to be configured passed as data
2265 *
2266 * The roaming related parameters are configured by the framework
2267 * using this interface.
2268 *
2269 * Return: Return either success or failure code.
2270 */
2271static int
2272__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2273 struct wireless_dev *wdev, const void *data, int data_len)
2274{
2275 struct net_device *dev = wdev->netdev;
2276 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2277 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2278 uint8_t session_id;
2279 struct roam_ext_params roam_params;
2280 uint32_t cmd_type, req_id;
2281 struct nlattr *curr_attr;
2282 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2283 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2284 int rem, i;
2285 uint32_t buf_len = 0;
2286 int ret;
2287
Jeff Johnson1f61b612016-02-12 16:28:33 -08002288 ENTER_DEV(dev);
2289
Anurag Chouhan6d760662016-02-20 16:05:43 +05302290 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002291 hdd_err("Command not allowed in FTM mode");
2292 return -EPERM;
2293 }
2294
2295 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302296 if (ret)
2297 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002298
2299 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2300 data, data_len,
2301 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002302 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002303 return -EINVAL;
2304 }
2305 /* Parse and fetch Command Type*/
2306 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002307 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002308 goto fail;
2309 }
2310 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302311 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002312 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2313 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002314 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002315 goto fail;
2316 }
2317 req_id = nla_get_u32(
2318 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002319 hdd_debug("Req Id (%d)", req_id);
2320 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002321 switch (cmd_type) {
2322 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2323 i = 0;
2324 nla_for_each_nested(curr_attr,
2325 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2326 rem) {
2327 if (nla_parse(tb2,
2328 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2329 nla_data(curr_attr), nla_len(curr_attr),
2330 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002331 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002332 goto fail;
2333 }
2334 /* Parse and Fetch allowed SSID list*/
2335 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002336 hdd_err("attr allowed ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002337 goto fail;
2338 }
2339 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2340 /*
2341 * Upper Layers include a null termination character.
2342 * Check for the actual permissible length of SSID and
2343 * also ensure not to copy the NULL termination
2344 * character to the driver buffer.
2345 */
2346 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2347 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2348 nla_memcpy(
2349 roam_params.ssid_allowed_list[i].ssId,
2350 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2351 buf_len - 1);
2352 roam_params.ssid_allowed_list[i].length =
2353 buf_len - 1;
Jeff Johnson020db452016-06-29 14:37:26 -07002354 hdd_debug("SSID[%d]: %.*s,length = %d", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002355 roam_params.ssid_allowed_list[i].length,
2356 roam_params.ssid_allowed_list[i].ssId,
2357 roam_params.ssid_allowed_list[i].length);
2358 i++;
2359 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002360 hdd_err("Invalid buffer length");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002361 }
2362 }
2363 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002364 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002365 roam_params.num_ssid_allowed_list);
2366 sme_update_roam_params(pHddCtx->hHal, session_id,
2367 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2368 break;
2369 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2370 /* Parse and fetch 5G Boost Threshold */
2371 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002372 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002373 goto fail;
2374 }
2375 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2376 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002377 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002378 roam_params.raise_rssi_thresh_5g);
2379 /* Parse and fetch 5G Penalty Threshold */
2380 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002381 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002382 goto fail;
2383 }
2384 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2385 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002386 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002387 roam_params.drop_rssi_thresh_5g);
2388 /* Parse and fetch 5G Boost Factor */
2389 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002390 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002391 goto fail;
2392 }
2393 roam_params.raise_factor_5g = nla_get_u32(
2394 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002395 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002396 roam_params.raise_factor_5g);
2397 /* Parse and fetch 5G Penalty factor */
2398 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002399 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002400 goto fail;
2401 }
2402 roam_params.drop_factor_5g = nla_get_u32(
2403 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002404 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002405 roam_params.drop_factor_5g);
2406 /* Parse and fetch 5G Max Boost */
2407 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002408 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002409 goto fail;
2410 }
2411 roam_params.max_raise_rssi_5g = nla_get_u32(
2412 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002413 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002414 roam_params.max_raise_rssi_5g);
2415 /* Parse and fetch Rssi Diff */
2416 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002417 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002418 goto fail;
2419 }
2420 roam_params.rssi_diff = nla_get_s32(
2421 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002422 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002423 roam_params.rssi_diff);
2424 /* Parse and fetch Alert Rssi Threshold */
2425 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002426 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002427 goto fail;
2428 }
2429 roam_params.alert_rssi_threshold = nla_get_u32(
2430 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002431 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002432 roam_params.alert_rssi_threshold);
2433 sme_update_roam_params(pHddCtx->hHal, session_id,
2434 roam_params,
2435 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2436 break;
2437 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2438 /* Parse and fetch Activate Good Rssi Roam */
2439 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002440 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002441 goto fail;
2442 }
2443 roam_params.good_rssi_roam = nla_get_s32(
2444 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002445 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002446 roam_params.good_rssi_roam);
2447 sme_update_roam_params(pHddCtx->hHal, session_id,
2448 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2449 break;
2450 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2451 /* Parse and fetch number of preferred BSSID */
2452 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002453 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002454 goto fail;
2455 }
2456 roam_params.num_bssid_favored = nla_get_u32(
2457 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002458 hdd_debug("Num of Preferred BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002459 roam_params.num_bssid_favored);
2460 i = 0;
2461 nla_for_each_nested(curr_attr,
2462 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2463 rem) {
2464 if (nla_parse(tb2,
2465 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2466 nla_data(curr_attr), nla_len(curr_attr),
2467 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002468 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002469 goto fail;
2470 }
2471 /* Parse and fetch MAC address */
2472 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002473 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002474 goto fail;
2475 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002476 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002477 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302478 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002479 hdd_debug(MAC_ADDRESS_STR,
2480 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002481 /* Parse and fetch preference factor*/
2482 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002483 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002484 goto fail;
2485 }
2486 roam_params.bssid_favored_factor[i] = nla_get_u32(
2487 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002488 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002489 roam_params.bssid_favored_factor[i]);
2490 i++;
2491 }
2492 sme_update_roam_params(pHddCtx->hHal, session_id,
2493 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
2494 break;
2495 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
2496 /* Parse and fetch number of blacklist BSSID */
2497 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002498 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002499 goto fail;
2500 }
2501 roam_params.num_bssid_avoid_list = nla_get_u32(
2502 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002503 hdd_debug("Num of blacklist BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002504 roam_params.num_bssid_avoid_list);
2505 i = 0;
2506 nla_for_each_nested(curr_attr,
2507 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
2508 rem) {
2509 if (nla_parse(tb2,
2510 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2511 nla_data(curr_attr), nla_len(curr_attr),
2512 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002513 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002514 goto fail;
2515 }
2516 /* Parse and fetch MAC address */
2517 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002518 hdd_err("attr blacklist addr failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002519 goto fail;
2520 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002521 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002522 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302523 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002524 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002525 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002526 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002527 i++;
2528 }
2529 sme_update_roam_params(pHddCtx->hHal, session_id,
2530 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
2531 break;
2532 }
2533 return 0;
2534fail:
2535 return -EINVAL;
2536}
2537
2538/**
2539 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
2540 * @wiphy: pointer to wireless wiphy structure.
2541 * @wdev: pointer to wireless_dev structure.
2542 * @data: Pointer to the data to be passed via vendor interface
2543 * @data_len:Length of the data to be passed
2544 *
2545 * Return: Return the Success or Failure code.
2546 */
2547static int
2548wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2549 struct wireless_dev *wdev,
2550 const void *data,
2551 int data_len)
2552{
2553 int ret;
2554
2555 cds_ssr_protect(__func__);
2556 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
2557 data, data_len);
2558 cds_ssr_unprotect(__func__);
2559
2560 return ret;
2561}
2562
2563static const struct nla_policy
2564wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
2565 +1] = {
2566 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
2567};
2568
2569/**
2570 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
2571 * @hdd_ctx: HDD context
2572 * @device_mode: device mode
2573 * Return: bool
2574 */
2575static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08002576 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002577{
2578 hdd_adapter_t *adapter;
2579 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
2580 hdd_ap_ctx_t *ap_ctx;
2581 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302582 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002583
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302584 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002585 &adapter_node);
2586
2587 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302588 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002589 adapter = adapter_node->pAdapter;
2590
2591 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002592 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002593 ap_ctx =
2594 WLAN_HDD_GET_AP_CTX_PTR(adapter);
2595
2596 /*
2597 * if there is SAP already running on DFS channel,
2598 * do not disable scan on dfs channels. Note that
2599 * with SAP on DFS, there cannot be conurrency on
2600 * single radio. But then we can have multiple
2601 * radios !!
2602 */
2603 if (CHANNEL_STATE_DFS ==
2604 cds_get_channel_state(
2605 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002606 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002607 return true;
2608 }
2609 }
2610
2611 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002612 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002613 sta_ctx =
2614 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2615
2616 /*
2617 * if STA is already connected on DFS channel,
2618 * do not disable scan on dfs channels
2619 */
2620 if (hdd_conn_is_connected(sta_ctx) &&
2621 (CHANNEL_STATE_DFS ==
2622 cds_get_channel_state(
2623 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002624 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002625 return true;
2626 }
2627 }
2628
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302629 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002630 adapter_node,
2631 &next);
2632 adapter_node = next;
2633 }
2634
2635 return false;
2636}
2637
2638/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002639 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
2640 * @hdd_ctx: HDD context within host driver
2641 * @adapter: Adapter pointer
2642 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
2643 *
2644 * Loops through devices to see who is operating on DFS channels
2645 * and then disables/enables DFS channels by calling SME API.
2646 * Fails the disable request if any device is active on a DFS channel.
2647 *
2648 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002649 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002650
2651int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
2652 hdd_adapter_t *adapter,
2653 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002654{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002655 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302656 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002657 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002658
2659 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
2660 if (no_dfs_flag) {
2661 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002662 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002663
2664 if (true == status)
2665 return -EOPNOTSUPP;
2666
2667 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002668 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002669
2670 if (true == status)
2671 return -EOPNOTSUPP;
2672 }
2673
2674 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
2675
2676 hdd_abort_mac_scan_all_adapters(hdd_ctx);
2677
2678 /*
2679 * call the SME API to tunnel down the new channel list
2680 * to the firmware
2681 */
2682 status = sme_handle_dfs_chan_scan(
2683 h_hal, hdd_ctx->config->enableDFSChnlScan);
2684
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302685 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002686 ret_val = 0;
2687
2688 /*
2689 * Clear the SME scan cache also. Note that the
2690 * clearing of scan results is independent of session;
2691 * so no need to iterate over
2692 * all sessions
2693 */
2694 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302695 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002696 ret_val = -EPERM;
2697 }
2698
2699 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002700 hdd_notice(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002701 ret_val = 0;
2702 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002703 return ret_val;
2704}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002705
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002706/**
2707 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
2708 * @wiphy: corestack handler
2709 * @wdev: wireless device
2710 * @data: data
2711 * @data_len: data length
2712 * Return: success(0) or reason code for failure
2713 */
2714static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2715 struct wireless_dev *wdev,
2716 const void *data,
2717 int data_len)
2718{
2719 struct net_device *dev = wdev->netdev;
2720 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2721 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2722 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
2723 int ret_val;
2724 uint32_t no_dfs_flag = 0;
2725
Jeff Johnson1f61b612016-02-12 16:28:33 -08002726 ENTER_DEV(dev);
2727
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002728 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302729 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002730 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002731
2732 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
2733 data, data_len,
2734 wlan_hdd_set_no_dfs_flag_config_policy)) {
2735 hdd_err("invalid attr");
2736 return -EINVAL;
2737 }
2738
2739 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
2740 hdd_err("attr dfs flag failed");
2741 return -EINVAL;
2742 }
2743
2744 no_dfs_flag = nla_get_u32(
2745 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
2746
Jeff Johnson020db452016-06-29 14:37:26 -07002747 hdd_notice(" DFS flag = %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002748
2749 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07002750 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002751 return -EINVAL;
2752 }
2753
2754 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
2755 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002756 return ret_val;
2757}
2758
2759/**
2760 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
2761 *
2762 * @wiphy: wiphy device pointer
2763 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07002764 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002765 * @data_len: Buffer length
2766 *
2767 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
2768 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
2769 *
2770 * Return: EOK or other error codes.
2771 */
2772
2773static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2774 struct wireless_dev *wdev,
2775 const void *data,
2776 int data_len)
2777{
2778 int ret;
2779
2780 cds_ssr_protect(__func__);
2781 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
2782 data, data_len);
2783 cds_ssr_unprotect(__func__);
2784
2785 return ret;
2786}
2787
Manikandan Mohan80dea792016-04-28 16:36:48 -07002788static const struct nla_policy
2789wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
2790 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
2791};
2792
2793/**
2794 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2795 * @wiphy: wiphy device pointer
2796 * @wdev: wireless device pointer
2797 * @data: Vendor command data buffer
2798 * @data_len: Buffer length
2799 *
2800 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2801 * setup WISA Mode features.
2802 *
2803 * Return: Success(0) or reason code for failure
2804 */
2805static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2806 struct wireless_dev *wdev, const void *data, int data_len)
2807{
2808 struct net_device *dev = wdev->netdev;
2809 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2810 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2811 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
2812 struct sir_wisa_params wisa;
2813 int ret_val;
2814 QDF_STATUS status;
2815 bool wisa_mode;
2816
2817 ENTER_DEV(dev);
2818 ret_val = wlan_hdd_validate_context(hdd_ctx);
2819 if (ret_val)
2820 goto err;
2821
2822 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2823 hdd_err("Command not allowed in FTM mode");
2824 return -EPERM;
2825 }
2826
2827 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
2828 wlan_hdd_wisa_cmd_policy)) {
2829 hdd_err("Invalid WISA cmd attributes");
2830 ret_val = -EINVAL;
2831 goto err;
2832 }
2833 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
2834 hdd_err("Invalid WISA mode");
2835 ret_val = -EINVAL;
2836 goto err;
2837 }
2838
2839 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
2840 hdd_info("WISA Mode: %d", wisa_mode);
2841 wisa.mode = wisa_mode;
2842 wisa.vdev_id = adapter->sessionId;
2843 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002844 if (!QDF_IS_STATUS_SUCCESS(status)) {
2845 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002846 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002847 }
2848 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
2849 ol_txrx_set_wisa_mode(ol_txrx_get_vdev_from_vdev_id(
2850 adapter->sessionId), wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002851err:
2852 EXIT();
2853 return ret_val;
2854}
2855
2856/**
2857 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2858 * @wiphy: corestack handler
2859 * @wdev: wireless device
2860 * @data: data
2861 * @data_len: data length
2862 *
2863 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2864 * setup WISA mode features.
2865 *
2866 * Return: Success(0) or reason code for failure
2867 */
2868static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2869 struct wireless_dev *wdev,
2870 const void *data,
2871 int data_len)
2872{
2873 int ret;
2874
2875 cds_ssr_protect(__func__);
2876 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
2877 cds_ssr_unprotect(__func__);
2878
2879 return ret;
2880}
2881
Anurag Chouhan96919482016-07-13 16:36:57 +05302882/*
2883 * define short names for the global vendor params
2884 * used by __wlan_hdd_cfg80211_get_station_cmd()
2885 */
2886#define STATION_INVALID \
2887 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
2888#define STATION_INFO \
2889 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
2890#define STATION_ASSOC_FAIL_REASON \
2891 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
2892#define STATION_MAX \
2893 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
2894
2895static const struct nla_policy
2896hdd_get_station_policy[STATION_MAX + 1] = {
2897 [STATION_INFO] = {.type = NLA_FLAG},
2898 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
2899};
2900
2901/**
2902 * hdd_get_station_assoc_fail() - Handle get station assoc fail
2903 * @hdd_ctx: HDD context within host driver
2904 * @wdev: wireless device
2905 *
2906 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
2907 * Validate cmd attributes and send the station info to upper layers.
2908 *
2909 * Return: Success(0) or reason code for failure
2910 */
2911static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
2912 hdd_adapter_t *adapter)
2913{
2914 struct sk_buff *skb = NULL;
2915 uint32_t nl_buf_len;
2916 hdd_station_ctx_t *hdd_sta_ctx;
2917
2918 nl_buf_len = NLMSG_HDRLEN;
2919 nl_buf_len += sizeof(uint32_t);
2920 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
2921
2922 if (!skb) {
2923 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
2924 return -ENOMEM;
2925 }
2926
2927 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2928
2929 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
2930 hdd_sta_ctx->conn_info.assoc_status_code)) {
2931 hdd_err("put fail");
2932 goto fail;
2933 }
2934 return cfg80211_vendor_cmd_reply(skb);
2935fail:
2936 if (skb)
2937 kfree_skb(skb);
2938 return -EINVAL;
2939}
2940
2941/**
2942 * hdd_map_auth_type() - transform auth type specific to
2943 * vendor command
2944 * @auth_type: csr auth type
2945 *
2946 * Return: Success(0) or reason code for failure
2947 */
2948static int hdd_convert_auth_type(uint32_t auth_type)
2949{
2950 uint32_t ret_val;
2951
2952 switch (auth_type) {
2953 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
2954 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
2955 break;
2956 case eCSR_AUTH_TYPE_SHARED_KEY:
2957 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
2958 break;
2959 case eCSR_AUTH_TYPE_WPA:
2960 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
2961 break;
2962 case eCSR_AUTH_TYPE_WPA_PSK:
2963 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
2964 break;
2965 case eCSR_AUTH_TYPE_AUTOSWITCH:
2966 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
2967 break;
2968 case eCSR_AUTH_TYPE_WPA_NONE:
2969 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
2970 break;
2971 case eCSR_AUTH_TYPE_RSN:
2972 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
2973 break;
2974 case eCSR_AUTH_TYPE_RSN_PSK:
2975 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
2976 break;
2977 case eCSR_AUTH_TYPE_FT_RSN:
2978 ret_val = QCA_WLAN_AUTH_TYPE_FT;
2979 break;
2980 case eCSR_AUTH_TYPE_FT_RSN_PSK:
2981 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
2982 break;
2983 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
2984 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
2985 break;
2986 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
2987 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
2988 break;
2989 case eCSR_AUTH_TYPE_CCKM_WPA:
2990 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
2991 break;
2992 case eCSR_AUTH_TYPE_CCKM_RSN:
2993 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
2994 break;
2995 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
2996 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
2997 break;
2998 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
2999 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3000 break;
3001 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3002 case eCSR_AUTH_TYPE_FAILED:
3003 case eCSR_AUTH_TYPE_NONE:
3004 default:
3005 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3006 break;
3007 }
3008 return ret_val;
3009}
3010
3011/**
3012 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3013 * vendor command
3014 * @dot11mode: dot11mode
3015 *
3016 * Return: Success(0) or reason code for failure
3017 */
3018static int hdd_convert_dot11mode(uint32_t dot11mode)
3019{
3020 uint32_t ret_val;
3021
3022 switch (dot11mode) {
3023 case eCSR_CFG_DOT11_MODE_11A:
3024 ret_val = QCA_WLAN_802_11_MODE_11A;
3025 break;
3026 case eCSR_CFG_DOT11_MODE_11B:
3027 ret_val = QCA_WLAN_802_11_MODE_11B;
3028 break;
3029 case eCSR_CFG_DOT11_MODE_11G:
3030 ret_val = QCA_WLAN_802_11_MODE_11G;
3031 break;
3032 case eCSR_CFG_DOT11_MODE_11N:
3033 ret_val = QCA_WLAN_802_11_MODE_11N;
3034 break;
3035 case eCSR_CFG_DOT11_MODE_11AC:
3036 ret_val = QCA_WLAN_802_11_MODE_11AC;
3037 break;
3038 case eCSR_CFG_DOT11_MODE_AUTO:
3039 case eCSR_CFG_DOT11_MODE_ABG:
3040 default:
3041 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3042 }
3043 return ret_val;
3044}
3045
3046/**
3047 * hdd_add_tx_bitrate() - add tx bitrate attribute
3048 * @skb: pointer to sk buff
3049 * @hdd_sta_ctx: pointer to hdd station context
3050 * @idx: attribute index
3051 *
3052 * Return: Success(0) or reason code for failure
3053 */
3054static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3055 hdd_station_ctx_t *hdd_sta_ctx,
3056 int idx)
3057{
3058 struct nlattr *nla_attr;
3059 uint32_t bitrate, bitrate_compat;
3060
3061 nla_attr = nla_nest_start(skb, idx);
3062 if (!nla_attr)
3063 goto fail;
3064 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3065 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3066
3067 /* report 16-bit bitrate only if we can */
3068 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3069 if (bitrate > 0 &&
3070 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3071 hdd_err("put fail");
3072 goto fail;
3073 }
3074 if (bitrate_compat > 0 &&
3075 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3076 hdd_err("put fail");
3077 goto fail;
3078 }
3079 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3080 hdd_sta_ctx->conn_info.txrate.nss)) {
3081 hdd_err("put fail");
3082 goto fail;
3083 }
3084 nla_nest_end(skb, nla_attr);
3085 return 0;
3086fail:
3087 return -EINVAL;
3088}
3089
3090/**
3091 * hdd_add_sta_info() - add station info attribute
3092 * @skb: pointer to sk buff
3093 * @hdd_sta_ctx: pointer to hdd station context
3094 * @idx: attribute index
3095 *
3096 * Return: Success(0) or reason code for failure
3097 */
3098static int32_t hdd_add_sta_info(struct sk_buff *skb,
3099 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3100{
3101 struct nlattr *nla_attr;
3102
3103 nla_attr = nla_nest_start(skb, idx);
3104 if (!nla_attr)
3105 goto fail;
3106 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3107 (hdd_sta_ctx->conn_info.signal + 100))) {
3108 hdd_err("put fail");
3109 goto fail;
3110 }
3111 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3112 goto fail;
3113 nla_nest_end(skb, nla_attr);
3114 return 0;
3115fail:
3116 return -EINVAL;
3117}
3118
3119/**
3120 * hdd_add_survey_info() - add survey info attribute
3121 * @skb: pointer to sk buff
3122 * @hdd_sta_ctx: pointer to hdd station context
3123 * @idx: attribute index
3124 *
3125 * Return: Success(0) or reason code for failure
3126 */
3127static int32_t hdd_add_survey_info(struct sk_buff *skb,
3128 hdd_station_ctx_t *hdd_sta_ctx,
3129 int idx)
3130{
3131 struct nlattr *nla_attr;
3132
3133 nla_attr = nla_nest_start(skb, idx);
3134 if (!nla_attr)
3135 goto fail;
3136 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3137 hdd_sta_ctx->conn_info.freq) ||
3138 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3139 (hdd_sta_ctx->conn_info.noise + 100))) {
3140 hdd_err("put fail");
3141 goto fail;
3142 }
3143 nla_nest_end(skb, nla_attr);
3144 return 0;
3145fail:
3146 return -EINVAL;
3147}
3148
3149/**
3150 * hdd_add_link_standard_info() - add link info attribute
3151 * @skb: pointer to sk buff
3152 * @hdd_sta_ctx: pointer to hdd station context
3153 * @idx: attribute index
3154 *
3155 * Return: Success(0) or reason code for failure
3156 */
3157static int32_t
3158hdd_add_link_standard_info(struct sk_buff *skb,
3159 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3160{
3161 struct nlattr *nla_attr;
3162
3163 nla_attr = nla_nest_start(skb, idx);
3164 if (!nla_attr)
3165 goto fail;
3166 if (nla_put(skb,
3167 NL80211_ATTR_SSID,
3168 hdd_sta_ctx->conn_info.SSID.SSID.length,
3169 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3170 hdd_err("put fail");
3171 goto fail;
3172 }
3173 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3174 goto fail;
3175 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3176 goto fail;
3177 nla_nest_end(skb, nla_attr);
3178 return 0;
3179fail:
3180 return -EINVAL;
3181}
3182
3183/**
3184 * hdd_add_ap_standard_info() - add ap info attribute
3185 * @skb: pointer to sk buff
3186 * @hdd_sta_ctx: pointer to hdd station context
3187 * @idx: attribute index
3188 *
3189 * Return: Success(0) or reason code for failure
3190 */
3191static int32_t
3192hdd_add_ap_standard_info(struct sk_buff *skb,
3193 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3194{
3195 struct nlattr *nla_attr;
3196
3197 nla_attr = nla_nest_start(skb, idx);
3198 if (!nla_attr)
3199 goto fail;
3200 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3201 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3202 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3203 &hdd_sta_ctx->conn_info.vht_caps)) {
3204 hdd_err("put fail");
3205 goto fail;
3206 }
3207 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3208 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3209 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3210 &hdd_sta_ctx->conn_info.ht_caps)) {
3211 hdd_err("put fail");
3212 goto fail;
3213 }
3214 nla_nest_end(skb, nla_attr);
3215 return 0;
3216fail:
3217 return -EINVAL;
3218}
3219
3220/**
3221 * hdd_get_station_info() - send BSS information to supplicant
3222 * @hdd_ctx: pointer to hdd context
3223 * @adapter: pointer to adapter
3224 *
3225 * Return: 0 if success else error status
3226 */
3227static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3228 hdd_adapter_t *adapter)
3229{
3230 struct sk_buff *skb = NULL;
3231 uint8_t *tmp_hs20 = NULL;
3232 uint32_t nl_buf_len;
3233 hdd_station_ctx_t *hdd_sta_ctx;
3234
3235 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3236
3237 nl_buf_len = NLMSG_HDRLEN;
3238 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3239 sizeof(hdd_sta_ctx->conn_info.freq) +
3240 sizeof(hdd_sta_ctx->conn_info.noise) +
3241 sizeof(hdd_sta_ctx->conn_info.signal) +
3242 (sizeof(uint32_t) * 2) +
3243 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3244 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3245 sizeof(hdd_sta_ctx->conn_info.authType) +
3246 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3247 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3248 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3249 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3250 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3251 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3252 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3253 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3254 1);
3255 }
3256 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3257 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3258 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3259 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3260
3261
3262 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3263 if (!skb) {
3264 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3265 return -ENOMEM;
3266 }
3267
3268 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3269 LINK_INFO_STANDARD_NL80211_ATTR)) {
3270 hdd_err("put fail");
3271 goto fail;
3272 }
3273 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3274 AP_INFO_STANDARD_NL80211_ATTR)) {
3275 hdd_err("put fail");
3276 goto fail;
3277 }
3278 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3279 hdd_sta_ctx->conn_info.roam_count) ||
3280 nla_put_u32(skb, INFO_AKM,
3281 hdd_convert_auth_type(
3282 hdd_sta_ctx->conn_info.authType)) ||
3283 nla_put_u32(skb, WLAN802_11_MODE,
3284 hdd_convert_dot11mode(
3285 hdd_sta_ctx->conn_info.dot11Mode))) {
3286 hdd_err("put fail");
3287 goto fail;
3288 }
3289 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3290 if (nla_put(skb, HT_OPERATION,
3291 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3292 &hdd_sta_ctx->conn_info.ht_operation)) {
3293 hdd_err("put fail");
3294 goto fail;
3295 }
3296 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3297 if (nla_put(skb, VHT_OPERATION,
3298 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3299 &hdd_sta_ctx->conn_info.vht_operation)) {
3300 hdd_err("put fail");
3301 goto fail;
3302 }
3303 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3304 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3305 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3306 tmp_hs20 + 1)) {
3307 hdd_err("put fail");
3308 goto fail;
3309 }
3310
3311 return cfg80211_vendor_cmd_reply(skb);
3312fail:
3313 if (skb)
3314 kfree_skb(skb);
3315 return -EINVAL;
3316}
3317
3318/**
3319 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3320 * @wiphy: corestack handler
3321 * @wdev: wireless device
3322 * @data: data
3323 * @data_len: data length
3324 *
3325 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3326 * Validate cmd attributes and send the station info to upper layers.
3327 *
3328 * Return: Success(0) or reason code for failure
3329 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303330static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303331__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3332 struct wireless_dev *wdev,
3333 const void *data,
3334 int data_len)
3335{
3336 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3337 struct net_device *dev = wdev->netdev;
3338 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3339 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3340 int32_t status;
3341
3342 ENTER_DEV(dev);
3343 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3344 hdd_err("Command not allowed in FTM mode");
3345 status = -EPERM;
3346 goto out;
3347 }
3348
3349 status = wlan_hdd_validate_context(hdd_ctx);
3350 if (0 != status)
3351 goto out;
3352
3353
3354 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3355 data, data_len, NULL);
3356 if (status) {
3357 hdd_err("Invalid ATTR");
3358 goto out;
3359 }
3360
3361 /* Parse and fetch Command Type*/
3362 if (tb[STATION_INFO]) {
3363 status = hdd_get_station_info(hdd_ctx, adapter);
3364 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3365 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3366 } else {
3367 hdd_err("get station info cmd type failed");
3368 status = -EINVAL;
3369 goto out;
3370 }
3371 EXIT();
3372out:
3373 return status;
3374}
3375
3376/**
3377 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3378 * @wiphy: corestack handler
3379 * @wdev: wireless device
3380 * @data: data
3381 * @data_len: data length
3382 *
3383 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3384 * Validate cmd attributes and send the station info to upper layers.
3385 *
3386 * Return: Success(0) or reason code for failure
3387 */
3388static int32_t
3389hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3390 struct wireless_dev *wdev,
3391 const void *data,
3392 int data_len)
3393{
3394 int ret;
3395
3396 cds_ssr_protect(__func__);
3397 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3398 cds_ssr_unprotect(__func__);
3399
3400 return ret;
3401}
3402
3403/*
3404 * undef short names defined for get station command
3405 * used by __wlan_hdd_cfg80211_get_station_cmd()
3406 */
3407#undef STATION_INVALID
3408#undef STATION_INFO
3409#undef STATION_ASSOC_FAIL_REASON
3410#undef STATION_MAX
3411
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003412#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3413/**
3414 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3415 * @wiphy: pointer to wireless wiphy structure.
3416 * @wdev: pointer to wireless_dev structure.
3417 * @data: Pointer to the Key data
3418 * @data_len:Length of the data passed
3419 *
3420 * This is called when wlan driver needs to save the keys received via
3421 * vendor specific command.
3422 *
3423 * Return: Return the Success or Failure code.
3424 */
3425static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3426 struct wireless_dev *wdev,
3427 const void *data, int data_len)
3428{
3429 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
3430 struct net_device *dev = wdev->netdev;
3431 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
3432 hdd_context_t *hdd_ctx_ptr;
3433 int status;
3434
Jeff Johnson1f61b612016-02-12 16:28:33 -08003435 ENTER_DEV(dev);
3436
Anurag Chouhan6d760662016-02-20 16:05:43 +05303437 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003438 hdd_err("Command not allowed in FTM mode");
3439 return -EPERM;
3440 }
3441
3442 if ((data == NULL) || (data_len == 0) ||
3443 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003444 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003445 return -EINVAL;
3446 }
3447
3448 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
3449 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07003450 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003451 return -EINVAL;
3452 }
3453
3454 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303455 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003456 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003457 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
3458 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07003459 true,
3460 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303461 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
3462 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003463 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
3464 hdd_adapter_ptr->sessionId, local_pmk, data_len);
3465 return 0;
3466}
3467
3468/**
3469 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3470 * @wiphy: pointer to wireless wiphy structure.
3471 * @wdev: pointer to wireless_dev structure.
3472 * @data: Pointer to the Key data
3473 * @data_len:Length of the data passed
3474 *
3475 * This is called when wlan driver needs to save the keys received via
3476 * vendor specific command.
3477 *
3478 * Return: Return the Success or Failure code.
3479 */
3480static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3481 struct wireless_dev *wdev,
3482 const void *data, int data_len)
3483{
3484 int ret;
3485
3486 cds_ssr_protect(__func__);
3487 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
3488 cds_ssr_unprotect(__func__);
3489
3490 return ret;
3491}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003492#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003493
3494static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
3495 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
3496 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
3497 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07003498 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003499};
3500
3501/**
3502 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3503 * @wiphy: pointer to wireless wiphy structure.
3504 * @wdev: pointer to wireless_dev structure.
3505 * @data: Pointer to the data to be passed via vendor interface
3506 * @data_len:Length of the data to be passed
3507 *
3508 * This is called when wlan driver needs to send wifi driver related info
3509 * (driver/fw version) to the user space application upon request.
3510 *
3511 * Return: Return the Success or Failure code.
3512 */
3513static int
3514__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3515 struct wireless_dev *wdev,
3516 const void *data, int data_len)
3517{
3518 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3519 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07003520 tSirVersionString driver_version;
3521 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003522 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003523 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07003524 struct sk_buff *reply_skb;
3525 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003526
Jeff Johnson1f61b612016-02-12 16:28:33 -08003527 ENTER_DEV(wdev->netdev);
3528
Anurag Chouhan6d760662016-02-20 16:05:43 +05303529 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003530 hdd_err("Command not allowed in FTM mode");
3531 return -EPERM;
3532 }
3533
3534 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303535 if (status)
3536 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003537
3538 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
3539 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003540 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003541 return -EINVAL;
3542 }
3543
3544 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003545 hdd_err("Rcvd req for Driver version");
3546 strlcpy(driver_version, QWLAN_VERSIONSTR,
3547 sizeof(driver_version));
3548 skb_len += strlen(driver_version) + 1;
3549 count++;
3550 }
3551
3552 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
3553 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003554 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
3555 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003556 snprintf(firmware_version, sizeof(firmware_version),
3557 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
3558 skb_len += strlen(firmware_version) + 1;
3559 count++;
3560 }
3561
3562 if (count == 0) {
3563 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003564 return -EINVAL;
3565 }
3566
Ryan Hsu7ac88852016-04-28 10:20:34 -07003567 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
3568 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
3569
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003570 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003571 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003572 return -ENOMEM;
3573 }
3574
Ryan Hsu7ac88852016-04-28 10:20:34 -07003575 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3576 if (nla_put_string(reply_skb,
3577 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
3578 driver_version))
3579 goto error_nla_fail;
3580 }
3581
3582 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3583 if (nla_put_string(reply_skb,
3584 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
3585 firmware_version))
3586 goto error_nla_fail;
3587 }
3588
3589 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
3590 if (nla_put_u32(reply_skb,
3591 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
3592 hdd_ctx->radio_index))
3593 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003594 }
3595
3596 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003597
3598error_nla_fail:
3599 hdd_err("nla put fail");
3600 kfree_skb(reply_skb);
3601 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003602}
3603
3604/**
3605 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3606 * @wiphy: pointer to wireless wiphy structure.
3607 * @wdev: pointer to wireless_dev structure.
3608 * @data: Pointer to the data to be passed via vendor interface
3609 * @data_len:Length of the data to be passed
3610 *
3611 * This is called when wlan driver needs to send wifi driver related info
3612 * (driver/fw version) to the user space application upon request.
3613 *
3614 * Return: Return the Success or Failure code.
3615 */
3616static int
3617wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3618 struct wireless_dev *wdev,
3619 const void *data, int data_len)
3620{
3621 int ret;
3622
3623 cds_ssr_protect(__func__);
3624 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
3625 cds_ssr_unprotect(__func__);
3626
3627 return ret;
3628}
3629
3630/**
3631 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3632 * @wiphy: pointer to wireless wiphy structure.
3633 * @wdev: pointer to wireless_dev structure.
3634 * @data: Pointer to the data to be passed via vendor interface
3635 * @data_len:Length of the data to be passed
3636 *
3637 * This is called by userspace to know the supported logger features
3638 *
3639 * Return: Return the Success or Failure code.
3640 */
3641static int
3642__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3643 struct wireless_dev *wdev,
3644 const void *data, int data_len)
3645{
3646 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3647 int status;
3648 uint32_t features;
3649 struct sk_buff *reply_skb = NULL;
3650
Jeff Johnson1f61b612016-02-12 16:28:33 -08003651 ENTER_DEV(wdev->netdev);
3652
Anurag Chouhan6d760662016-02-20 16:05:43 +05303653 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003654 hdd_err("Command not allowed in FTM mode");
3655 return -EPERM;
3656 }
3657
3658 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303659 if (status)
3660 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003661
3662 features = 0;
3663
3664 if (hdd_is_memdump_supported())
3665 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
3666 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
3667 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
3668 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
3669
3670 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
3671 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
3672 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003673 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003674 return -ENOMEM;
3675 }
3676
Jeff Johnson020db452016-06-29 14:37:26 -07003677 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003678 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
3679 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003680 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003681 kfree_skb(reply_skb);
3682 return -EINVAL;
3683 }
3684
3685 return cfg80211_vendor_cmd_reply(reply_skb);
3686}
3687
3688/**
3689 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3690 * @wiphy: pointer to wireless wiphy structure.
3691 * @wdev: pointer to wireless_dev structure.
3692 * @data: Pointer to the data to be passed via vendor interface
3693 * @data_len:Length of the data to be passed
3694 *
3695 * This is called by userspace to know the supported logger features
3696 *
3697 * Return: Return the Success or Failure code.
3698 */
3699static int
3700wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3701 struct wireless_dev *wdev,
3702 const void *data, int data_len)
3703{
3704 int ret;
3705
3706 cds_ssr_protect(__func__);
3707 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
3708 data, data_len);
3709 cds_ssr_unprotect(__func__);
3710
3711 return ret;
3712}
3713
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003714#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003715/**
3716 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
3717 * @hdd_ctx_ptr: pointer to HDD Context.
3718 * @bssid: pointer to bssid of roamed AP.
3719 * @req_rsn_ie: Pointer to request RSN IE
3720 * @req_rsn_len: Length of the request RSN IE
3721 * @rsp_rsn_ie: Pointer to response RSN IE
3722 * @rsp_rsn_len: Length of the response RSN IE
3723 * @roam_info_ptr: Pointer to the roaming related information
3724 *
3725 * This is called when wlan driver needs to send the roaming and
3726 * authorization information after roaming.
3727 *
3728 * The information that would be sent is the request RSN IE, response
3729 * RSN IE and BSSID of the newly roamed AP.
3730 *
3731 * If the Authorized status is authenticated, then additional parameters
3732 * like PTK's KCK and KEK and Replay Counter would also be passed to the
3733 * supplicant.
3734 *
3735 * The supplicant upon receiving this event would ignore the legacy
3736 * cfg80211_roamed call and use the entire information from this event.
3737 * The cfg80211_roamed should still co-exist since the kernel will
3738 * make use of the parameters even if the supplicant ignores it.
3739 *
3740 * Return: Return the Success or Failure code.
3741 */
3742int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid,
3743 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
3744 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
3745{
3746 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003747 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003748 ENTER();
3749
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303750 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003751 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003752
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07003753 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08003754 !roam_info_ptr->roamSynchInProgress)
3755 return 0;
3756
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003757 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
3758 NULL,
3759 ETH_ALEN + req_rsn_len + rsp_rsn_len +
3760 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
3761 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003762 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003763 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
3764 GFP_KERNEL);
3765
3766 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003767 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003768 return -EINVAL;
3769 }
3770
3771 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
3772 ETH_ALEN, bssid) ||
3773 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
3774 req_rsn_len, req_rsn_ie) ||
3775 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
3776 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003777 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003778 goto nla_put_failure;
3779 }
Jeff Johnson020db452016-06-29 14:37:26 -07003780 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003781 if (roam_info_ptr->synchAuthStatus ==
3782 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07003783 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08003784 if (nla_put_u8(skb,
3785 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
3786 hdd_err("nla put fail");
3787 goto nla_put_failure;
3788 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003789 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
3790 /* if FT or CCKM connection: dont send replay counter */
3791 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
3792 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
3793 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
3794 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
3795 nla_put(skb,
3796 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
3797 SIR_REPLAY_CTR_LEN,
3798 roam_info_ptr->replay_ctr)) {
3799 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08003800 hdd_err("failed to send replay counter.");
3801 goto nla_put_failure;
3802 }
3803 if (nla_put(skb,
3804 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
3805 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
3806 nla_put(skb,
3807 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
3808 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
3809 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003810 goto nla_put_failure;
3811 }
3812 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07003813 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003814 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
3815 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003816 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003817 goto nla_put_failure;
3818 }
3819 }
3820
Jeff Johnson020db452016-06-29 14:37:26 -07003821 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003822 roam_info_ptr->subnet_change_status);
3823
3824 /*
3825 * Add subnet change status if subnet has changed
3826 * 0 = unchanged
3827 * 1 = changed
3828 * 2 = unknown
3829 */
3830 if (roam_info_ptr->subnet_change_status) {
3831 if (nla_put_u8(skb,
3832 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
3833 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003834 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003835 goto nla_put_failure;
3836 }
3837 }
3838
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003839 cfg80211_vendor_event(skb, GFP_KERNEL);
3840 return 0;
3841
3842nla_put_failure:
3843 kfree_skb(skb);
3844 return -EINVAL;
3845}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003846#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003847
3848static const struct nla_policy
3849wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
3850
3851 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
3852 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
3853 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
3854};
3855
3856
3857/**
3858 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3859 * vendor command
3860 *
3861 * @wiphy: wiphy device pointer
3862 * @wdev: wireless device pointer
3863 * @data: Vendor command data buffer
3864 * @data_len: Buffer length
3865 *
3866 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3867 *
3868 * Return: Error code.
3869 */
3870static int
3871__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3872 struct wireless_dev *wdev,
3873 const void *data,
3874 int data_len)
3875{
3876 struct net_device *dev = wdev->netdev;
3877 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3878 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3879 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
3880 int ret_val = 0;
3881 u32 modulated_dtim;
3882 u16 stats_avg_factor;
3883 u32 guard_time;
Krunal Sonie3531942016-04-12 17:43:53 -07003884 u32 ftm_capab;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303885 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003886
Jeff Johnson1f61b612016-02-12 16:28:33 -08003887 ENTER_DEV(dev);
3888
Anurag Chouhan6d760662016-02-20 16:05:43 +05303889 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003890 hdd_err("Command not allowed in FTM mode");
3891 return -EPERM;
3892 }
3893
3894 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303895 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003896 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003897
3898 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
3899 data, data_len,
3900 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07003901 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003902 return -EINVAL;
3903 }
3904
Krunal Sonie3531942016-04-12 17:43:53 -07003905 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
3906 ftm_capab = nla_get_u32(tb[
3907 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
3908 hdd_ctx->config->fine_time_meas_cap =
3909 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
3910 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
3911 hdd_ctx->config->fine_time_meas_cap);
3912 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
3913 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
3914 hdd_ctx->config->fine_time_meas_cap);
3915 }
3916
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003917 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
3918 modulated_dtim = nla_get_u32(
3919 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
3920
3921 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
3922 adapter->sessionId,
3923 modulated_dtim);
3924
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303925 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003926 ret_val = -EPERM;
3927 }
3928
3929 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
3930 stats_avg_factor = nla_get_u16(
3931 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
3932 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
3933 adapter->sessionId,
3934 stats_avg_factor);
3935
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303936 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003937 ret_val = -EPERM;
3938 }
3939
3940
3941 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
3942 guard_time = nla_get_u32(
3943 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
3944 status = sme_configure_guard_time(hdd_ctx->hHal,
3945 adapter->sessionId,
3946 guard_time);
3947
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303948 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003949 ret_val = -EPERM;
3950 }
3951
3952 return ret_val;
3953}
3954
3955/**
3956 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3957 * vendor command
3958 *
3959 * @wiphy: wiphy device pointer
3960 * @wdev: wireless device pointer
3961 * @data: Vendor command data buffer
3962 * @data_len: Buffer length
3963 *
3964 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3965 *
3966 * Return: EOK or other error codes.
3967 */
3968static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3969 struct wireless_dev *wdev,
3970 const void *data,
3971 int data_len)
3972{
3973 int ret;
3974
3975 cds_ssr_protect(__func__);
3976 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
3977 data, data_len);
3978 cds_ssr_unprotect(__func__);
3979
3980 return ret;
3981}
3982
3983static const struct
3984nla_policy
3985qca_wlan_vendor_wifi_logger_start_policy
3986[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
3987 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
3988 = {.type = NLA_U32 },
3989 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
3990 = {.type = NLA_U32 },
3991 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
3992 = {.type = NLA_U32 },
3993};
3994
3995/**
3996 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
3997 * or disable the collection of packet statistics from the firmware
3998 * @wiphy: WIPHY structure pointer
3999 * @wdev: Wireless device structure pointer
4000 * @data: Pointer to the data received
4001 * @data_len: Length of the data received
4002 *
4003 * This function enables or disables the collection of packet statistics from
4004 * the firmware
4005 *
4006 * Return: 0 on success and errno on failure
4007 */
4008static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4009 struct wireless_dev *wdev,
4010 const void *data,
4011 int data_len)
4012{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304013 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004014 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4015 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4016 struct sir_wifi_start_log start_log;
4017
Jeff Johnson1f61b612016-02-12 16:28:33 -08004018 ENTER_DEV(wdev->netdev);
4019
Anurag Chouhan6d760662016-02-20 16:05:43 +05304020 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004021 hdd_err("Command not allowed in FTM mode");
4022 return -EPERM;
4023 }
4024
4025 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304026 if (status)
4027 return status;
4028
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004029
4030 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4031 data, data_len,
4032 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004033 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004034 return -EINVAL;
4035 }
4036
4037 /* Parse and fetch ring id */
4038 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004039 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004040 return -EINVAL;
4041 }
4042 start_log.ring_id = nla_get_u32(
4043 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004044 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004045
4046 /* Parse and fetch verbose level */
4047 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004048 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004049 return -EINVAL;
4050 }
4051 start_log.verbose_level = nla_get_u32(
4052 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004053 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004054
4055 /* Parse and fetch flag */
4056 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004057 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004058 return -EINVAL;
4059 }
4060 start_log.flag = nla_get_u32(
4061 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004062 hdd_info("flag=%d", start_log.flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004063
4064 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4065
4066 if (start_log.ring_id == RING_ID_WAKELOCK) {
4067 /* Start/stop wakelock events */
4068 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4069 cds_set_wakelock_logging(true);
4070 else
4071 cds_set_wakelock_logging(false);
4072 return 0;
4073 }
4074
4075 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304076 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004077 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004078 status);
4079 return -EINVAL;
4080 }
4081 return 0;
4082}
4083
4084/**
4085 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4086 * or disable the collection of packet statistics from the firmware
4087 * @wiphy: WIPHY structure pointer
4088 * @wdev: Wireless device structure pointer
4089 * @data: Pointer to the data received
4090 * @data_len: Length of the data received
4091 *
4092 * This function is used to enable or disable the collection of packet
4093 * statistics from the firmware
4094 *
4095 * Return: 0 on success and errno on failure
4096 */
4097static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4098 struct wireless_dev *wdev,
4099 const void *data,
4100 int data_len)
4101{
4102 int ret = 0;
4103
4104 cds_ssr_protect(__func__);
4105 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4106 wdev, data, data_len);
4107 cds_ssr_unprotect(__func__);
4108
4109 return ret;
4110}
4111
4112static const struct
4113nla_policy
4114qca_wlan_vendor_wifi_logger_get_ring_data_policy
4115[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4116 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4117 = {.type = NLA_U32 },
4118};
4119
4120/**
4121 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4122 * @wiphy: WIPHY structure pointer
4123 * @wdev: Wireless device structure pointer
4124 * @data: Pointer to the data received
4125 * @data_len: Length of the data received
4126 *
4127 * This function is used to flush or retrieve the per packet statistics from
4128 * the driver
4129 *
4130 * Return: 0 on success and errno on failure
4131 */
4132static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4133 struct wireless_dev *wdev,
4134 const void *data,
4135 int data_len)
4136{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304137 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004138 uint32_t ring_id;
4139 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4140 struct nlattr *tb
4141 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4142
Jeff Johnson1f61b612016-02-12 16:28:33 -08004143 ENTER_DEV(wdev->netdev);
4144
Anurag Chouhan6d760662016-02-20 16:05:43 +05304145 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004146 hdd_err("Command not allowed in FTM mode");
4147 return -EPERM;
4148 }
4149
4150 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304151 if (status)
4152 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004153
4154 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
4155 data, data_len,
4156 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004157 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004158 return -EINVAL;
4159 }
4160
4161 /* Parse and fetch ring id */
4162 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004163 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004164 return -EINVAL;
4165 }
4166
4167 ring_id = nla_get_u32(
4168 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
4169
4170 if (ring_id == RING_ID_PER_PACKET_STATS) {
4171 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07004172 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05304173 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
4174 /*
4175 * As part of DRIVER ring ID, flush both driver and fw logs.
4176 * For other Ring ID's driver doesn't have any rings to flush
4177 */
4178 hdd_notice("Bug report triggered by framework");
4179
4180 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
4181 WLAN_LOG_INDICATOR_FRAMEWORK,
4182 WLAN_LOG_REASON_CODE_UNUSED,
4183 true, false);
4184 if (QDF_STATUS_SUCCESS != status) {
4185 hdd_err("Failed to trigger bug report");
4186 return -EINVAL;
4187 }
4188 } else {
4189 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
4190 WLAN_LOG_INDICATOR_FRAMEWORK,
4191 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004192 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004193 return 0;
4194}
4195
4196/**
4197 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
4198 * @wiphy: WIPHY structure pointer
4199 * @wdev: Wireless device structure pointer
4200 * @data: Pointer to the data received
4201 * @data_len: Length of the data received
4202 *
4203 * This function is used to flush or retrieve the per packet statistics from
4204 * the driver
4205 *
4206 * Return: 0 on success and errno on failure
4207 */
4208static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4209 struct wireless_dev *wdev,
4210 const void *data,
4211 int data_len)
4212{
4213 int ret = 0;
4214
4215 cds_ssr_protect(__func__);
4216 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
4217 wdev, data, data_len);
4218 cds_ssr_unprotect(__func__);
4219
4220 return ret;
4221}
4222
4223#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4224/**
4225 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
4226 * @hdd_ctx: HDD context
4227 * @request_id: [input] request id
4228 * @pattern_id: [output] pattern id
4229 *
4230 * This function loops through request id to pattern id array
4231 * if the slot is available, store the request id and return pattern id
4232 * if entry exists, return the pattern id
4233 *
4234 * Return: 0 on success and errno on failure
4235 */
4236static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4237 uint32_t request_id,
4238 uint8_t *pattern_id)
4239{
4240 uint32_t i;
4241
4242 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4243 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4244 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
4245 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
4246 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4247 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4248 return 0;
4249 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
4250 request_id) {
4251 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4252 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4253 return 0;
4254 }
4255 }
4256 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4257 return -EINVAL;
4258}
4259
4260/**
4261 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
4262 * @hdd_ctx: HDD context
4263 * @request_id: [input] request id
4264 * @pattern_id: [output] pattern id
4265 *
4266 * This function loops through request id to pattern id array
4267 * reset request id to 0 (slot available again) and
4268 * return pattern id
4269 *
4270 * Return: 0 on success and errno on failure
4271 */
4272static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4273 uint32_t request_id,
4274 uint8_t *pattern_id)
4275{
4276 uint32_t i;
4277
4278 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4279 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4280 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
4281 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4282 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4283 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4284 return 0;
4285 }
4286 }
4287 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4288 return -EINVAL;
4289}
4290
4291
4292/*
4293 * define short names for the global vendor params
4294 * used by __wlan_hdd_cfg80211_offloaded_packets()
4295 */
4296#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
4297#define PARAM_REQUEST_ID \
4298 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
4299#define PARAM_CONTROL \
4300 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
4301#define PARAM_IP_PACKET \
4302 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
4303#define PARAM_SRC_MAC_ADDR \
4304 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
4305#define PARAM_DST_MAC_ADDR \
4306 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
4307#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
4308
4309/**
4310 * wlan_hdd_add_tx_ptrn() - add tx pattern
4311 * @adapter: adapter pointer
4312 * @hdd_ctx: hdd context
4313 * @tb: nl attributes
4314 *
4315 * This function reads the NL attributes and forms a AddTxPtrn message
4316 * posts it to SME.
4317 *
4318 */
4319static int
4320wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4321 struct nlattr **tb)
4322{
4323 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304324 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004325 uint32_t request_id, ret, len;
4326 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304327 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004328 uint16_t eth_type = htons(ETH_P_IP);
4329
4330 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004331 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004332 return -ENOTSUPP;
4333 }
4334
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304335 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004336 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004337 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004338 return -ENOMEM;
4339 }
4340
4341 /* Parse and fetch request Id */
4342 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004343 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004344 goto fail;
4345 }
4346
4347 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4348 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004349 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004350 return -EINVAL;
4351 }
Jeff Johnson77848112016-06-29 14:52:06 -07004352 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004353
4354 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004355 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004356 goto fail;
4357 }
4358 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07004359 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004360 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07004361 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004362 goto fail;
4363 }
4364
4365 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004366 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004367 goto fail;
4368 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08004369 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05304370 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004371 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004372 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004373
Anurag Chouhanc5548422016-02-24 18:33:27 +05304374 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004375 &adapter->macAddressCurrent)) {
4376 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004377 goto fail;
4378 }
4379
4380 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004381 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004382 goto fail;
4383 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05304384 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004385 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004386 MAC_ADDR_ARRAY(dst_addr.bytes));
4387
4388 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004389 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004390 goto fail;
4391 }
4392 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07004393 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004394
4395 if (add_req->ucPtrnSize < 0 ||
4396 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
4397 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004398 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004399 add_req->ucPtrnSize);
4400 goto fail;
4401 }
4402
4403 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304404 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05304405 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304406 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304407 QDF_MAC_ADDR_SIZE);
4408 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304409 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004410 len += 2;
4411
4412 /*
4413 * This is the IP packet, add 14 bytes Ethernet (802.3) header
4414 * ------------------------------------------------------------
4415 * | 14 bytes Ethernet (802.3) header | IP header and payload |
4416 * ------------------------------------------------------------
4417 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304418 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004419 nla_data(tb[PARAM_IP_PACKET]),
4420 add_req->ucPtrnSize);
4421 add_req->ucPtrnSize += len;
4422
4423 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4424 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004425 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004426 goto fail;
4427 }
4428 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004429 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004430
4431 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304432 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004433 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004434 goto fail;
4435 }
4436
4437 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304438 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004439 return 0;
4440
4441fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304442 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004443 return -EINVAL;
4444}
4445
4446/**
4447 * wlan_hdd_del_tx_ptrn() - delete tx pattern
4448 * @adapter: adapter pointer
4449 * @hdd_ctx: hdd context
4450 * @tb: nl attributes
4451 *
4452 * This function reads the NL attributes and forms a DelTxPtrn message
4453 * posts it to SME.
4454 *
4455 */
4456static int
4457wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4458 struct nlattr **tb)
4459{
4460 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304461 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004462 uint32_t request_id, ret;
4463 uint8_t pattern_id = 0;
4464
4465 /* Parse and fetch request Id */
4466 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004467 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004468 return -EINVAL;
4469 }
4470 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4471 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004472 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004473 return -EINVAL;
4474 }
4475
4476 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4477 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004478 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004479 return -EINVAL;
4480 }
4481
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304482 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004483 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004484 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004485 return -ENOMEM;
4486 }
4487
Anurag Chouhanc5548422016-02-24 18:33:27 +05304488 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004489 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004490 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004491 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004492 request_id, del_req->ucPtrnId);
4493
4494 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304495 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004496 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004497 goto fail;
4498 }
4499
4500 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304501 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004502 return 0;
4503
4504fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304505 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004506 return -EINVAL;
4507}
4508
4509
4510/**
4511 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
4512 * @wiphy: Pointer to wireless phy
4513 * @wdev: Pointer to wireless device
4514 * @data: Pointer to data
4515 * @data_len: Data length
4516 *
4517 * Return: 0 on success, negative errno on failure
4518 */
4519static int
4520__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4521 struct wireless_dev *wdev,
4522 const void *data,
4523 int data_len)
4524{
4525 struct net_device *dev = wdev->netdev;
4526 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4527 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4528 struct nlattr *tb[PARAM_MAX + 1];
4529 uint8_t control;
4530 int ret;
4531 static const struct nla_policy policy[PARAM_MAX + 1] = {
4532 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4533 [PARAM_CONTROL] = { .type = NLA_U32 },
4534 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304535 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004536 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304537 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004538 [PARAM_PERIOD] = { .type = NLA_U32 },
4539 };
4540
Jeff Johnson1f61b612016-02-12 16:28:33 -08004541 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004542
Anurag Chouhan6d760662016-02-20 16:05:43 +05304543 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004544 hdd_err("Command not allowed in FTM mode");
4545 return -EPERM;
4546 }
4547
4548 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304549 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004550 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004551
4552 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004553 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004554 return -ENOTSUPP;
4555 }
4556
4557 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004558 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004559 return -EINVAL;
4560 }
4561
4562 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004563 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004564 return -EINVAL;
4565 }
4566 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07004567 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004568
4569 if (control == WLAN_START_OFFLOADED_PACKETS)
4570 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
4571 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
4572 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
4573 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004574 hdd_err("Invalid control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004575 return -EINVAL;
4576 }
4577}
4578
4579/*
4580 * done with short names for the global vendor params
4581 * used by __wlan_hdd_cfg80211_offloaded_packets()
4582 */
4583#undef PARAM_MAX
4584#undef PARAM_REQUEST_ID
4585#undef PARAM_CONTROL
4586#undef PARAM_IP_PACKET
4587#undef PARAM_SRC_MAC_ADDR
4588#undef PARAM_DST_MAC_ADDR
4589#undef PARAM_PERIOD
4590
4591/**
4592 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
4593 * @wiphy: wiphy structure pointer
4594 * @wdev: Wireless device structure pointer
4595 * @data: Pointer to the data received
4596 * @data_len: Length of @data
4597 *
4598 * Return: 0 on success; errno on failure
4599 */
4600static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4601 struct wireless_dev *wdev,
4602 const void *data,
4603 int data_len)
4604{
4605 int ret = 0;
4606
4607 cds_ssr_protect(__func__);
4608 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
4609 wdev, data, data_len);
4610 cds_ssr_unprotect(__func__);
4611
4612 return ret;
4613}
4614#endif
4615
4616/*
4617 * define short names for the global vendor params
4618 * used by __wlan_hdd_cfg80211_monitor_rssi()
4619 */
4620#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
4621#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
4622#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
4623#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
4624#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
4625
4626/**
4627 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
4628 * @wiphy: Pointer to wireless phy
4629 * @wdev: Pointer to wireless device
4630 * @data: Pointer to data
4631 * @data_len: Data length
4632 *
4633 * Return: 0 on success, negative errno on failure
4634 */
4635static int
4636__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
4637 struct wireless_dev *wdev,
4638 const void *data,
4639 int data_len)
4640{
4641 struct net_device *dev = wdev->netdev;
4642 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4643 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4644 struct nlattr *tb[PARAM_MAX + 1];
4645 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304646 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004647 int ret;
4648 uint32_t control;
4649 static const struct nla_policy policy[PARAM_MAX + 1] = {
4650 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4651 [PARAM_CONTROL] = { .type = NLA_U32 },
4652 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
4653 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
4654 };
4655
Jeff Johnson1f61b612016-02-12 16:28:33 -08004656 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004657
4658 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304659 if (ret)
4660 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004661
4662 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004663 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004664 return -ENOTSUPP;
4665 }
4666
4667 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004668 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004669 return -EINVAL;
4670 }
4671
4672 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004673 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004674 return -EINVAL;
4675 }
4676
4677 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004678 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004679 return -EINVAL;
4680 }
4681
4682 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4683 req.session_id = adapter->sessionId;
4684 control = nla_get_u32(tb[PARAM_CONTROL]);
4685
4686 if (control == QCA_WLAN_RSSI_MONITORING_START) {
4687 req.control = true;
4688 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004689 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004690 return -EINVAL;
4691 }
4692
4693 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004694 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004695 return -EINVAL;
4696 }
4697
4698 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
4699 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
4700
4701 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004702 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004703 req.min_rssi, req.max_rssi);
4704 return -EINVAL;
4705 }
Jeff Johnson77848112016-06-29 14:52:06 -07004706 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004707 req.min_rssi, req.max_rssi);
4708
4709 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
4710 req.control = false;
4711 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004712 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004713 return -EINVAL;
4714 }
Jeff Johnson77848112016-06-29 14:52:06 -07004715 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004716 req.request_id, req.session_id, req.control);
4717
4718 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304719 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004720 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004721 return -EINVAL;
4722 }
4723
4724 return 0;
4725}
4726
4727/*
4728 * done with short names for the global vendor params
4729 * used by __wlan_hdd_cfg80211_monitor_rssi()
4730 */
4731#undef PARAM_MAX
4732#undef PARAM_CONTROL
4733#undef PARAM_REQUEST_ID
4734#undef PARAM_MAX_RSSI
4735#undef PARAM_MIN_RSSI
4736
4737/**
4738 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
4739 * @wiphy: wiphy structure pointer
4740 * @wdev: Wireless device structure pointer
4741 * @data: Pointer to the data received
4742 * @data_len: Length of @data
4743 *
4744 * Return: 0 on success; errno on failure
4745 */
4746static int
4747wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
4748 const void *data, int data_len)
4749{
4750 int ret;
4751
4752 cds_ssr_protect(__func__);
4753 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
4754 cds_ssr_unprotect(__func__);
4755
4756 return ret;
4757}
4758
4759/**
4760 * hdd_rssi_threshold_breached() - rssi breached NL event
4761 * @hddctx: HDD context
4762 * @data: rssi breached event data
4763 *
4764 * This function reads the rssi breached event %data and fill in the skb with
4765 * NL attributes and send up the NL event.
4766 *
4767 * Return: none
4768 */
4769void hdd_rssi_threshold_breached(void *hddctx,
4770 struct rssi_breach_event *data)
4771{
4772 hdd_context_t *hdd_ctx = hddctx;
4773 struct sk_buff *skb;
4774
4775 ENTER();
4776
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05304777 if (wlan_hdd_validate_context(hdd_ctx))
4778 return;
4779 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07004780 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004781 return;
4782 }
4783
4784 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
4785 NULL,
4786 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
4787 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
4788 GFP_KERNEL);
4789
4790 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07004791 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004792 return;
4793 }
4794
Jeff Johnson77848112016-06-29 14:52:06 -07004795 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004796 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07004797 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004798 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
4799
4800 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
4801 data->request_id) ||
4802 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
4803 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
4804 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
4805 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004806 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004807 goto fail;
4808 }
4809
4810 cfg80211_vendor_event(skb, GFP_KERNEL);
4811 return;
4812
4813fail:
4814 kfree_skb(skb);
4815 return;
4816}
4817
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05304818static const struct nla_policy
4819ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
4820 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
4821};
4822
4823/**
4824 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
4825 * @wiphy: Pointer to wireless phy
4826 * @wdev: Pointer to wireless device
4827 * @data: Pointer to data
4828 * @data_len: Length of @data
4829 *
4830 * Return: 0 on success, negative errno on failure
4831 */
4832static int
4833__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
4834 struct wireless_dev *wdev,
4835 const void *data, int data_len)
4836{
4837 int status;
4838 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
4839 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07004840 struct net_device *dev = wdev->netdev;
4841 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05304842
4843 ENTER_DEV(wdev->netdev);
4844
4845 status = wlan_hdd_validate_context(pHddCtx);
4846 if (0 != status)
4847 return status;
4848 if (!pHddCtx->config->fhostNSOffload) {
4849 hdd_err("ND Offload not supported");
4850 return -EINVAL;
4851 }
4852
4853 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
4854 (struct nlattr *)data,
4855 data_len, ns_offload_set_policy)) {
4856 hdd_err("nla_parse failed");
4857 return -EINVAL;
4858 }
4859
4860 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
4861 hdd_err("ND Offload flag attribute not present");
4862 return -EINVAL;
4863 }
4864
4865 pHddCtx->ns_offload_enable =
4866 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
4867
Dustin Brownd8279d22016-09-07 14:52:57 -07004868 /* update ns offload in case it is already enabled/disabled */
4869 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
4870
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05304871 return 0;
4872}
4873
4874/**
4875 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
4876 * @wiphy: pointer to wireless wiphy structure.
4877 * @wdev: pointer to wireless_dev structure.
4878 * @data: Pointer to the data to be passed via vendor interface
4879 * @data_len:Length of the data to be passed
4880 *
4881 * Return: Return the Success or Failure code.
4882 */
4883static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
4884 struct wireless_dev *wdev,
4885 const void *data, int data_len)
4886{
4887 int ret;
4888
4889 cds_ssr_protect(__func__);
4890 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
4891 cds_ssr_unprotect(__func__);
4892
4893 return ret;
4894}
4895
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004896/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
4897 * @wiphy: Pointer to wireless phy
4898 * @wdev: Pointer to wireless device
4899 * @data: Pointer to data
4900 * @data_len: Data length
4901 *
4902 * This function return the preferred frequency list generated by the policy
4903 * manager.
4904 *
4905 * Return: success or failure code
4906 */
4907static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
4908 struct wireless_dev
4909 *wdev, const void *data,
4910 int data_len)
4911{
4912 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4913 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304914 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05304915 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004916 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05304917 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004918 enum cds_con_mode intf_mode;
4919 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
4920 struct sk_buff *reply_skb;
4921
Jeff Johnson1f61b612016-02-12 16:28:33 -08004922 ENTER_DEV(wdev->netdev);
4923
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004924 ret = wlan_hdd_validate_context(hdd_ctx);
4925 if (ret)
4926 return -EINVAL;
4927
4928 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
4929 data, data_len, NULL)) {
4930 hdd_err("Invalid ATTR");
4931 return -EINVAL;
4932 }
4933
4934 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
4935 hdd_err("attr interface type failed");
4936 return -EINVAL;
4937 }
4938
4939 intf_mode = nla_get_u32(tb
4940 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
4941
4942 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
4943 hdd_err("Invalid interface type");
4944 return -EINVAL;
4945 }
4946
4947 hdd_debug("Userspace requested pref freq list");
4948
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05304949 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
4950 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304951 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004952 hdd_err("Get pcl failed");
4953 return -EINVAL;
4954 }
4955
4956 /* convert channel number to frequency */
4957 for (i = 0; i < pcl_len; i++) {
4958 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
4959 freq_list[i] =
4960 ieee80211_channel_to_frequency(pcl[i],
4961 IEEE80211_BAND_2GHZ);
4962 else
4963 freq_list[i] =
4964 ieee80211_channel_to_frequency(pcl[i],
4965 IEEE80211_BAND_5GHZ);
4966 }
4967
4968 /* send the freq_list back to supplicant */
4969 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
4970 sizeof(u32) *
4971 pcl_len +
4972 NLMSG_HDRLEN);
4973
4974 if (!reply_skb) {
4975 hdd_err("Allocate reply_skb failed");
4976 return -EINVAL;
4977 }
4978
4979 if (nla_put_u32(reply_skb,
4980 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
4981 intf_mode) ||
4982 nla_put(reply_skb,
4983 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
4984 sizeof(uint32_t) * pcl_len,
4985 freq_list)) {
4986 hdd_err("nla put fail");
4987 kfree_skb(reply_skb);
4988 return -EINVAL;
4989 }
4990
4991 return cfg80211_vendor_cmd_reply(reply_skb);
4992}
4993
4994/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
4995 * @wiphy: Pointer to wireless phy
4996 * @wdev: Pointer to wireless device
4997 * @data: Pointer to data
4998 * @data_len: Data length
4999 *
5000 * This function return the preferred frequency list generated by the policy
5001 * manager.
5002 *
5003 * Return: success or failure code
5004 */
5005static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5006 struct wireless_dev
5007 *wdev, const void *data,
5008 int data_len)
5009{
5010 int ret = 0;
5011
5012 cds_ssr_protect(__func__);
5013 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5014 data, data_len);
5015 cds_ssr_unprotect(__func__);
5016
5017 return ret;
5018}
5019
5020/**
5021 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5022 * @wiphy: Pointer to wireless phy
5023 * @wdev: Pointer to wireless device
5024 * @data: Pointer to data
5025 * @data_len: Data length
5026 *
5027 * Return: 0 on success, negative errno on failure
5028 */
5029static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5030 struct wireless_dev *wdev,
5031 const void *data,
5032 int data_len)
5033{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305034 struct net_device *ndev = wdev->netdev;
5035 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005036 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5037 int ret = 0;
5038 enum cds_con_mode intf_mode;
5039 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5040 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005041
Jeff Johnson1f61b612016-02-12 16:28:33 -08005042 ENTER_DEV(ndev);
5043
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005044 ret = wlan_hdd_validate_context(hdd_ctx);
5045 if (ret)
5046 return ret;
5047
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005048 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5049 data, data_len, NULL)) {
5050 hdd_err("Invalid ATTR");
5051 return -EINVAL;
5052 }
5053
5054 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5055 hdd_err("attr interface type failed");
5056 return -EINVAL;
5057 }
5058
5059 intf_mode = nla_get_u32(tb
5060 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5061
5062 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5063 hdd_err("Invalid interface type");
5064 return -EINVAL;
5065 }
5066
5067 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5068 hdd_err("attr probable freq failed");
5069 return -EINVAL;
5070 }
5071
5072 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5073 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5074
5075 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005076 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005077 channel_hint, HW_MODE_20_MHZ)) {
5078 hdd_err("Set channel hint failed due to concurrency check");
5079 return -EINVAL;
5080 }
5081
Krunal Soni09e55032016-06-07 10:06:55 -07005082 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5083 hdd_warn("Remain On Channel Pending");
5084
Krunal Soni3091bcc2016-06-23 12:28:21 -07005085 ret = qdf_reset_connection_update();
5086 if (!QDF_IS_STATUS_SUCCESS(ret))
5087 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005088
Krunal Soni3091bcc2016-06-23 12:28:21 -07005089 ret = cds_current_connections_update(adapter->sessionId,
5090 channel_hint,
5091 SIR_UPDATE_REASON_SET_OPER_CHAN);
5092 if (QDF_STATUS_E_FAILURE == ret) {
5093 /* return in the failure case */
5094 hdd_err("ERROR: connections update failed!!");
5095 return -EINVAL;
5096 }
5097
5098 if (QDF_STATUS_SUCCESS == ret) {
5099 /*
5100 * Success is the only case for which we expect hw mode
5101 * change to take place, hence we need to wait.
5102 * For any other return value it should be a pass
5103 * through
5104 */
5105 ret = qdf_wait_for_connection_update();
5106 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5107 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005108 return -EINVAL;
5109 }
5110
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005111 }
5112
5113 return 0;
5114}
5115
5116/**
5117 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5118 * @wiphy: Pointer to wireless phy
5119 * @wdev: Pointer to wireless device
5120 * @data: Pointer to data
5121 * @data_len: Data length
5122 *
5123 * Return: 0 on success, negative errno on failure
5124 */
5125static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5126 struct wireless_dev *wdev,
5127 const void *data,
5128 int data_len)
5129{
5130 int ret = 0;
5131
5132 cds_ssr_protect(__func__);
5133 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5134 data, data_len);
5135 cds_ssr_unprotect(__func__);
5136
5137 return ret;
5138}
5139
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305140static const struct
5141nla_policy
5142qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5143 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5144};
5145
5146/**
5147 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
5148 * @wiphy: WIPHY structure pointer
5149 * @wdev: Wireless device structure pointer
5150 * @data: Pointer to the data received
5151 * @data_len: Length of the data received
5152 *
5153 * This function is used to get link properties like nss, rate flags and
5154 * operating frequency for the active connection with the given peer.
5155 *
5156 * Return: 0 on success and errno on failure
5157 */
5158static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5159 struct wireless_dev *wdev,
5160 const void *data,
5161 int data_len)
5162{
5163 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5164 struct net_device *dev = wdev->netdev;
5165 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5166 hdd_station_ctx_t *hdd_sta_ctx;
5167 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05305168 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305169 uint32_t sta_id;
5170 struct sk_buff *reply_skb;
5171 uint32_t rate_flags = 0;
5172 uint8_t nss;
5173 uint8_t final_rate_flags = 0;
5174 uint32_t freq;
5175
Jeff Johnson1f61b612016-02-12 16:28:33 -08005176 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305177
Anurag Chouhan6d760662016-02-20 16:05:43 +05305178 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305179 hdd_err("Command not allowed in FTM mode");
5180 return -EPERM;
5181 }
5182
5183 if (0 != wlan_hdd_validate_context(hdd_ctx))
5184 return -EINVAL;
5185
5186 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
5187 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005188 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305189 return -EINVAL;
5190 }
5191
5192 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005193 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305194 adapter->device_mode);
5195 return -EINVAL;
5196 }
5197
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305198 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05305199 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005200 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305201 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
5202
Krunal Sonib4326f22016-03-10 13:05:51 -08005203 if (adapter->device_mode == QDF_STA_MODE ||
5204 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305205 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
5206 if ((hdd_sta_ctx->conn_info.connState !=
5207 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305208 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305209 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005210 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305211 MAC_ADDR_ARRAY(peer_mac));
5212 return -EINVAL;
5213 }
5214
5215 nss = hdd_sta_ctx->conn_info.nss;
5216 freq = cds_chan_to_freq(
5217 hdd_sta_ctx->conn_info.operationChannel);
5218 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08005219 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
5220 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305221
5222 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
5223 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05305224 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305225 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305226 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305227 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305228 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305229 break;
5230 }
5231
5232 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07005233 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305234 MAC_ADDR_ARRAY(peer_mac));
5235 return -EINVAL;
5236 }
5237
5238 nss = adapter->aStaInfo[sta_id].nss;
5239 freq = cds_chan_to_freq(
5240 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
5241 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
5242 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07005243 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305244 MAC_ADDR_ARRAY(peer_mac));
5245 return -EINVAL;
5246 }
5247
5248 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
5249 if (rate_flags & eHAL_TX_RATE_VHT80) {
5250 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005251#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305252 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005253#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305254 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
5255 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005256#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305257 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005258#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305259 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
5260 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
5261 } else if (rate_flags &
5262 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
5263 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005264#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305265 if (rate_flags & eHAL_TX_RATE_HT40)
5266 final_rate_flags |=
5267 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005268#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305269 }
5270
5271 if (rate_flags & eHAL_TX_RATE_SGI) {
5272 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
5273 final_rate_flags |= RATE_INFO_FLAGS_MCS;
5274 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
5275 }
5276 }
5277
5278 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5279 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
5280
5281 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005282 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305283 return -EINVAL;
5284 }
5285
5286 if (nla_put_u8(reply_skb,
5287 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
5288 nss) ||
5289 nla_put_u8(reply_skb,
5290 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
5291 final_rate_flags) ||
5292 nla_put_u32(reply_skb,
5293 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
5294 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005295 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305296 kfree_skb(reply_skb);
5297 return -EINVAL;
5298 }
5299
5300 return cfg80211_vendor_cmd_reply(reply_skb);
5301}
5302
5303/**
5304 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
5305 * properties.
5306 * @wiphy: WIPHY structure pointer
5307 * @wdev: Wireless device structure pointer
5308 * @data: Pointer to the data received
5309 * @data_len: Length of the data received
5310 *
5311 * This function is used to get link properties like nss, rate flags and
5312 * operating frequency for the active connection with the given peer.
5313 *
5314 * Return: 0 on success and errno on failure
5315 */
5316static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5317 struct wireless_dev *wdev,
5318 const void *data,
5319 int data_len)
5320{
5321 int ret = 0;
5322
5323 cds_ssr_protect(__func__);
5324 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
5325 wdev, data, data_len);
5326 cds_ssr_unprotect(__func__);
5327
5328 return ret;
5329}
5330
Peng Xu278d0122015-09-24 16:34:17 -07005331static const struct
5332nla_policy
5333qca_wlan_vendor_ota_test_policy
5334[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
5335 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
5336};
5337
5338/**
5339 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
5340 * @wiphy: Pointer to wireless phy
5341 * @wdev: Pointer to wireless device
5342 * @data: Pointer to data
5343 * @data_len: Data length
5344 *
5345 * Return: 0 on success, negative errno on failure
5346 */
5347static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5348 struct wireless_dev *wdev,
5349 const void *data,
5350 int data_len)
5351{
5352 struct net_device *dev = wdev->netdev;
5353 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5354 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
5355 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5356 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
5357 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305358 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07005359 uint32_t current_roam_state;
5360
Jeff Johnson1f61b612016-02-12 16:28:33 -08005361 ENTER_DEV(dev);
5362
Anurag Chouhan6d760662016-02-20 16:05:43 +05305363 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07005364 hdd_err("Command not allowed in FTM mode");
5365 return -EPERM;
5366 }
5367
5368 if (0 != wlan_hdd_validate_context(hdd_ctx))
5369 return -EINVAL;
5370
5371 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
5372 data, data_len,
5373 qca_wlan_vendor_ota_test_policy)) {
5374 hdd_err("invalid attr");
5375 return -EINVAL;
5376 }
5377
5378 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
5379 hdd_err("attr ota test failed");
5380 return -EINVAL;
5381 }
5382
5383 ota_enable = nla_get_u8(
5384 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
5385
5386 hdd_info(" OTA test enable = %d", ota_enable);
5387 if (ota_enable != 1) {
5388 hdd_err("Invalid value, only enable test mode is supported!");
5389 return -EINVAL;
5390 }
5391
5392 current_roam_state =
5393 sme_get_current_roam_state(hal, adapter->sessionId);
5394 status = sme_stop_roaming(hal, adapter->sessionId,
5395 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305396 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005397 hdd_err("Enable/Disable roaming failed");
5398 return -EINVAL;
5399 }
5400
5401 status = sme_ps_enable_disable(hal, adapter->sessionId,
5402 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305403 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005404 hdd_err("Enable/Disable power save failed");
5405 /* restore previous roaming setting */
5406 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
5407 current_roam_state == eCSR_ROAMING_STATE_JOINED)
5408 status = sme_start_roaming(hal, adapter->sessionId,
5409 eCsrHddIssued);
5410 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
5411 current_roam_state == eCSR_ROAMING_STATE_IDLE)
5412 status = sme_stop_roaming(hal, adapter->sessionId,
5413 eCsrHddIssued);
5414
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305415 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07005416 hdd_err("Restoring roaming state failed");
5417
5418 return -EINVAL;
5419 }
5420
5421
5422 return 0;
5423}
5424
5425/**
5426 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
5427 * @wiphy: Pointer to wireless phy
5428 * @wdev: Pointer to wireless device
5429 * @data: Pointer to data
5430 * @data_len: Data length
5431 *
5432 * Return: 0 on success, negative errno on failure
5433 */
5434static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5435 struct wireless_dev *wdev,
5436 const void *data,
5437 int data_len)
5438{
5439 int ret = 0;
5440
5441 cds_ssr_protect(__func__);
5442 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
5443 cds_ssr_unprotect(__func__);
5444
5445 return ret;
5446}
5447
Peng Xu4d67c8f2015-10-16 16:02:26 -07005448/**
5449 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5450 * @wiphy: Pointer to wireless phy
5451 * @wdev: Pointer to wireless device
5452 * @data: Pointer to data
5453 * @data_len: Data length
5454 *
5455 * Return: 0 on success, negative errno on failure
5456 */
5457static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5458 struct wireless_dev *wdev,
5459 const void *data,
5460 int data_len)
5461{
5462 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5463 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005464 hdd_adapter_t *adapter;
5465 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005466 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
5467 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005468 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005469
Jeff Johnson1f61b612016-02-12 16:28:33 -08005470 ENTER_DEV(dev);
5471
Peng Xu4d67c8f2015-10-16 16:02:26 -07005472 ret = wlan_hdd_validate_context(hdd_ctx);
5473 if (ret)
5474 return ret;
5475
5476 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5477
5478 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
5479 data, data_len, NULL)) {
5480 hdd_err("Invalid ATTR");
5481 return -EINVAL;
5482 }
5483
5484 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
5485 hdd_err("attr tx power scale failed");
5486 return -EINVAL;
5487 }
5488
5489 scale_value = nla_get_u8(tb
5490 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
5491
5492 if (scale_value > MAX_TXPOWER_SCALE) {
5493 hdd_err("Invalid tx power scale level");
5494 return -EINVAL;
5495 }
5496
Peng Xu62c8c432016-05-09 15:23:02 -07005497 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005498
Peng Xu62c8c432016-05-09 15:23:02 -07005499 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005500 hdd_err("Set tx power scale failed");
5501 return -EINVAL;
5502 }
5503
5504 return 0;
5505}
5506
5507/**
5508 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5509 * @wiphy: Pointer to wireless phy
5510 * @wdev: Pointer to wireless device
5511 * @data: Pointer to data
5512 * @data_len: Data length
5513 *
5514 * Return: 0 on success, negative errno on failure
5515 */
5516static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5517 struct wireless_dev *wdev,
5518 const void *data,
5519 int data_len)
5520{
Peng Xu62c8c432016-05-09 15:23:02 -07005521 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005522
5523 cds_ssr_protect(__func__);
5524 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
5525 data, data_len);
5526 cds_ssr_unprotect(__func__);
5527
5528 return ret;
5529}
5530
5531/**
5532 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5533 * @wiphy: Pointer to wireless phy
5534 * @wdev: Pointer to wireless device
5535 * @data: Pointer to data
5536 * @data_len: Data length
5537 *
5538 * Return: 0 on success, negative errno on failure
5539 */
5540static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5541 struct wireless_dev *wdev,
5542 const void *data,
5543 int data_len)
5544{
5545 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5546 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005547 hdd_adapter_t *adapter;
5548 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005549 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
5550 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005551 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005552
Jeff Johnson1f61b612016-02-12 16:28:33 -08005553 ENTER_DEV(dev);
5554
Peng Xu4d67c8f2015-10-16 16:02:26 -07005555 ret = wlan_hdd_validate_context(hdd_ctx);
5556 if (ret)
5557 return ret;
5558
5559 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5560
5561 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
5562 data, data_len, NULL)) {
5563 hdd_err("Invalid ATTR");
5564 return -EINVAL;
5565 }
5566
5567 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
5568 hdd_err("attr tx power decrease db value failed");
5569 return -EINVAL;
5570 }
5571
5572 scale_value = nla_get_u8(tb
5573 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
5574
Peng Xu62c8c432016-05-09 15:23:02 -07005575 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
5576 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005577
Peng Xu62c8c432016-05-09 15:23:02 -07005578 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005579 hdd_err("Set tx power decrease db failed");
5580 return -EINVAL;
5581 }
5582
5583 return 0;
5584}
5585
5586/**
5587 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5588 * @wiphy: Pointer to wireless phy
5589 * @wdev: Pointer to wireless device
5590 * @data: Pointer to data
5591 * @data_len: Data length
5592 *
5593 * Return: 0 on success, negative errno on failure
5594 */
5595static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5596 struct wireless_dev *wdev,
5597 const void *data,
5598 int data_len)
5599{
Peng Xu62c8c432016-05-09 15:23:02 -07005600 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005601
5602 cds_ssr_protect(__func__);
5603 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
5604 data, data_len);
5605 cds_ssr_unprotect(__func__);
5606
5607 return ret;
5608}
Peng Xu8fdaa492016-06-22 10:20:47 -07005609
5610/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05305611 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
5612 * @wiphy: Pointer to wireless phy
5613 * @wdev: Pointer to wireless device
5614 * @data: Pointer to data
5615 * @data_len: Data length
5616 *
5617 * Processes the conditional channel switch request and invokes the helper
5618 * APIs to process the channel switch request.
5619 *
5620 * Return: 0 on success, negative errno on failure
5621 */
5622static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
5623 struct wireless_dev *wdev,
5624 const void *data,
5625 int data_len)
5626{
5627 int ret;
5628 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5629 struct net_device *dev = wdev->netdev;
5630 hdd_adapter_t *adapter;
5631 struct nlattr
5632 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
5633 uint32_t freq_len, i;
5634 uint32_t *freq;
5635 uint8_t chans[QDF_MAX_NUM_CHAN];
5636
5637 ENTER_DEV(dev);
5638
5639 ret = wlan_hdd_validate_context(hdd_ctx);
5640 if (ret)
5641 return ret;
5642
5643 if (!hdd_ctx->config->enableDFSMasterCap) {
5644 hdd_err("DFS master capability is not present in the driver");
5645 return -EINVAL;
5646 }
5647
5648 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5649 hdd_err("Command not allowed in FTM mode");
5650 return -EPERM;
5651 }
5652
5653 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5654 if (adapter->device_mode != QDF_SAP_MODE) {
5655 hdd_err("Invalid device mode %d", adapter->device_mode);
5656 return -EINVAL;
5657 }
5658
5659 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
5660 data, data_len, NULL)) {
5661 hdd_err("Invalid ATTR");
5662 return -EINVAL;
5663 }
5664
5665 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
5666 hdd_err("Frequency list is missing");
5667 return -EINVAL;
5668 }
5669
5670 freq_len = nla_len(
5671 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
5672 sizeof(uint32_t);
5673
5674 if (freq_len > QDF_MAX_NUM_CHAN) {
5675 hdd_err("insufficient space to hold channels");
5676 return -ENOMEM;
5677 }
5678
5679 hdd_debug("freq_len=%d", freq_len);
5680
5681 freq = nla_data(
5682 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
5683
5684
5685 for (i = 0; i < freq_len; i++) {
5686 if (freq[i] == 0)
5687 chans[i] = 0;
5688 else
5689 chans[i] = ieee80211_frequency_to_channel(freq[i]);
5690
5691 hdd_debug("freq[%d]=%d", i, freq[i]);
5692 }
5693
5694 /*
5695 * The input frequency list from user space is designed to be a
5696 * priority based frequency list. This is only to accommodate any
5697 * future request. But, current requirement is only to perform CAC
5698 * on a single channel. So, the first entry from the list is picked.
5699 *
5700 * If channel is zero, any channel in the available outdoor regulatory
5701 * domain will be selected.
5702 */
5703 ret = wlan_hdd_request_pre_cac(chans[0]);
5704 if (ret) {
5705 hdd_err("pre cac request failed with reason:%d", ret);
5706 return ret;
5707 }
5708
5709 return 0;
5710}
5711
5712/**
Peng Xu8fdaa492016-06-22 10:20:47 -07005713 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
5714 * @wiphy: Pointer to wireless phy
5715 * @wdev: Pointer to wireless device
5716 * @data: Pointer to data
5717 * @data_len: Data length
5718 *
5719 * This function is to process the p2p listen offload start vendor
5720 * command. It parses the input parameters and invoke WMA API to
5721 * send the command to firmware.
5722 *
5723 * Return: 0 on success, negative errno on failure
5724 */
5725static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
5726 struct wireless_dev *wdev,
5727 const void *data,
5728 int data_len)
5729{
5730 int ret;
5731 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5732 struct net_device *dev = wdev->netdev;
5733 hdd_adapter_t *adapter;
5734 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
5735 struct sir_p2p_lo_start params;
5736 QDF_STATUS status;
5737
5738 ENTER_DEV(dev);
5739
5740 ret = wlan_hdd_validate_context(hdd_ctx);
5741 if (ret)
5742 return ret;
5743
5744 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5745 hdd_err("Command not allowed in FTM mode");
5746 return -EPERM;
5747 }
5748
5749 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5750 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
5751 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
5752 (adapter->device_mode != QDF_P2P_GO_MODE)) {
5753 hdd_err("Invalid device mode %d", adapter->device_mode);
5754 return -EINVAL;
5755 }
5756
5757 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
5758 data, data_len, NULL)) {
5759 hdd_err("Invalid ATTR");
5760 return -EINVAL;
5761 }
5762
5763 memset(&params, 0, sizeof(params));
5764
5765 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
5766 params.ctl_flags = 1; /* set to default value */
5767 else
5768 params.ctl_flags = nla_get_u32(tb
5769 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
5770
5771 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
5772 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
5773 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
5774 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
5775 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
5776 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
5777 hdd_err("Attribute parsing failed");
5778 return -EINVAL;
5779 }
5780
5781 params.vdev_id = adapter->sessionId;
5782 params.freq = nla_get_u32(tb
5783 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
5784 if ((params.freq != 2412) && (params.freq != 2437) &&
5785 (params.freq != 2462)) {
5786 hdd_err("Invalid listening channel: %d", params.freq);
5787 return -EINVAL;
5788 }
5789
5790 params.period = nla_get_u32(tb
5791 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
5792 if (!((params.period > 0) && (params.period < UINT_MAX))) {
5793 hdd_err("Invalid period: %d", params.period);
5794 return -EINVAL;
5795 }
5796
5797 params.interval = nla_get_u32(tb
5798 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
5799 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
5800 hdd_err("Invalid interval: %d", params.interval);
5801 return -EINVAL;
5802 }
5803
5804 params.count = nla_get_u32(tb
5805 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
5806 if (!((params.count > 0) && (params.count < UINT_MAX))) {
5807 hdd_err("Invalid count: %d", params.count);
5808 return -EINVAL;
5809 }
5810
5811 params.device_types = nla_data(tb
5812 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
5813 if (params.device_types == NULL) {
5814 hdd_err("Invalid device types");
5815 return -EINVAL;
5816 }
5817
5818 params.dev_types_len = nla_len(tb
5819 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
5820 if (params.dev_types_len < 8) {
5821 hdd_err("Invalid device type length: %d", params.dev_types_len);
5822 return -EINVAL;
5823 }
5824
5825 params.probe_resp_tmplt = nla_data(tb
5826 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
5827 if (params.probe_resp_tmplt == NULL) {
5828 hdd_err("Invalid probe response template");
5829 return -EINVAL;
5830 }
5831
5832 params.probe_resp_len = nla_len(tb
5833 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
5834 if (params.probe_resp_len == 0) {
5835 hdd_err("Invalid probe resp template length: %d",
5836 params.probe_resp_len);
5837 return -EINVAL;
5838 }
5839
5840 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
5841 params.freq, params.period, params.interval, params.count);
5842
5843 status = wma_p2p_lo_start(&params);
5844
5845 if (!QDF_IS_STATUS_SUCCESS(status)) {
5846 hdd_err("P2P LO start failed");
5847 return -EINVAL;
5848 }
5849
5850 return 0;
5851}
5852
5853
5854/**
5855 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
5856 * @wiphy: Pointer to wireless phy
5857 * @wdev: Pointer to wireless device
5858 * @data: Pointer to data
5859 * @data_len: Data length
5860 *
5861 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
5862 * to process p2p listen offload start vendor command.
5863 *
5864 * Return: 0 on success, negative errno on failure
5865 */
5866static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
5867 struct wireless_dev *wdev,
5868 const void *data,
5869 int data_len)
5870{
5871 int ret = 0;
5872
5873 cds_ssr_protect(__func__);
5874 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
5875 data, data_len);
5876 cds_ssr_unprotect(__func__);
5877
5878 return ret;
5879}
5880
5881/**
5882 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
5883 * @wiphy: Pointer to wireless phy
5884 * @wdev: Pointer to wireless device
5885 * @data: Pointer to data
5886 * @data_len: Data length
5887 *
5888 * This function is to process the p2p listen offload stop vendor
5889 * command. It invokes WMA API to send command to firmware.
5890 *
5891 * Return: 0 on success, negative errno on failure
5892 */
5893static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
5894 struct wireless_dev *wdev,
5895 const void *data,
5896 int data_len)
5897{
5898 QDF_STATUS status;
5899 hdd_adapter_t *adapter;
5900 struct net_device *dev = wdev->netdev;
5901
5902 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5903 hdd_err("Command not allowed in FTM mode");
5904 return -EPERM;
5905 }
5906
5907 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5908 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
5909 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
5910 (adapter->device_mode != QDF_P2P_GO_MODE)) {
5911 hdd_err("Invalid device mode");
5912 return -EINVAL;
5913 }
5914
5915 status = wma_p2p_lo_stop(adapter->sessionId);
5916
5917 if (!QDF_IS_STATUS_SUCCESS(status)) {
5918 hdd_err("P2P LO stop failed");
5919 return -EINVAL;
5920 }
5921
5922 return 0;
5923}
5924
5925/**
5926 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
5927 * @wiphy: Pointer to wireless phy
5928 * @wdev: Pointer to wireless device
5929 * @data: Pointer to data
5930 * @data_len: Data length
5931 *
5932 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
5933 * to process p2p listen offload stop vendor command.
5934 *
5935 * Return: 0 on success, negative errno on failure
5936 */
5937static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
5938 struct wireless_dev *wdev,
5939 const void *data,
5940 int data_len)
5941{
5942 int ret = 0;
5943
5944 cds_ssr_protect(__func__);
5945 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
5946 data, data_len);
5947 cds_ssr_unprotect(__func__);
5948
5949 return ret;
5950}
5951
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05305952/**
5953 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP 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 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
5960 * to process the conditional 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
5971 cds_ssr_protect(__func__);
5972 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
5973 data, data_len);
5974 cds_ssr_unprotect(__func__);
5975
5976 return ret;
5977}
5978
Arun Khandavalli2476ef52016-04-26 20:19:43 +05305979/*
5980 * define short names for the global vendor params
5981 * used by __wlan_hdd_cfg80211_bpf_offload()
5982 */
5983#define BPF_INVALID \
5984 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
5985#define BPF_SET_RESET \
5986 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
5987#define BPF_VERSION \
5988 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
5989#define BPF_FILTER_ID \
5990 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
5991#define BPF_PACKET_SIZE \
5992 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
5993#define BPF_CURRENT_OFFSET \
5994 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
5995#define BPF_PROGRAM \
5996 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
5997#define BPF_MAX \
5998 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07005999
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306000static const struct nla_policy
6001wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6002 [BPF_SET_RESET] = {.type = NLA_U32},
6003 [BPF_VERSION] = {.type = NLA_U32},
6004 [BPF_FILTER_ID] = {.type = NLA_U32},
6005 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6006 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6007 [BPF_PROGRAM] = {.type = NLA_U8},
6008};
6009
6010/**
6011 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
6012 * @hdd_context: hdd_context
6013 * @bpf_get_offload: struct for get offload
6014 *
6015 * This function receives the response/data from the lower layer and
6016 * checks to see if the thread is still waiting then post the results to
6017 * upper layer, if the request has timed out then ignore.
6018 *
6019 * Return: None
6020 */
6021void hdd_get_bpf_offload_cb(void *hdd_context,
6022 struct sir_bpf_get_offload *data)
6023{
6024 hdd_context_t *hdd_ctx = hdd_context;
6025 struct hdd_bpf_context *context;
6026
6027 ENTER();
6028
6029 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006030 hdd_err("HDD context is invalid or data(%p) is null",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306031 data);
6032 return;
6033 }
6034
6035 spin_lock(&hdd_context_lock);
6036
6037 context = &bpf_context;
6038 /* The caller presumably timed out so there is nothing we can do */
6039 if (context->magic != BPF_CONTEXT_MAGIC) {
6040 spin_unlock(&hdd_context_lock);
6041 return;
6042 }
6043
6044 /* context is valid so caller is still waiting */
6045 /* paranoia: invalidate the magic */
6046 context->magic = 0;
6047
6048 context->capability_response = *data;
6049 complete(&context->completion);
6050
6051 spin_unlock(&hdd_context_lock);
6052
6053 return;
6054}
6055
6056/**
6057 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6058 * @hdd_context: hdd_context
6059 * @bpf_get_offload: struct for get offload
6060 *
6061 * Return: 0 on success, error number otherwise.
6062 */
6063static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6064 struct sir_bpf_get_offload *bpf_get_offload)
6065{
6066 struct sk_buff *skb;
6067 uint32_t nl_buf_len;
6068
6069 ENTER();
6070
6071 nl_buf_len = NLMSG_HDRLEN;
6072 nl_buf_len +=
6073 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6074 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6075
6076 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6077 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006078 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306079 return -ENOMEM;
6080 }
6081
Jeff Johnson77848112016-06-29 14:52:06 -07006082 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306083 bpf_get_offload->bpf_version,
6084 bpf_get_offload->max_bytes_for_bpf_inst);
6085
6086 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6087 bpf_get_offload->max_bytes_for_bpf_inst) ||
6088 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006089 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306090 goto nla_put_failure;
6091 }
6092
6093 cfg80211_vendor_cmd_reply(skb);
6094 EXIT();
6095 return 0;
6096
6097nla_put_failure:
6098 kfree_skb(skb);
6099 return -EINVAL;
6100}
6101
6102/**
6103 * hdd_get_bpf_offload - Get BPF offload Capabilities
6104 * @hdd_ctx: Hdd context
6105 *
6106 * Return: 0 on success, errno on failure
6107 */
6108static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6109{
6110 unsigned long rc;
6111 struct hdd_bpf_context *context;
6112 QDF_STATUS status;
6113 int ret;
6114
6115 ENTER();
6116
6117 spin_lock(&hdd_context_lock);
6118 context = &bpf_context;
6119 context->magic = BPF_CONTEXT_MAGIC;
6120 INIT_COMPLETION(context->completion);
6121 spin_unlock(&hdd_context_lock);
6122
6123 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal);
6124 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006125 hdd_err("Unable to retrieve BPF caps");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306126 return -EINVAL;
6127 }
6128 /* request was sent -- wait for the response */
6129 rc = wait_for_completion_timeout(&context->completion,
6130 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
6131 if (!rc) {
Jeff Johnson77848112016-06-29 14:52:06 -07006132 hdd_err("Target response timed out");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306133 spin_lock(&hdd_context_lock);
6134 context->magic = 0;
6135 spin_unlock(&hdd_context_lock);
6136
6137 return -ETIMEDOUT;
6138 }
6139 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
6140 &bpf_context.capability_response);
6141 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006142 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306143
6144 EXIT();
6145 return ret;
6146}
6147
6148/**
6149 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
6150 * @hdd_ctx: Hdd context
6151 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306152 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306153 *
6154 * Return: 0 on success; errno on failure
6155 */
6156static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
6157 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306158 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306159{
6160 struct sir_bpf_set_offload *bpf_set_offload;
6161 QDF_STATUS status;
6162 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05306163 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306164
6165 ENTER();
6166
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306167 if (adapter->device_mode == QDF_STA_MODE ||
6168 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
6169 if (!hdd_conn_is_connected(
6170 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
6171 hdd_err("Not in Connected state!");
6172 return -ENOTSUPP;
6173 }
6174 }
6175
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306176 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
6177 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07006178 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306179 return -ENOMEM;
6180 }
6181 qdf_mem_zero(bpf_set_offload, sizeof(*bpf_set_offload));
6182
6183 /* Parse and fetch bpf packet size */
6184 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006185 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306186 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306187 goto fail;
6188 }
6189 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
6190
6191 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07006192 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306193 goto post_sme;
6194 }
6195
6196 /* Parse and fetch bpf program */
6197 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006198 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306199 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306200 goto fail;
6201 }
6202
6203 prog_len = nla_len(tb[BPF_PROGRAM]);
6204 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05306205
6206 if (bpf_set_offload->program == NULL) {
6207 hdd_err("qdf_mem_malloc failed for bpf offload program");
6208 ret = -ENOMEM;
6209 goto fail;
6210 }
6211
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306212 bpf_set_offload->current_length = prog_len;
6213 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306214 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306215
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05306216 hdd_info("BPF set instructions");
6217 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
6218 bpf_set_offload->program, prog_len);
6219
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306220 /* Parse and fetch filter Id */
6221 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006222 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306223 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306224 goto fail;
6225 }
6226 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
6227
6228 /* Parse and fetch current offset */
6229 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006230 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306231 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306232 goto fail;
6233 }
6234 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
6235
6236post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07006237 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 +05306238 bpf_set_offload->session_id,
6239 bpf_set_offload->version,
6240 bpf_set_offload->filter_id,
6241 bpf_set_offload->total_length,
6242 bpf_set_offload->current_length,
6243 bpf_set_offload->current_offset);
6244
6245 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
6246 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006247 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05306248 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306249 goto fail;
6250 }
6251 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306252
6253fail:
6254 if (bpf_set_offload->current_length)
6255 qdf_mem_free(bpf_set_offload->program);
6256 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05306257 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306258}
6259
6260/**
6261 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
6262 * @wiphy: wiphy structure pointer
6263 * @wdev: Wireless device structure pointer
6264 * @data: Pointer to the data received
6265 * @data_len: Length of @data
6266 *
6267 * Return: 0 on success; errno on failure
6268 */
6269static int
6270__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6271 struct wireless_dev *wdev,
6272 const void *data, int data_len)
6273{
6274 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6275 struct net_device *dev = wdev->netdev;
6276 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6277 struct nlattr *tb[BPF_MAX + 1];
6278 int ret_val, packet_filter_subcmd;
6279
6280 ENTER();
6281
6282 ret_val = wlan_hdd_validate_context(hdd_ctx);
6283 if (ret_val)
6284 return ret_val;
6285
6286 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07006287 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306288 return -EINVAL;
6289 }
6290
6291 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07006292 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306293 return -ENOTSUPP;
6294 }
6295
6296 if (nla_parse(tb, BPF_MAX, data, data_len,
6297 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006298 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306299 return -EINVAL;
6300 }
6301
6302 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006303 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306304 return -EINVAL;
6305 }
6306
6307 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
6308
6309 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
6310 return hdd_get_bpf_offload(hdd_ctx);
6311 else
6312 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306313 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306314}
6315
6316/**
6317 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
6318 * @wiphy: wiphy structure pointer
6319 * @wdev: Wireless device structure pointer
6320 * @data: Pointer to the data received
6321 * @data_len: Length of @data
6322 *
6323 * Return: 0 on success; errno on failure
6324 */
6325
6326static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6327 struct wireless_dev *wdev,
6328 const void *data, int data_len)
6329{
6330 int ret;
6331
6332 cds_ssr_protect(__func__);
6333 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
6334 cds_ssr_unprotect(__func__);
6335
6336 return ret;
6337}
6338
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306339/**
6340 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
6341 * @pre_cac_adapter: AP adapter used for pre cac
6342 * @status: Status (true or false)
6343 * @handle: Global handle
6344 *
6345 * Sets the status of pre cac i.e., whether the pre cac is active or not
6346 *
6347 * Return: Zero on success, non-zero on failure
6348 */
6349static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
6350 bool status, tHalHandle handle)
6351{
6352 QDF_STATUS ret;
6353
6354 ret = wlan_sap_set_pre_cac_status(
6355 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
6356 if (QDF_IS_STATUS_ERROR(ret))
6357 return -EINVAL;
6358
6359 return 0;
6360}
6361
6362/**
6363 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
6364 * @ap_adapter: AP adapter
6365 * @chan_before_pre_cac: Channel
6366 *
6367 * Saves the channel which the AP was beaconing on before moving to the pre
6368 * cac channel. If radar is detected on the pre cac channel, this saved
6369 * channel will be used for AP operations.
6370 *
6371 * Return: Zero on success, non-zero on failure
6372 */
6373static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
6374 uint8_t chan_before_pre_cac)
6375{
6376 QDF_STATUS ret;
6377
6378 ret = wlan_sap_set_chan_before_pre_cac(
6379 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
6380 if (QDF_IS_STATUS_ERROR(ret))
6381 return -EINVAL;
6382
6383 return 0;
6384}
6385
6386/**
6387 * wlan_hdd_sap_get_nol() - Get SAPs NOL
6388 * @ap_adapter: AP adapter
6389 * @nol: Non-occupancy list
6390 * @nol_len: Length of NOL
6391 *
6392 * Get the NOL for SAP
6393 *
6394 * Return: Zero on success, non-zero on failure
6395 */
6396static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
6397 uint32_t *nol_len)
6398{
6399 QDF_STATUS ret;
6400
6401 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
6402 nol, nol_len);
6403 if (QDF_IS_STATUS_ERROR(ret))
6404 return -EINVAL;
6405
6406 return 0;
6407}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306408
6409/**
6410 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
6411 * @hdd_ctx: HDD context
6412 * @ap_adapter: AP adapter
6413 * @channel: Channel requested by userspace
6414 * @pre_cac_chan: Pointer to the pre CAC channel
6415 *
6416 * Validates the channel provided by userspace. If user provided channel 0,
6417 * a valid outdoor channel must be selected from the regulatory channel.
6418 *
6419 * Return: Zero on success and non zero value on error
6420 */
6421int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
6422 hdd_adapter_t *ap_adapter,
6423 uint8_t channel,
6424 uint8_t *pre_cac_chan)
6425{
6426 uint32_t i, j;
6427 QDF_STATUS status;
6428 int ret;
6429 uint8_t nol[QDF_MAX_NUM_CHAN];
6430 uint32_t nol_len = 0, weight_len = 0;
6431 bool found;
6432 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6433 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
6434 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
6435
6436 if (0 == channel) {
6437 /* Channel is not obtained from PCL because PCL may not have
6438 * the entire channel list. For example: if SAP is up on
6439 * channel 6 and PCL is queried for the next SAP interface,
6440 * if SCC is preferred, the PCL will contain only the channel
6441 * 6. But, we are in need of a DFS channel. So, going with the
6442 * first channel from the valid channel list.
6443 */
6444 status = cds_get_valid_chans(channel_list, &len);
6445 if (QDF_IS_STATUS_ERROR(status)) {
6446 hdd_err("Failed to get channel list");
6447 return -EINVAL;
6448 }
6449 cds_update_with_safe_channel_list(channel_list, &len,
6450 pcl_weights, weight_len);
6451 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
6452 for (i = 0; i < len; i++) {
6453 found = false;
6454 for (j = 0; j < nol_len; j++) {
6455 if (channel_list[i] == nol[j]) {
6456 found = true;
6457 break;
6458 }
6459 }
6460 if (found)
6461 continue;
6462 if (CDS_IS_DFS_CH(channel_list[i])) {
6463 *pre_cac_chan = channel_list[i];
6464 break;
6465 }
6466 }
6467 if (*pre_cac_chan == 0) {
6468 hdd_err("unable to find outdoor channel");
6469 return -EINVAL;
6470 }
6471 } else {
6472 /* Only when driver selects a channel, check is done for
6473 * unnsafe and NOL channels. When user provides a fixed channel
6474 * the user is expected to take care of this.
6475 */
6476 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
6477 !CDS_IS_DFS_CH(channel)) {
6478 hdd_err("Invalid channel for pre cac:%d", channel);
6479 return -EINVAL;
6480 } else {
6481 *pre_cac_chan = channel;
6482 }
6483 }
6484 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
6485 return 0;
6486}
6487
6488/**
6489 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
6490 * @channel: Channel option provided by userspace
6491 *
6492 * Sets the driver to the required hardware mode and start an adapater for
6493 * pre CAC which will mimic an AP.
6494 *
6495 * Return: Zero on success, non-zero value on error
6496 */
6497int wlan_hdd_request_pre_cac(uint8_t channel)
6498{
6499 uint8_t pre_cac_chan = 0;
6500 hdd_context_t *hdd_ctx;
6501 int ret;
6502 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
6503 hdd_ap_ctx_t *hdd_ap_ctx;
6504 QDF_STATUS status;
6505 struct wiphy *wiphy;
6506 struct net_device *dev;
6507 struct cfg80211_chan_def chandef;
6508 enum nl80211_channel_type channel_type;
6509 uint32_t freq;
6510 struct ieee80211_channel *chan;
6511 tHalHandle handle;
6512 bool val;
6513
6514 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
6515 if (0 != wlan_hdd_validate_context(hdd_ctx))
6516 return -EINVAL;
6517
6518 if (cds_get_connection_count() > 1) {
6519 hdd_err("pre cac not allowed in concurrency");
6520 return -EINVAL;
6521 }
6522
6523 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
6524 if (!ap_adapter) {
6525 hdd_err("unable to get SAP adapter");
6526 return -EINVAL;
6527 }
6528
6529 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
6530 if (!handle) {
6531 hdd_err("Invalid handle");
6532 return -EINVAL;
6533 }
6534
6535 val = wlan_sap_is_pre_cac_active(handle);
6536 if (val) {
6537 hdd_err("pre cac is already in progress");
6538 return -EINVAL;
6539 }
6540
6541 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6542 if (!hdd_ap_ctx) {
6543 hdd_err("SAP context is NULL");
6544 return -EINVAL;
6545 }
6546
6547 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
6548 hdd_err("SAP is already on DFS channel:%d",
6549 hdd_ap_ctx->operatingChannel);
6550 return -EINVAL;
6551 }
6552
6553 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
6554 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
6555 hdd_ap_ctx->operatingChannel);
6556 return -EINVAL;
6557 }
6558
6559 hdd_info("channel:%d", channel);
6560
6561 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
6562 &pre_cac_chan);
6563 if (ret != 0)
6564 return ret;
6565
6566 /* Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
6567 * connection update should result in DBS mode
6568 */
6569 status = cds_update_and_wait_for_connection_update(
6570 ap_adapter->sessionId,
6571 pre_cac_chan,
6572 SIR_UPDATE_REASON_PRE_CAC);
6573 if (QDF_IS_STATUS_ERROR(status)) {
6574 hdd_err("error in moving to DBS mode");
6575 return -EINVAL;
6576 }
6577
6578 hdd_debug("starting pre cac SAP adapter");
6579
6580 /* Starting a SAP adapter:
6581 * Instead of opening an adapter, we could just do a SME open session
6582 * for AP type. But, start BSS would still need an adapter.
6583 * So, this option is not taken.
6584 *
6585 * hdd open adapter is going to register this precac interface with
6586 * user space. This interface though exposed to user space will be in
6587 * DOWN state. Consideration was done to avoid this registration to the
6588 * user space. But, as part of SAP operations multiple events are sent
6589 * to user space. Some of these events received from unregistered
6590 * interface was causing crashes. So, retaining the registration.
6591 *
6592 * So, this interface would remain registered and will remain in DOWN
6593 * state for the CAC duration. We will add notes in the feature
6594 * announcement to not use this temporary interface for any activity
6595 * from user space.
6596 */
6597 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
6598 wlan_hdd_get_intf_addr(hdd_ctx),
6599 NET_NAME_UNKNOWN, true);
6600 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306601 hdd_err("error opening the pre cac adapter");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306602 return -EINVAL;
6603 }
6604
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306605 /*
6606 * This interface is internally created by the driver. So, no interface
6607 * up comes for this interface from user space and hence starting
6608 * the adapter internally.
6609 */
6610 if (hdd_start_adapter(pre_cac_adapter)) {
6611 hdd_err("error starting the pre cac adapter");
6612 goto close_pre_cac_adapter;
6613 }
6614
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306615 hdd_debug("preparing for start ap/bss on the pre cac adapter");
6616
6617 wiphy = hdd_ctx->wiphy;
6618 dev = pre_cac_adapter->dev;
6619
6620 /* Since this is only a dummy interface lets us use the IEs from the
6621 * other active SAP interface. In regular scenarios, these IEs would
6622 * come from the user space entity
6623 */
6624 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
6625 sizeof(*ap_adapter->sessionCtx.ap.beacon));
6626 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
6627 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306628 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306629 }
6630 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
6631 ap_adapter->sessionCtx.ap.beacon,
6632 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
6633 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
6634 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
6635 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
6636 ap_adapter->sessionCtx.ap.sapConfig.authType;
6637
6638 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
6639 * to operate on the same bandwidth as that of the 2.4GHz operations.
6640 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
6641 */
6642 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
6643 case CH_WIDTH_20MHZ:
6644 channel_type = NL80211_CHAN_HT20;
6645 break;
6646 case CH_WIDTH_40MHZ:
6647 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
6648 ap_adapter->sessionCtx.ap.sapConfig.channel)
6649 channel_type = NL80211_CHAN_HT40PLUS;
6650 else
6651 channel_type = NL80211_CHAN_HT40MINUS;
6652 break;
6653 default:
6654 channel_type = NL80211_CHAN_NO_HT;
6655 break;
6656 }
6657
6658 freq = cds_chan_to_freq(pre_cac_chan);
6659 chan = __ieee80211_get_channel(wiphy, freq);
6660 if (!chan) {
6661 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306662 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306663 }
6664
6665 cfg80211_chandef_create(&chandef, chan, channel_type);
6666
6667 hdd_debug("orig width:%d channel_type:%d freq:%d",
6668 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
6669 channel_type, freq);
6670
6671 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
6672 if (0 != ret) {
6673 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306674 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306675 }
6676
6677 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
6678 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
6679 eHIDDEN_SSID_NOT_IN_USE, false);
6680 if (QDF_IS_STATUS_ERROR(status)) {
6681 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306682 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306683 }
6684
6685 /*
6686 * The pre cac status is set here. But, it would not be reset explicitly
6687 * anywhere, since after the pre cac success/failure, the pre cac
6688 * adapter itself would be removed.
6689 */
6690 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
6691 if (0 != ret) {
6692 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306693 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306694 }
6695
6696 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
6697 hdd_ap_ctx->operatingChannel);
6698 if (0 != ret) {
6699 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306700 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306701 }
6702
6703 ap_adapter->pre_cac_chan = pre_cac_chan;
6704
6705 return 0;
6706
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306707stop_close_pre_cac_adapter:
6708 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306709 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
6710 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306711close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306712 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
6713 return -EINVAL;
6714}
6715
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306716/**
6717 * hdd_init_bpf_completion() - Initialize the completion event for bpf
6718 *
6719 * Return: None
6720 */
6721void hdd_init_bpf_completion(void)
6722{
6723 init_completion(&bpf_context.completion);
6724}
6725
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05306726static const struct nla_policy
6727wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
6728 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
6729};
6730
6731/**
6732 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
6733 * SAP is on unsafe channel.
6734 * @wiphy: wiphy structure pointer
6735 * @wdev: Wireless device structure pointer
6736 * @data: Pointer to the data received
6737 * @data_len: Length of @data
6738 *
6739 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
6740 * driver.
6741 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
6742 * will initiate restart of sap.
6743 *
6744 * Return: 0 on success; errno on failure
6745 */
6746static int
6747__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
6748 struct wireless_dev *wdev,
6749 const void *data, int data_len)
6750{
6751 struct net_device *ndev = wdev->netdev;
6752 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
6753 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6754 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
6755 uint8_t config_channel = 0;
6756 hdd_ap_ctx_t *ap_ctx;
6757 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05306758 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05306759
6760 ENTER();
6761
6762 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07006763 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05306764 return -EINVAL;
6765 }
6766
6767 ret = wlan_hdd_validate_context(hdd_ctx);
6768 if (0 != ret)
6769 return -EINVAL;
6770
6771 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
6772 data, data_len,
6773 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006774 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05306775 return -EINVAL;
6776 }
6777
6778 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
6779 if (!test_bit(SOFTAP_BSS_STARTED,
6780 &hostapd_adapter->event_flags)) {
6781 hdd_err("SAP is not started yet. Restart sap will be invalid");
6782 return -EINVAL;
6783 }
6784
6785 config_channel =
6786 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
6787
6788 if (!((IS_24G_CH(config_channel)) ||
6789 (IS_5G_CH(config_channel)))) {
6790 hdd_err("Channel %d is not valid to restart SAP",
6791 config_channel);
6792 return -ENOTSUPP;
6793 }
6794
6795 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
6796 ap_ctx->sapConfig.channel = config_channel;
6797 ap_ctx->sapConfig.ch_params.ch_width =
6798 ap_ctx->sapConfig.ch_width_orig;
6799
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07006800 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05306801 ap_ctx->sapConfig.sec_ch,
6802 &ap_ctx->sapConfig.ch_params);
6803
6804 cds_restart_sap(hostapd_adapter);
6805 }
6806
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05306807 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
6808 uint32_t freq_len, i;
6809 uint32_t *freq;
6810 uint8_t chans[QDF_MAX_NUM_CHAN];
6811
6812 hdd_debug("setting mandatory freq/chan list");
6813
6814 freq_len = nla_len(
6815 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
6816 sizeof(uint32_t);
6817
6818 if (freq_len > QDF_MAX_NUM_CHAN) {
6819 hdd_err("insufficient space to hold channels");
6820 return -ENOMEM;
6821 }
6822
6823 freq = nla_data(
6824 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
6825
6826 hdd_debug("freq_len=%d", freq_len);
6827
6828 for (i = 0; i < freq_len; i++) {
6829 chans[i] = ieee80211_frequency_to_channel(freq[i]);
6830 hdd_debug("freq[%d]=%d", i, freq[i]);
6831 }
6832
6833 status = cds_set_sap_mandatory_channels(chans, freq_len);
6834 if (QDF_IS_STATUS_ERROR(status))
6835 return -EINVAL;
6836 }
6837
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05306838 return 0;
6839}
6840
6841/**
6842 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
6843 * @wiphy: wiphy structure pointer
6844 * @wdev: Wireless device structure pointer
6845 * @data: Pointer to the data received
6846 * @data_len: Length of @data
6847 *
6848 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
6849 * driver.
6850 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
6851 * will initiate restart of sap.
6852 *
6853 * Return: 0 on success; errno on failure
6854 */
6855static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
6856 struct wireless_dev *wdev,
6857 const void *data, int data_len)
6858{
6859 int ret;
6860
6861 cds_ssr_protect(__func__);
6862 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
6863 wdev, data, data_len);
6864 cds_ssr_unprotect(__func__);
6865
6866 return ret;
6867}
6868
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306869#undef BPF_INVALID
6870#undef BPF_SET_RESET
6871#undef BPF_VERSION
6872#undef BPF_ID
6873#undef BPF_PACKET_SIZE
6874#undef BPF_CURRENT_OFFSET
6875#undef BPF_PROGRAM
6876#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05306877
6878/**
6879 * define short names for the global vendor params
6880 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
6881 */
6882#define PARAM_TOTAL_CMD_EVENT_WAKE \
6883 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
6884#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
6885 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
6886#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
6887 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
6888#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
6889 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
6890#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
6891 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
6892#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
6893 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
6894#define PARAM_TOTAL_RX_DATA_WAKE \
6895 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
6896#define PARAM_RX_UNICAST_CNT \
6897 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
6898#define PARAM_RX_MULTICAST_CNT \
6899 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
6900#define PARAM_RX_BROADCAST_CNT \
6901 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
6902#define PARAM_ICMP_PKT \
6903 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
6904#define PARAM_ICMP6_PKT \
6905 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
6906#define PARAM_ICMP6_RA \
6907 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
6908#define PARAM_ICMP6_NA \
6909 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
6910#define PARAM_ICMP6_NS \
6911 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
6912#define PARAM_ICMP4_RX_MULTICAST_CNT \
6913 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
6914#define PARAM_ICMP6_RX_MULTICAST_CNT \
6915 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
6916#define PARAM_OTHER_RX_MULTICAST_CNT \
6917 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
6918
6919
6920/**
6921 * hdd_send_wakelock_stats() - API to send wakelock stats
6922 * @ctx: context to be passed to callback
6923 * @data: data passed to callback
6924 *
6925 * This function is used to send wake lock stats to HAL layer
6926 *
6927 * Return: 0 on success, error number otherwise.
6928 */
6929static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
6930 const struct sir_wake_lock_stats *data)
6931{
6932 struct sk_buff *skb;
6933 uint32_t nl_buf_len;
6934 uint32_t total_rx_data_wake, rx_multicast_cnt;
6935 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05306936 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05306937
6938 ENTER();
6939
6940 nl_buf_len = NLMSG_HDRLEN;
6941 nl_buf_len +=
6942 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
6943 (NLMSG_HDRLEN + sizeof(uint32_t));
6944
6945 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6946
6947 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07006948 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05306949 return -ENOMEM;
6950 }
6951
Jeff Johnson64943bd2016-08-23 13:14:06 -07006952 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05306953 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07006954 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05306955 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07006956 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05306957 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07006958 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05306959 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07006960 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05306961 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07006962 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05306963 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07006964 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05306965 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07006966 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
6967 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05306968 data->wow_icmpv6_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05306969
6970 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05306971 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05306972
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05306973 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05306974 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05306975
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05306976 rx_multicast_cnt =
6977 data->wow_ipv4_mcast_wake_up_count +
6978 ipv6_rx_multicast_addr_cnt;
6979
6980 total_rx_data_wake =
6981 data->wow_ucast_wake_up_count +
6982 data->wow_bcast_wake_up_count +
6983 rx_multicast_cnt;
6984
6985 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
6986 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
6987 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
6988 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
6989 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
6990 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
6991 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
6992 total_rx_data_wake) ||
6993 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
6994 data->wow_ucast_wake_up_count) ||
6995 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
6996 rx_multicast_cnt) ||
6997 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
6998 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05306999 nla_put_u32(skb, PARAM_ICMP_PKT,
7000 data->wow_icmpv4_count) ||
7001 nla_put_u32(skb, PARAM_ICMP6_PKT,
7002 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307003 nla_put_u32(skb, PARAM_ICMP6_RA,
7004 data->wow_ipv6_mcast_ra_stats) ||
7005 nla_put_u32(skb, PARAM_ICMP6_NA,
7006 data->wow_ipv6_mcast_na_stats) ||
7007 nla_put_u32(skb, PARAM_ICMP6_NS,
7008 data->wow_ipv6_mcast_ns_stats) ||
7009 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
7010 data->wow_ipv4_mcast_wake_up_count) ||
7011 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
7012 ipv6_rx_multicast_addr_cnt) ||
7013 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007014 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307015 goto nla_put_failure;
7016 }
7017
7018 cfg80211_vendor_cmd_reply(skb);
7019
7020 EXIT();
7021 return 0;
7022
7023nla_put_failure:
7024 kfree_skb(skb);
7025 return -EINVAL;
7026}
7027
7028/**
7029 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7030 * @wiphy: wiphy pointer
7031 * @wdev: pointer to struct wireless_dev
7032 * @data: pointer to incoming NL vendor data
7033 * @data_len: length of @data
7034 *
7035 * This function parses the incoming NL vendor command data attributes and
7036 * invokes the SME Api and blocks on a completion variable.
7037 * WMA copies required data and invokes callback
7038 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7039 *
7040 * Return: 0 on success; error number otherwise.
7041 */
7042static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7043 struct wireless_dev *wdev,
7044 const void *data,
7045 int data_len)
7046{
7047 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7048 int status, ret;
7049 struct sir_wake_lock_stats wake_lock_stats;
7050 QDF_STATUS qdf_status;
7051
7052 ENTER();
7053
7054 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007055 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307056 return -EINVAL;
7057 }
7058
7059 status = wlan_hdd_validate_context(hdd_ctx);
7060 if (0 != status)
7061 return -EINVAL;
7062
7063 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
7064 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007065 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307066 return -EINVAL;
7067 }
7068
7069 ret = hdd_send_wakelock_stats(hdd_ctx,
7070 &wake_lock_stats);
7071 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07007072 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307073
7074 EXIT();
7075 return ret;
7076}
7077
7078/**
7079 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7080 * @wiphy: wiphy pointer
7081 * @wdev: pointer to struct wireless_dev
7082 * @data: pointer to incoming NL vendor data
7083 * @data_len: length of @data
7084 *
7085 * This function parses the incoming NL vendor command data attributes and
7086 * invokes the SME Api and blocks on a completion variable.
7087 * WMA copies required data and invokes callback
7088 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7089 *
7090 * Return: 0 on success; error number otherwise.
7091 */
7092static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7093 struct wireless_dev *wdev,
7094 const void *data, int data_len)
7095{
7096 int ret;
7097
7098 cds_ssr_protect(__func__);
7099 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
7100 data_len);
7101 cds_ssr_protect(__func__);
7102
7103 return ret;
7104}
7105
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307106/**
7107 *__wlan_hdd_cfg80211_setband() - set band
7108 * @wiphy: Pointer to wireless phy
7109 * @wdev: Pointer to wireless device
7110 * @data: Pointer to data
7111 * @data_len: Length of @data
7112 *
7113 * Return: 0 on success, negative errno on failure
7114 */
7115static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7116 struct wireless_dev *wdev,
7117 const void *data, int data_len)
7118{
7119 struct net_device *dev = wdev->netdev;
7120 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7121 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7122 int ret;
7123 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
7124 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
7125
7126 ENTER();
7127
7128 ret = wlan_hdd_validate_context(hdd_ctx);
7129 if (ret)
7130 return ret;
7131
7132 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
7133 hdd_err(FL("Invalid ATTR"));
7134 return -EINVAL;
7135 }
7136
7137 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
7138 hdd_err(FL("attr SETBAND_VALUE failed"));
7139 return -EINVAL;
7140 }
7141
7142 ret = hdd_set_band(dev,
7143 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
7144
7145 EXIT();
7146 return ret;
7147}
7148
7149/**
7150 * wlan_hdd_cfg80211_setband() - Wrapper to setband
7151 * @wiphy: wiphy structure pointer
7152 * @wdev: Wireless device structure pointer
7153 * @data: Pointer to the data received
7154 * @data_len: Length of @data
7155 *
7156 * Return: 0 on success; errno on failure
7157 */
7158static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7159 struct wireless_dev *wdev,
7160 const void *data, int data_len)
7161{
7162 int ret;
7163
7164 cds_ssr_protect(__func__);
7165 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
7166 cds_ssr_unprotect(__func__);
7167
7168 return ret;
7169}
7170
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007171const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
7172 {
7173 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7174 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
7175 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7176 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7177 .doit = is_driver_dfs_capable
7178 },
7179
7180#ifdef WLAN_FEATURE_NAN
7181 {
7182 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7183 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
7184 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7185 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7186 .doit = wlan_hdd_cfg80211_nan_request
7187 },
7188#endif
7189
7190#ifdef WLAN_FEATURE_STATS_EXT
7191 {
7192 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7193 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
7194 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7195 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7196 .doit = wlan_hdd_cfg80211_stats_ext_request
7197 },
7198#endif
7199#ifdef FEATURE_WLAN_EXTSCAN
7200 {
7201 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7202 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
7203 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7204 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7205 .doit = wlan_hdd_cfg80211_extscan_start
7206 },
7207 {
7208 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7209 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
7210 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7211 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7212 .doit = wlan_hdd_cfg80211_extscan_stop
7213 },
7214 {
7215 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7216 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
7217 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
7218 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
7219 },
7220 {
7221 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7222 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
7223 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7224 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7225 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
7226 },
7227 {
7228 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7229 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
7230 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7231 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7232 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
7233 },
7234 {
7235 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7236 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
7237 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7238 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7239 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
7240 },
7241 {
7242 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7243 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
7244 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7245 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7246 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
7247 },
7248 {
7249 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7250 .info.subcmd =
7251 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
7252 .flags =
7253 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
7254 WIPHY_VENDOR_CMD_NEED_RUNNING,
7255 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
7256 },
7257 {
7258 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7259 .info.subcmd =
7260 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
7261 .flags =
7262 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
7263 WIPHY_VENDOR_CMD_NEED_RUNNING,
7264 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
7265 },
7266 {
7267 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7268 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
7269 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7270 WIPHY_VENDOR_CMD_NEED_NETDEV |
7271 WIPHY_VENDOR_CMD_NEED_RUNNING,
7272 .doit = wlan_hdd_cfg80211_set_epno_list
7273 },
7274#endif /* FEATURE_WLAN_EXTSCAN */
7275
7276#ifdef WLAN_FEATURE_LINK_LAYER_STATS
7277 {
7278 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7279 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
7280 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7281 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7282 .doit = wlan_hdd_cfg80211_ll_stats_clear
7283 },
7284
7285 {
7286 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7287 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
7288 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7289 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7290 .doit = wlan_hdd_cfg80211_ll_stats_set
7291 },
7292
7293 {
7294 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7295 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
7296 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7297 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7298 .doit = wlan_hdd_cfg80211_ll_stats_get
7299 },
7300#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
7301#ifdef FEATURE_WLAN_TDLS
7302 {
7303 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7304 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
7305 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7306 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7307 .doit = wlan_hdd_cfg80211_exttdls_enable
7308 },
7309 {
7310 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7311 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
7312 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7313 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7314 .doit = wlan_hdd_cfg80211_exttdls_disable
7315 },
7316 {
7317 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7318 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
7319 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
7320 .doit = wlan_hdd_cfg80211_exttdls_get_status
7321 },
7322#endif
7323 {
7324 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7325 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
7326 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
7327 .doit = wlan_hdd_cfg80211_get_supported_features
7328 },
7329 {
7330 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7331 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
7332 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
7333 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
7334 },
7335 {
7336 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7337 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
7338 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05307339 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007340 },
7341 {
7342 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7343 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
7344 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7345 WIPHY_VENDOR_CMD_NEED_NETDEV,
7346 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
7347 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07007348 {
7349 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7350 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
7351 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7352 WIPHY_VENDOR_CMD_NEED_NETDEV,
7353 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
7354 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007355 {
7356 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05307357 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
7358 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7359 WIPHY_VENDOR_CMD_NEED_NETDEV |
7360 WIPHY_VENDOR_CMD_NEED_RUNNING,
7361 .doit = hdd_cfg80211_get_station_cmd
7362 },
7363 {
7364 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007365 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
7366 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7367 WIPHY_VENDOR_CMD_NEED_NETDEV |
7368 WIPHY_VENDOR_CMD_NEED_RUNNING,
7369 .doit = wlan_hdd_cfg80211_do_acs
7370 },
7371
7372 {
7373 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7374 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
7375 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7376 WIPHY_VENDOR_CMD_NEED_NETDEV,
7377 .doit = wlan_hdd_cfg80211_get_features
7378 },
7379#ifdef WLAN_FEATURE_ROAM_OFFLOAD
7380 {
7381 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7382 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
7383 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7384 WIPHY_VENDOR_CMD_NEED_NETDEV |
7385 WIPHY_VENDOR_CMD_NEED_RUNNING,
7386 .doit = wlan_hdd_cfg80211_keymgmt_set_key
7387 },
7388#endif
7389#ifdef FEATURE_WLAN_EXTSCAN
7390 {
7391 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7392 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
7393 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7394 WIPHY_VENDOR_CMD_NEED_NETDEV |
7395 WIPHY_VENDOR_CMD_NEED_RUNNING,
7396 .doit = wlan_hdd_cfg80211_set_passpoint_list
7397 },
7398 {
7399 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7400 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
7401 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7402 WIPHY_VENDOR_CMD_NEED_NETDEV |
7403 WIPHY_VENDOR_CMD_NEED_RUNNING,
7404 .doit = wlan_hdd_cfg80211_reset_passpoint_list
7405 },
7406 {
7407 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7408 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
7409 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7410 WIPHY_VENDOR_CMD_NEED_NETDEV |
7411 WIPHY_VENDOR_CMD_NEED_RUNNING,
7412 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
7413 },
7414 {
7415 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7416 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
7417 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7418 WIPHY_VENDOR_CMD_NEED_NETDEV |
7419 WIPHY_VENDOR_CMD_NEED_RUNNING,
7420 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
7421 },
7422#endif /* FEATURE_WLAN_EXTSCAN */
7423 {
7424 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7425 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
7426 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7427 WIPHY_VENDOR_CMD_NEED_NETDEV,
7428 .doit = wlan_hdd_cfg80211_get_wifi_info
7429 },
7430 {
7431 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7432 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
7433 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7434 WIPHY_VENDOR_CMD_NEED_NETDEV |
7435 WIPHY_VENDOR_CMD_NEED_RUNNING,
7436 .doit = wlan_hdd_cfg80211_wifi_configuration_set
7437 },
7438 {
7439 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7440 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
7441 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7442 WIPHY_VENDOR_CMD_NEED_NETDEV,
7443 .doit = wlan_hdd_cfg80211_set_ext_roam_params
7444 },
7445 {
7446 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7447 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
7448 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7449 WIPHY_VENDOR_CMD_NEED_NETDEV,
7450 .doit = wlan_hdd_cfg80211_wifi_logger_start
7451 },
7452 {
7453 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7454 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
7455 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7456 WIPHY_VENDOR_CMD_NEED_NETDEV,
7457 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
7458 },
7459 {
7460 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7461 .info.subcmd =
7462 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
7463 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7464 WIPHY_VENDOR_CMD_NEED_NETDEV |
7465 WIPHY_VENDOR_CMD_NEED_RUNNING,
7466 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
7467 },
7468 {
7469 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7470 .info.subcmd =
7471 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
7472 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7473 WIPHY_VENDOR_CMD_NEED_NETDEV |
7474 WIPHY_VENDOR_CMD_NEED_RUNNING,
7475 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
7476 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07007477#ifdef WLAN_FEATURE_TSF
7478 {
7479 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7480 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
7481 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7482 WIPHY_VENDOR_CMD_NEED_NETDEV |
7483 WIPHY_VENDOR_CMD_NEED_RUNNING,
7484 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
7485 },
7486#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007487#ifdef FEATURE_WLAN_TDLS
7488 {
7489 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7490 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
7491 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7492 WIPHY_VENDOR_CMD_NEED_NETDEV |
7493 WIPHY_VENDOR_CMD_NEED_RUNNING,
7494 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
7495 },
7496#endif
7497#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
7498 {
7499 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7500 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
7501 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7502 WIPHY_VENDOR_CMD_NEED_NETDEV |
7503 WIPHY_VENDOR_CMD_NEED_RUNNING,
7504 .doit = wlan_hdd_cfg80211_offloaded_packets
7505 },
7506#endif
7507 {
7508 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7509 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
7510 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7511 WIPHY_VENDOR_CMD_NEED_NETDEV |
7512 WIPHY_VENDOR_CMD_NEED_RUNNING,
7513 .doit = wlan_hdd_cfg80211_monitor_rssi
7514 },
7515 {
7516 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05307517 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
7518 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7519 WIPHY_VENDOR_CMD_NEED_NETDEV |
7520 WIPHY_VENDOR_CMD_NEED_RUNNING,
7521 .doit = wlan_hdd_cfg80211_set_ns_offload
7522 },
7523 {
7524 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007525 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
7526 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7527 WIPHY_VENDOR_CMD_NEED_NETDEV |
7528 WIPHY_VENDOR_CMD_NEED_RUNNING,
7529 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
7530 },
7531#ifdef WLAN_FEATURE_MEMDUMP
7532 {
7533 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7534 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
7535 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7536 WIPHY_VENDOR_CMD_NEED_NETDEV |
7537 WIPHY_VENDOR_CMD_NEED_RUNNING,
7538 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
7539 },
7540#endif /* WLAN_FEATURE_MEMDUMP */
7541 {
7542 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7543 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
7544 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7545 WIPHY_VENDOR_CMD_NEED_NETDEV |
7546 WIPHY_VENDOR_CMD_NEED_RUNNING,
7547 .doit = wlan_hdd_cfg80211_vendor_scan
7548 },
7549
7550 /* OCB commands */
7551 {
7552 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7553 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
7554 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7555 WIPHY_VENDOR_CMD_NEED_NETDEV |
7556 WIPHY_VENDOR_CMD_NEED_RUNNING,
7557 .doit = wlan_hdd_cfg80211_ocb_set_config
7558 },
7559 {
7560 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7561 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
7562 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7563 WIPHY_VENDOR_CMD_NEED_NETDEV |
7564 WIPHY_VENDOR_CMD_NEED_RUNNING,
7565 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
7566 },
7567 {
7568 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7569 .info.subcmd =
7570 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
7571 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7572 WIPHY_VENDOR_CMD_NEED_NETDEV |
7573 WIPHY_VENDOR_CMD_NEED_RUNNING,
7574 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
7575 },
7576 {
7577 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7578 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
7579 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7580 WIPHY_VENDOR_CMD_NEED_NETDEV |
7581 WIPHY_VENDOR_CMD_NEED_RUNNING,
7582 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
7583 },
7584 {
7585 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7586 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
7587 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7588 WIPHY_VENDOR_CMD_NEED_NETDEV |
7589 WIPHY_VENDOR_CMD_NEED_RUNNING,
7590 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
7591 },
7592 {
7593 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7594 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
7595 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7596 WIPHY_VENDOR_CMD_NEED_NETDEV |
7597 WIPHY_VENDOR_CMD_NEED_RUNNING,
7598 .doit = wlan_hdd_cfg80211_dcc_get_stats
7599 },
7600 {
7601 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7602 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
7603 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7604 WIPHY_VENDOR_CMD_NEED_NETDEV |
7605 WIPHY_VENDOR_CMD_NEED_RUNNING,
7606 .doit = wlan_hdd_cfg80211_dcc_clear_stats
7607 },
7608 {
7609 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7610 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
7611 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7612 WIPHY_VENDOR_CMD_NEED_NETDEV |
7613 WIPHY_VENDOR_CMD_NEED_RUNNING,
7614 .doit = wlan_hdd_cfg80211_dcc_update_ndl
7615 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05307616 {
7617 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7618 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
7619 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7620 WIPHY_VENDOR_CMD_NEED_NETDEV |
7621 WIPHY_VENDOR_CMD_NEED_RUNNING,
7622 .doit = wlan_hdd_cfg80211_get_link_properties
7623 },
Peng Xu278d0122015-09-24 16:34:17 -07007624 {
Peng Xud2220962016-07-11 17:59:17 -07007625 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07007626 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
7627 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7628 WIPHY_VENDOR_CMD_NEED_NETDEV |
7629 WIPHY_VENDOR_CMD_NEED_RUNNING,
7630 .doit = wlan_hdd_cfg80211_set_ota_test
7631 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08007632#ifdef FEATURE_LFR_SUBNET_DETECTION
7633 {
7634 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7635 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
7636 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7637 WIPHY_VENDOR_CMD_NEED_NETDEV |
7638 WIPHY_VENDOR_CMD_NEED_RUNNING,
7639 .doit = wlan_hdd_cfg80211_set_gateway_params
7640 },
7641#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07007642 {
Peng Xud2220962016-07-11 17:59:17 -07007643 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07007644 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
7645 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7646 WIPHY_VENDOR_CMD_NEED_NETDEV |
7647 WIPHY_VENDOR_CMD_NEED_RUNNING,
7648 .doit = wlan_hdd_cfg80211_txpower_scale
7649 },
7650 {
7651 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7652 .info.subcmd =
7653 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
7654 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7655 WIPHY_VENDOR_CMD_NEED_NETDEV |
7656 WIPHY_VENDOR_CMD_NEED_RUNNING,
7657 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
7658 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307659 {
7660 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7661 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
7662 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7663 WIPHY_VENDOR_CMD_NEED_NETDEV |
7664 WIPHY_VENDOR_CMD_NEED_RUNNING,
7665 .doit = wlan_hdd_cfg80211_bpf_offload
7666 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307667 {
7668 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7669 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
7670 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7671 WIPHY_VENDOR_CMD_NEED_NETDEV |
7672 WIPHY_VENDOR_CMD_NEED_RUNNING,
7673 .doit = wlan_hdd_cfg80211_sap_configuration_set
7674 },
Peng Xu8fdaa492016-06-22 10:20:47 -07007675 {
Peng Xu4225c152016-07-14 21:18:14 -07007676 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07007677 .info.subcmd =
7678 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
7679 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7680 WIPHY_VENDOR_CMD_NEED_NETDEV |
7681 WIPHY_VENDOR_CMD_NEED_RUNNING,
7682 .doit = wlan_hdd_cfg80211_p2p_lo_start
7683 },
7684 {
7685 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7686 .info.subcmd =
7687 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
7688 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7689 WIPHY_VENDOR_CMD_NEED_NETDEV |
7690 WIPHY_VENDOR_CMD_NEED_RUNNING,
7691 .doit = wlan_hdd_cfg80211_p2p_lo_stop
7692 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05307693 {
7694 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7695 .info.subcmd =
7696 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
7697 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7698 WIPHY_VENDOR_CMD_NEED_NETDEV |
7699 WIPHY_VENDOR_CMD_NEED_RUNNING,
7700 .doit = wlan_hdd_cfg80211_conditional_chan_switch
7701 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07007702#ifdef WLAN_FEATURE_NAN_DATAPATH
7703 {
7704 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7705 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
7706 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7707 WIPHY_VENDOR_CMD_NEED_NETDEV |
7708 WIPHY_VENDOR_CMD_NEED_RUNNING,
7709 .doit = wlan_hdd_cfg80211_process_ndp_cmd
7710 },
7711#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307712 {
7713 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7714 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
7715 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7716 WIPHY_VENDOR_CMD_NEED_NETDEV |
7717 WIPHY_VENDOR_CMD_NEED_RUNNING,
7718 .doit = wlan_hdd_cfg80211_get_wakelock_stats
7719 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307720 {
7721 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
7722 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7723 WIPHY_VENDOR_CMD_NEED_NETDEV |
7724 WIPHY_VENDOR_CMD_NEED_RUNNING,
7725 .doit = wlan_hdd_cfg80211_setband
7726 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007727};
7728
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007729/**
7730 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
7731 * @priv_size: Size of the hdd context.
7732 *
7733 * Allocate wiphy context and hdd context.
7734 *
7735 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007736 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007737hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007738{
7739 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007740 hdd_context_t *hdd_ctx;
7741
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007742 ENTER();
7743
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007744 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
7745
7746 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007747 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007748 return NULL;
7749 }
7750
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08007751 hdd_ctx = wiphy_priv(wiphy);
7752
7753 hdd_ctx->wiphy = wiphy;
7754
7755 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007756}
7757
7758/*
7759 * FUNCTION: wlan_hdd_cfg80211_update_band
7760 * This function is called from the supplicant through a
7761 * private ioctl to change the band value
7762 */
7763int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
7764{
7765 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07007766 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007767
7768 ENTER();
7769
7770 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
7771
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08007772 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007773 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007774
7775 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
7776 struct ieee80211_supported_band *band = wiphy->bands[i];
7777
7778 channelEnabledState =
7779 cds_get_channel_state(band->channels[j].
7780 hw_value);
7781
7782 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
7783 /* 5G only */
7784#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
7785 /* Enable Social channels for P2P */
7786 if (WLAN_HDD_IS_SOCIAL_CHANNEL
7787 (band->channels[j].center_freq)
7788 && CHANNEL_STATE_ENABLE ==
7789 channelEnabledState)
7790 band->channels[j].flags &=
7791 ~IEEE80211_CHAN_DISABLED;
7792 else
7793#endif
7794 band->channels[j].flags |=
7795 IEEE80211_CHAN_DISABLED;
7796 continue;
7797 } else if (IEEE80211_BAND_5GHZ == i &&
7798 eCSR_BAND_24 == eBand) {
7799 /* 2G only */
7800 band->channels[j].flags |=
7801 IEEE80211_CHAN_DISABLED;
7802 continue;
7803 }
7804
Amar Singhal6842e8f2016-02-23 16:30:32 -08007805 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007806 band->channels[j].flags &=
7807 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007808 }
7809 }
7810 return 0;
7811}
7812
7813/*
7814 * FUNCTION: wlan_hdd_cfg80211_init
7815 * This function is called by hdd_wlan_startup()
7816 * during initialization.
7817 * This function is used to initialize and register wiphy structure.
7818 */
7819int wlan_hdd_cfg80211_init(struct device *dev,
7820 struct wiphy *wiphy, struct hdd_config *pCfg)
7821{
7822 int i, j;
7823 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
7824
7825 ENTER();
7826
7827 /* Now bind the underlying wlan device with wiphy */
7828 set_wiphy_dev(wiphy, dev);
7829
7830 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
7831
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007832#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
7833 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07007834 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007835#else
7836 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07007837 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007838#endif
7839
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007840 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
7841 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
7842 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
7843#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
7844 | WIPHY_FLAG_4ADDR_STATION
7845#endif
7846 | WIPHY_FLAG_OFFCHAN_TX;
7847
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007848#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
7849 wiphy->wowlan = &wowlan_support_cfg80211_init;
7850#else
7851 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
7852 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
7853 wiphy->wowlan.pattern_min_len = 1;
7854 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
7855#endif
7856
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07007857 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007858#ifdef FEATURE_WLAN_ESE
7859 || pCfg->isEseIniFeatureEnabled
7860#endif
7861 ) {
7862 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
7863 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007864#ifdef FEATURE_WLAN_TDLS
7865 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
7866 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
7867#endif
7868
7869 wiphy->features |= NL80211_FEATURE_HT_IBSS;
7870
Naveen Rawatc77e6e72016-08-05 15:19:03 -07007871#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
7872 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
7873#endif
7874
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007875#ifdef FEATURE_WLAN_SCAN_PNO
7876 if (pCfg->configPNOScanSupport) {
7877 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
7878 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
7879 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
7880 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Ryan Hsub736bc52016-06-15 16:58:24 -07007881#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) || defined(WITH_BACKPORTS)
7882 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
7883#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007884 }
7885#endif /*FEATURE_WLAN_SCAN_PNO */
7886
7887#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05307888 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007889#endif
7890
7891 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
7892 driver can still register regulatory callback and
7893 it will get regulatory settings in wiphy->band[], but
7894 driver need to determine what to do with both
7895 regulatory settings */
7896
7897 wiphy->reg_notifier = hdd_reg_notifier;
7898
7899#if defined QCA_WIFI_FTM
7900}
7901#endif
7902
7903 wiphy->max_scan_ssids = MAX_SCAN_SSID;
7904
7905 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
7906
7907 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
7908
Arun Khandavallifae92942016-08-01 13:31:08 +05307909 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
7910 | BIT(NL80211_IFTYPE_ADHOC)
7911 | BIT(NL80211_IFTYPE_P2P_CLIENT)
7912 | BIT(NL80211_IFTYPE_P2P_GO)
7913 | BIT(NL80211_IFTYPE_AP)
7914 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007915
Arun Khandavallifae92942016-08-01 13:31:08 +05307916 if (pCfg->advertiseConcurrentOperation) {
7917 if (pCfg->enableMCC) {
7918 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07007919
Arun Khandavallifae92942016-08-01 13:31:08 +05307920 for (i = 0;
7921 i < ARRAY_SIZE(wlan_hdd_iface_combination);
7922 i++) {
7923 if (!pCfg->allowMCCGODiffBI)
7924 wlan_hdd_iface_combination[i].
7925 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007926 }
7927 }
7928 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +05307929 ARRAY_SIZE(wlan_hdd_iface_combination);
7930 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007931 }
7932
7933 /* Before registering we need to update the ht capabilitied based
7934 * on ini values*/
7935 if (!pCfg->ShortGI20MhzEnable) {
7936 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
7937 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007938 }
7939
7940 if (!pCfg->ShortGI40MhzEnable) {
7941 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
7942 }
7943
7944 if (!pCfg->nChannelBondingMode5GHz) {
7945 wlan_hdd_band_5_ghz.ht_cap.cap &=
7946 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
7947 }
7948
Abhishek Singhf512bf32016-05-04 16:47:46 +05307949 /*
7950 * In case of static linked driver at the time of driver unload,
7951 * module exit doesn't happens. Module cleanup helps in cleaning
7952 * of static memory.
7953 * If driver load happens statically, at the time of driver unload,
7954 * wiphy flags don't get reset because of static memory.
7955 * It's better not to store channel in static memory.
7956 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007957 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
Abhishek Singhf512bf32016-05-04 16:47:46 +05307958 wiphy->bands[IEEE80211_BAND_2GHZ]->channels =
7959 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
7960 if (wiphy->bands[IEEE80211_BAND_2GHZ]->channels == NULL) {
7961 hdd_err("Not enough memory to allocate channels");
7962 return -ENOMEM;
7963 }
7964 qdf_mem_copy(wiphy->bands[IEEE80211_BAND_2GHZ]->channels,
7965 &hdd_channels_2_4_ghz[0],
7966 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +05307967 if ((hdd_is_5g_supported(pHddCtx)) &&
7968 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
7969 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
7970 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
7971 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007972 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
Abhishek Singhf512bf32016-05-04 16:47:46 +05307973 wiphy->bands[IEEE80211_BAND_5GHZ]->channels =
7974 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
7975 if (wiphy->bands[IEEE80211_BAND_5GHZ]->channels == NULL) {
7976 hdd_err("Not enough memory to allocate channels");
7977 qdf_mem_free(wiphy->
7978 bands[IEEE80211_BAND_2GHZ]->channels);
7979 wiphy->bands[IEEE80211_BAND_2GHZ]->channels = NULL;
7980 return -ENOMEM;
7981 }
7982 qdf_mem_copy(wiphy->bands[IEEE80211_BAND_5GHZ]->channels,
7983 &hdd_channels_5_ghz[0],
7984 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007985 }
7986
7987 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
7988
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08007989 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007990 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007991
7992 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
7993 struct ieee80211_supported_band *band = wiphy->bands[i];
7994
7995 if (IEEE80211_BAND_2GHZ == i &&
7996 eCSR_BAND_5G == pCfg->nBandCapability) {
7997 /* 5G only */
7998#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
7999 /* Enable social channels for P2P */
8000 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8001 (band->channels[j].center_freq))
8002 band->channels[j].flags &=
8003 ~IEEE80211_CHAN_DISABLED;
8004 else
8005#endif
8006 band->channels[j].flags |=
8007 IEEE80211_CHAN_DISABLED;
8008 continue;
8009 } else if (IEEE80211_BAND_5GHZ == i &&
8010 eCSR_BAND_24 == pCfg->nBandCapability) {
8011 /* 2G only */
8012 band->channels[j].flags |=
8013 IEEE80211_CHAN_DISABLED;
8014 continue;
8015 }
8016 }
8017 }
8018 /*Initialise the supported cipher suite details */
8019 wiphy->cipher_suites = hdd_cipher_suites;
8020 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
8021
8022 /*signal strength in mBm (100*dBm) */
8023 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
8024 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
8025
Anurag Chouhan6d760662016-02-20 16:05:43 +05308026 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008027 wiphy->n_vendor_commands =
8028 ARRAY_SIZE(hdd_wiphy_vendor_commands);
8029 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
8030
8031 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
8032 wiphy->n_vendor_events =
8033 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
8034 }
8035
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008036 if (pCfg->enableDFSMasterCap) {
8037 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
8038 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008039
8040 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8041
8042#ifdef QCA_HT_2040_COEX
8043 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
8044#endif
8045
Abhishek Singh1bdb1572015-10-16 16:24:19 +05308046 hdd_add_channel_switch_support(&wiphy->flags);
8047
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008048 EXIT();
8049 return 0;
8050}
8051
Abhishek Singhf512bf32016-05-04 16:47:46 +05308052/**
8053 * wlan_hdd_cfg80211_deinit - Deinit cfg80211
8054 * @ wiphy: the wiphy to validate against
8055 *
8056 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308057 * memory allocated in wlan_hdd_cfg80211_init also
8058 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +05308059 *
8060 * Return: void
8061 */
8062void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
8063{
8064 int i;
8065
8066 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8067 if (NULL != wiphy->bands[i] &&
8068 (NULL != wiphy->bands[i]->channels)) {
8069 qdf_mem_free(wiphy->bands[i]->channels);
8070 wiphy->bands[i]->channels = NULL;
8071 }
8072 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308073 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +05308074}
8075
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008076/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308077 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008078 * initialization. In wlan_hdd_cfg80211_init, only the
8079 * default values will be initialized. The final initialization
8080 * of all required members can be done here.
8081 */
8082void wlan_hdd_update_wiphy(struct wiphy *wiphy, struct hdd_config *pCfg)
8083{
8084 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8085}
8086
8087/* In this function we are registering wiphy. */
8088int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
8089{
8090 ENTER();
8091 /* Register our wiphy dev with cfg80211 */
8092 if (0 > wiphy_register(wiphy)) {
8093 /* print error */
Jeff Johnson77848112016-06-29 14:52:06 -07008094 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008095 return -EIO;
8096 }
8097
8098 EXIT();
8099 return 0;
8100}
8101
8102/*
8103 HDD function to update wiphy capability based on target offload status.
8104
8105 wlan_hdd_cfg80211_init() does initialization of all wiphy related
8106 capability even before downloading firmware to the target. In discrete
8107 case, host will get know certain offload capability (say sched_scan
8108 caps) only after downloading firmware to the target and target boots up.
8109 This function is used to override setting done in wlan_hdd_cfg80211_init()
8110 based on target capability.
8111 */
8112void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
8113{
8114#ifdef FEATURE_WLAN_SCAN_PNO
8115 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8116 struct hdd_config *pCfg = pHddCtx->config;
8117
8118 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
8119 * control comes here. Here just we need to clear it if firmware doesn't
8120 * have PNO support. */
8121 if (!pCfg->PnoOffload) {
8122 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8123 wiphy->max_sched_scan_ssids = 0;
8124 wiphy->max_match_sets = 0;
8125 wiphy->max_sched_scan_ie_len = 0;
8126 }
8127#endif
8128}
8129
8130/* This function registers for all frame which supplicant is interested in */
8131void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
8132{
8133 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8134 /* Register for all P2P action, public action etc frames */
8135 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
8136
8137 ENTER();
8138
Abhishek Singh7996eb72015-12-30 17:24:02 +05308139 /* Register frame indication call back */
8140 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
8141
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +05308142 /* Register for p2p ack indication */
8143 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
8144
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008145 /* Right now we are registering these frame when driver is getting
8146 initialized. Once we will move to 2.6.37 kernel, in which we have
8147 frame register ops, we will move this code as a part of that */
8148 /* GAS Initial Request */
8149 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8150 (uint8_t *) GAS_INITIAL_REQ,
8151 GAS_INITIAL_REQ_SIZE);
8152
8153 /* GAS Initial Response */
8154 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8155 (uint8_t *) GAS_INITIAL_RSP,
8156 GAS_INITIAL_RSP_SIZE);
8157
8158 /* GAS Comeback Request */
8159 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8160 (uint8_t *) GAS_COMEBACK_REQ,
8161 GAS_COMEBACK_REQ_SIZE);
8162
8163 /* GAS Comeback Response */
8164 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8165 (uint8_t *) GAS_COMEBACK_RSP,
8166 GAS_COMEBACK_RSP_SIZE);
8167
8168 /* P2P Public Action */
8169 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8170 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
8171 P2P_PUBLIC_ACTION_FRAME_SIZE);
8172
8173 /* P2P Action */
8174 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8175 (uint8_t *) P2P_ACTION_FRAME,
8176 P2P_ACTION_FRAME_SIZE);
8177
8178 /* WNM BSS Transition Request frame */
8179 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8180 (uint8_t *) WNM_BSS_ACTION_FRAME,
8181 WNM_BSS_ACTION_FRAME_SIZE);
8182
8183 /* WNM-Notification */
8184 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
8185 (uint8_t *) WNM_NOTIFICATION_FRAME,
8186 WNM_NOTIFICATION_FRAME_SIZE);
8187}
8188
8189void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
8190{
8191 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8192 /* Register for all P2P action, public action etc frames */
8193 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
8194
8195 ENTER();
8196
8197 /* Right now we are registering these frame when driver is getting
8198 initialized. Once we will move to 2.6.37 kernel, in which we have
8199 frame register ops, we will move this code as a part of that */
8200 /* GAS Initial Request */
8201
8202 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8203 (uint8_t *) GAS_INITIAL_REQ,
8204 GAS_INITIAL_REQ_SIZE);
8205
8206 /* GAS Initial Response */
8207 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8208 (uint8_t *) GAS_INITIAL_RSP,
8209 GAS_INITIAL_RSP_SIZE);
8210
8211 /* GAS Comeback Request */
8212 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8213 (uint8_t *) GAS_COMEBACK_REQ,
8214 GAS_COMEBACK_REQ_SIZE);
8215
8216 /* GAS Comeback Response */
8217 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8218 (uint8_t *) GAS_COMEBACK_RSP,
8219 GAS_COMEBACK_RSP_SIZE);
8220
8221 /* P2P Public Action */
8222 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8223 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
8224 P2P_PUBLIC_ACTION_FRAME_SIZE);
8225
8226 /* P2P Action */
8227 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8228 (uint8_t *) P2P_ACTION_FRAME,
8229 P2P_ACTION_FRAME_SIZE);
8230
8231 /* WNM-Notification */
8232 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
8233 (uint8_t *) WNM_NOTIFICATION_FRAME,
8234 WNM_NOTIFICATION_FRAME_SIZE);
8235}
8236
8237#ifdef FEATURE_WLAN_WAPI
8238void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
8239 const uint8_t *mac_addr, const uint8_t *key,
8240 int key_Len)
8241{
8242 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8243 tCsrRoamSetKey setKey;
8244 bool isConnected = true;
8245 int status = 0;
8246 uint32_t roamId = 0xFF;
8247 uint8_t *pKeyPtr = NULL;
8248 int n = 0;
8249
Jeff Johnson46b40792016-06-29 14:03:14 -07008250 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008251 hdd_device_mode_to_string(pAdapter->device_mode),
8252 pAdapter->device_mode);
8253
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308254 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008255 setKey.keyId = key_index; /* Store Key ID */
8256 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
8257 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
8258 setKey.paeRole = 0; /* the PAE role */
8259 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05308260 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008261 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308262 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008263 }
8264 setKey.keyLength = key_Len;
8265 pKeyPtr = setKey.Key;
8266 memcpy(pKeyPtr, key, key_Len);
8267
Jeff Johnson46b40792016-06-29 14:03:14 -07008268 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008269 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -07008270 hdd_notice("WAPI KEY Data[%d]:%02x ",
8271 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008272
8273 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
8274 if (isConnected) {
8275 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
8276 pAdapter->sessionId, &setKey, &roamId);
8277 }
8278 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -07008279 hdd_err("sme_roam_set_key returned ERROR status= %d",
8280 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008281 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
8282 }
8283}
8284#endif /* FEATURE_WLAN_WAPI */
8285
8286uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
8287 uint8_t eid)
8288{
8289 int left = length;
8290 uint8_t *ptr = (uint8_t *)ies_ptr;
8291 uint8_t elem_id, elem_len;
8292
8293 while (left >= 2) {
8294 elem_id = ptr[0];
8295 elem_len = ptr[1];
8296 left -= 2;
8297 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -07008298 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008299 eid, elem_len, left);
8300 return NULL;
8301 }
8302 if (elem_id == eid) {
8303 return ptr;
8304 }
8305
8306 left -= elem_len;
8307 ptr += (elem_len + 2);
8308 }
8309 return NULL;
8310}
8311
8312/*
8313 * FUNCTION: wlan_hdd_validate_operation_channel
8314 * called by wlan_hdd_cfg80211_start_bss() and
8315 * wlan_hdd_set_channel()
8316 * This function validates whether given channel is part of valid
8317 * channel list.
8318 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308319QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008320 int channel)
8321{
8322
8323 uint32_t num_ch = 0;
8324 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
8325 u32 indx = 0;
8326 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8327 uint8_t fValidChannel = false, count = 0;
8328 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
8329
8330 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
8331
8332 if (hdd_pConfig_ini->sapAllowAllChannel) {
8333 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -08008334 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07008335 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008336 fValidChannel = true;
8337 break;
8338 }
8339 }
8340 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -07008341 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308342 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008343 }
8344 } else {
8345 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
8346 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008347 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308348 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008349 }
8350 for (indx = 0; indx < num_ch; indx++) {
8351 if (channel == valid_ch[indx]) {
8352 break;
8353 }
8354 }
8355
8356 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -07008357 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308358 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008359 }
8360 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308361 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008362
8363}
8364
8365#ifdef DHCP_SERVER_OFFLOAD
8366static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
8367{
8368 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
8369 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
8370 uint8_t numEntries = 0;
8371 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
8372 uint8_t num;
8373 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308374 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008375 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -07008376 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008377 return;
8378 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308379 qdf_mem_zero(pDhcpSrvInfo, sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008380 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
8381 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
8382 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
8383 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
8384 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
8385 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -07008386 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008387 goto end;
8388 }
8389 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008390 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008391 goto end;
8392 }
8393 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -07008394 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008395 goto end;
8396 }
8397 for (num = 0; num < numEntries; num++) {
8398 temp = srv_ip[num];
8399 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
8400 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308401 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008402 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008403 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008404 goto end;
8405 }
Jeff Johnson77848112016-06-29 14:52:06 -07008406 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008407end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308408 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008409 return;
8410}
8411#endif /* DHCP_SERVER_OFFLOAD */
8412
8413static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
8414 struct net_device *dev,
8415 struct bss_parameters *params)
8416{
8417 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8418 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8419 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308420 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008421
8422 ENTER();
8423
Anurag Chouhan6d760662016-02-20 16:05:43 +05308424 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008425 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008426 return -EINVAL;
8427 }
8428
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308429 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008430 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
8431 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -07008432 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008433 hdd_device_mode_to_string(pAdapter->device_mode),
8434 pAdapter->device_mode, params->ap_isolate);
8435
8436 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8437 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05308438 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008439 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008440
Krunal Sonib4326f22016-03-10 13:05:51 -08008441 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
8442 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008443 return -EOPNOTSUPP;
8444 }
8445
8446 /* ap_isolate == -1 means that in change bss, upper layer doesn't
8447 * want to update this parameter */
8448 if (-1 != params->ap_isolate) {
8449 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
8450 !!params->ap_isolate;
8451
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308452 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008453 pAdapter->sessionId,
8454 pAdapter->sessionCtx.
8455 ap.
8456 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308457 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008458 ret = -EINVAL;
8459 }
8460 }
8461
8462 EXIT();
8463 return ret;
8464}
8465
Krunal Soni8c37e322016-02-03 16:08:37 -08008466/**
8467 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
8468 * @ndev: pointer to net device provided by supplicant
8469 * @type: type of the interface, upper layer wanted to change
8470 *
8471 * Upper layer provides the new interface mode that needs to be changed
8472 * for given net device
8473 *
8474 * Return: success or failure in terms of integer value
8475 */
8476static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008477 enum nl80211_iftype type)
8478{
Krunal Soni8c37e322016-02-03 16:08:37 -08008479 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8480 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
8481 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008482 hdd_wext_state_t *wext;
8483 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05308484 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008485
8486 ENTER();
8487
Krunal Soni8c37e322016-02-03 16:08:37 -08008488 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008489 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008490 return 0;
8491 }
8492
8493 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -08008494 hdd_stop_adapter(hdd_ctx, adapter, true);
8495 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008496 wdev->iftype = type;
8497 /*Check for sub-string p2p to confirm its a p2p interface */
8498 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -08008499 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008500 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08008501 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -08008502 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -08008503 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008504 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -08008505 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008506 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08008507 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008508 }
Krunal Soni8c37e322016-02-03 16:08:37 -08008509 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
8510 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -08008511 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
8512 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008513 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -08008514 adapter->scan_info.scanAddIE.length;
8515 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +05308516 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -08008517 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
8518 wext->roamProfile.phyMode =
8519 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
8520 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008521 EXIT();
8522 return status;
8523}
8524
8525static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
8526 struct net_device *dev,
8527 struct bss_parameters *params)
8528{
8529 int ret;
8530
8531 cds_ssr_protect(__func__);
8532 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
8533 cds_ssr_unprotect(__func__);
8534
8535 return ret;
8536}
8537
8538/* FUNCTION: wlan_hdd_change_country_code_cd
8539 * to wait for contry code completion
8540 */
8541void *wlan_hdd_change_country_code_cb(void *pAdapter)
8542{
8543 hdd_adapter_t *call_back_pAdapter = pAdapter;
8544 complete(&call_back_pAdapter->change_country_code);
8545 return NULL;
8546}
8547
Rajeev Kumar98edb772016-01-19 12:42:19 -08008548/**
8549 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
8550 * @wiphy: Pointer to the wiphy structure
8551 * @ndev: Pointer to the net device
8552 * @type: Interface type
8553 * @flags: Flags for change interface
8554 * @params: Pointer to change interface parameters
8555 *
8556 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008557 */
8558static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
8559 struct net_device *ndev,
8560 enum nl80211_iftype type,
8561 u32 *flags,
8562 struct vif_params *params)
8563{
8564 struct wireless_dev *wdev;
8565 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
8566 hdd_context_t *pHddCtx;
8567 tCsrRoamProfile *pRoamProfile = NULL;
8568 eCsrRoamBssType LastBSSType;
8569 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308570 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008571 int status;
8572
8573 ENTER();
8574
Anurag Chouhan6d760662016-02-20 16:05:43 +05308575 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07008576 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008577 return -EINVAL;
8578 }
8579
8580 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8581 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05308582 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008583 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008584
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308585 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008586 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
8587 pAdapter->sessionId, type));
8588
Jeff Johnson77848112016-06-29 14:52:06 -07008589 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008590 pAdapter->device_mode, type);
8591
Arun Khandavallifae92942016-08-01 13:31:08 +05308592 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
8593 if (status) {
8594 hdd_err("Failed to start modules");
8595 return -EINVAL;
8596 }
8597
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08008598 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008599 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
8600 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -07008601 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008602 return -EINVAL;
8603 }
8604
8605 pConfig = pHddCtx->config;
8606 wdev = ndev->ieee80211_ptr;
8607
8608 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08008609 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008610
8611 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
8612
Krunal Sonib4326f22016-03-10 13:05:51 -08008613 if ((pAdapter->device_mode == QDF_STA_MODE) ||
8614 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
8615 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
8616 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008617 hdd_wext_state_t *pWextState =
8618 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
8619
8620 pRoamProfile = &pWextState->roamProfile;
8621 LastBSSType = pRoamProfile->BSSType;
8622
8623 switch (type) {
8624 case NL80211_IFTYPE_STATION:
8625 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -08008626 case NL80211_IFTYPE_ADHOC:
8627 if (type == NL80211_IFTYPE_ADHOC) {
8628 wlan_hdd_tdls_exit(pAdapter);
8629 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -07008630 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -08008631 }
8632 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
8633 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308634 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008635 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05308636 if (hdd_start_adapter(pAdapter)) {
8637 hdd_err("Failed to start adapter :%d",
8638 pAdapter->device_mode);
8639 return -EINVAL;
8640 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008641 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008642 case NL80211_IFTYPE_AP:
8643 case NL80211_IFTYPE_P2P_GO:
8644 {
Jeff Johnson77848112016-06-29 14:52:06 -07008645 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008646 (type ==
8647 NL80211_IFTYPE_AP) ? "SoftAP" :
8648 "P2pGo");
8649
8650 /* Cancel any remain on channel for GO mode */
8651 if (NL80211_IFTYPE_P2P_GO == type) {
8652 wlan_hdd_cancel_existing_remain_on_channel
8653 (pAdapter);
8654 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008655
Arun Khandavallifae92942016-08-01 13:31:08 +05308656 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008657 /* De-init the adapter */
8658 hdd_deinit_adapter(pHddCtx, pAdapter, true);
8659 memset(&pAdapter->sessionCtx, 0,
8660 sizeof(pAdapter->sessionCtx));
8661 pAdapter->device_mode =
8662 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -08008663 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
8664 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008665
8666 /*
8667 * Fw will take care incase of concurrency
8668 */
8669
Krunal Sonib4326f22016-03-10 13:05:51 -08008670 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008671 && (pConfig->apRandomBssidEnabled)) {
8672 /* To meet Android requirements create a randomized
8673 MAC address of the form 02:1A:11:Fx:xx:xx */
8674 get_random_bytes(&ndev->dev_addr[3], 3);
8675 ndev->dev_addr[0] = 0x02;
8676 ndev->dev_addr[1] = 0x1A;
8677 ndev->dev_addr[2] = 0x11;
8678 ndev->dev_addr[3] |= 0xF0;
8679 memcpy(pAdapter->macAddressCurrent.
8680 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05308681 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008682 pr_info("wlan: Generated HotSpot BSSID "
8683 MAC_ADDRESS_STR "\n",
8684 MAC_ADDR_ARRAY(ndev->dev_addr));
8685 }
8686
8687 hdd_set_ap_ops(pAdapter->dev);
8688
Arun Khandavallifae92942016-08-01 13:31:08 +05308689 if (hdd_start_adapter(pAdapter)) {
8690 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008691 return -EINVAL;
8692 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008693 /* Interface type changed update in wiphy structure */
8694 if (wdev) {
8695 wdev->iftype = type;
8696 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07008697 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008698 return -EINVAL;
8699 }
8700 goto done;
8701 }
8702
8703 default:
Jeff Johnson77848112016-06-29 14:52:06 -07008704 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008705 type);
8706 return -EOPNOTSUPP;
8707 }
Krunal Sonib4326f22016-03-10 13:05:51 -08008708 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
8709 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008710 switch (type) {
8711 case NL80211_IFTYPE_STATION:
8712 case NL80211_IFTYPE_P2P_CLIENT:
8713 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -08008714 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
8715 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308716 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008717 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05308718 if (hdd_start_adapter(pAdapter)) {
8719 hdd_err("Failed to start adapter :%d",
8720 pAdapter->device_mode);
8721 return -EINVAL;
8722 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008723 goto done;
8724
8725 case NL80211_IFTYPE_AP:
8726 case NL80211_IFTYPE_P2P_GO:
8727 wdev->iftype = type;
8728 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08008729 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008730 goto done;
8731
8732 default:
Jeff Johnson77848112016-06-29 14:52:06 -07008733 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008734 type);
8735 return -EOPNOTSUPP;
8736 }
8737 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07008738 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008739 pAdapter->device_mode);
8740 return -EOPNOTSUPP;
8741 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008742done:
8743 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08008744 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008745
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008746 wlan_hdd_send_all_scan_intf_info(pHddCtx);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008747
8748 EXIT();
8749 return 0;
8750}
8751
Rajeev Kumar98edb772016-01-19 12:42:19 -08008752/**
8753 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
8754 * @wiphy: Pointer to the wiphy structure
8755 * @ndev: Pointer to the net device
8756 * @type: Interface type
8757 * @flags: Flags for change interface
8758 * @params: Pointer to change interface parameters
8759 *
8760 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008761 */
8762static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
8763 struct net_device *ndev,
8764 enum nl80211_iftype type,
8765 u32 *flags,
8766 struct vif_params *params)
8767{
8768 int ret;
8769
8770 cds_ssr_protect(__func__);
8771 ret =
8772 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
8773 cds_ssr_unprotect(__func__);
8774
8775 return ret;
8776}
8777
8778#ifdef FEATURE_WLAN_TDLS
8779static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
8780 int index, uint8_t match)
8781{
8782 int i;
8783 for (i = 0; i < index; i++) {
8784 if (arr[i] == match)
8785 return true;
8786 }
8787 return false;
8788}
8789#endif
8790
8791/**
8792 * __wlan_hdd_change_station() - change station
8793 * @wiphy: Pointer to the wiphy structure
8794 * @dev: Pointer to the net device.
8795 * @mac: bssid
8796 * @params: Pointer to station parameters
8797 *
8798 * Return: 0 for success, error number on failure.
8799 */
8800#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
8801static int __wlan_hdd_change_station(struct wiphy *wiphy,
8802 struct net_device *dev,
8803 const uint8_t *mac,
8804 struct station_parameters *params)
8805#else
8806static int __wlan_hdd_change_station(struct wiphy *wiphy,
8807 struct net_device *dev,
8808 uint8_t *mac,
8809 struct station_parameters *params)
8810#endif
8811{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308812 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008813 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
8814 hdd_context_t *pHddCtx;
8815 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +05308816 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008817#ifdef FEATURE_WLAN_TDLS
8818 tCsrStaParams StaParams = { 0 };
8819 uint8_t isBufSta = 0;
8820 uint8_t isOffChannelSupported = 0;
8821#endif
8822 int ret;
8823
8824 ENTER();
8825
Anurag Chouhan6d760662016-02-20 16:05:43 +05308826 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07008827 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008828 return -EINVAL;
8829 }
8830
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05308831 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008832 TRACE_CODE_HDD_CHANGE_STATION,
8833 pAdapter->sessionId, params->listen_interval));
8834
8835 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
8836 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05308837 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008838 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008839
8840 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
8841
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308842 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008843
Krunal Sonib4326f22016-03-10 13:05:51 -08008844 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
8845 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008846 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
8847 status =
8848 hdd_softap_change_sta_state(pAdapter,
8849 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -08008850 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008851
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05308852 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07008853 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008854 return -EINVAL;
8855 }
8856 }
Krunal Sonib4326f22016-03-10 13:05:51 -08008857 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
8858 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008859#ifdef FEATURE_WLAN_TDLS
8860 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -07008861
8862 if (cds_is_sub_20_mhz_enabled()) {
8863 hdd_err("TDLS not allowed with sub 20 MHz");
8864 return -EINVAL;
8865 }
8866
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008867 StaParams.capability = params->capability;
8868 StaParams.uapsd_queues = params->uapsd_queues;
8869 StaParams.max_sp = params->max_sp;
8870
8871 /* Convert (first channel , number of channels) tuple to
8872 * the total list of channels. This goes with the assumption
8873 * that if the first channel is < 14, then the next channels
8874 * are an incremental of 1 else an incremental of 4 till the number
8875 * of channels.
8876 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07008877 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008878 if (0 != params->supported_channels_len) {
8879 int i = 0, j = 0, k = 0, no_of_channels = 0;
8880 int num_unique_channels;
8881 int next;
8882 for (i = 0;
8883 i < params->supported_channels_len
8884 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
8885 int wifi_chan_index;
8886 if (!wlan_hdd_is_duplicate_channel
8887 (StaParams.supported_channels, j,
8888 params->supported_channels[i])) {
8889 StaParams.
8890 supported_channels[j] =
8891 params->
8892 supported_channels[i];
8893 } else {
8894 continue;
8895 }
8896 wifi_chan_index =
8897 ((StaParams.supported_channels[j] <=
8898 HDD_CHANNEL_14) ? 1 : 4);
8899 no_of_channels =
8900 params->supported_channels[i + 1];
8901
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07008902 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 -08008903 StaParams.
8904 supported_channels[j],
8905 wifi_chan_index,
8906 no_of_channels);
8907 for (k = 1; k <= no_of_channels &&
8908 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
8909 k++) {
8910 next =
8911 StaParams.
8912 supported_channels[j] +
8913 wifi_chan_index;
8914 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
8915 StaParams.
8916 supported_channels[j
8917 +
8918 1]
8919 = next;
8920 } else {
8921 continue;
8922 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07008923 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008924 j + 1,
8925 StaParams.
8926 supported_channels[j +
8927 1]);
8928 j += 1;
8929 }
8930 }
8931 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07008932 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008933 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07008934 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008935 StaParams.
8936 supported_channels[i]);
8937 }
8938 if (MAX_CHANNEL < num_unique_channels)
8939 num_unique_channels = MAX_CHANNEL;
8940 StaParams.supported_channels_len =
8941 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07008942 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008943 StaParams.supported_channels_len);
8944 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308945 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008946 params->supported_oper_classes,
8947 params->supported_oper_classes_len);
8948 StaParams.supported_oper_classes_len =
8949 params->supported_oper_classes_len;
8950
8951 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308952 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008953 params->ext_capab,
8954 sizeof(StaParams.extn_capability));
8955
8956 if (NULL != params->ht_capa) {
8957 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308958 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008959 sizeof(tSirHTCap));
8960 }
8961
8962 StaParams.supported_rates_len =
8963 params->supported_rates_len;
8964
8965 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
8966 * The supported_rates array , for all the structures propogating till Add Sta
8967 * to the firmware has to be modified , if the supplicant (ieee80211) is
8968 * modified to send more rates.
8969 */
8970
8971 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
8972 */
8973 if (StaParams.supported_rates_len >
8974 SIR_MAC_MAX_SUPP_RATES)
8975 StaParams.supported_rates_len =
8976 SIR_MAC_MAX_SUPP_RATES;
8977
8978 if (0 != StaParams.supported_rates_len) {
8979 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308980 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008981 params->supported_rates,
8982 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07008983 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008984 StaParams.supported_rates_len);
8985 for (i = 0; i < StaParams.supported_rates_len;
8986 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07008987 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008988 StaParams.supported_rates[i]);
8989 }
8990
8991 if (NULL != params->vht_capa) {
8992 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05308993 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008994 params->vht_capa,
8995 sizeof(tSirVHTCap));
8996 }
8997
8998 if (0 != params->ext_capab_len) {
8999 /*Define A Macro : TODO Sunil */
9000 if ((1 << 4) & StaParams.extn_capability[3]) {
9001 isBufSta = 1;
9002 }
9003 /* TDLS Channel Switching Support */
9004 if ((1 << 6) & StaParams.extn_capability[3]) {
9005 isOffChannelSupported = 1;
9006 }
9007 }
9008
9009 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
9010 &StaParams,
9011 isBufSta,
9012 isOffChannelSupported);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309013 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009014 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009015 return -EINVAL;
9016 }
9017
9018 status =
9019 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
9020 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309021 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009022 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009023 return -EINVAL;
9024 }
9025 }
9026#endif
9027 }
9028 EXIT();
9029 return ret;
9030}
9031
9032/**
9033 * wlan_hdd_change_station() - cfg80211 change station handler function
9034 * @wiphy: Pointer to the wiphy structure
9035 * @dev: Pointer to the net device.
9036 * @mac: bssid
9037 * @params: Pointer to station parameters
9038 *
9039 * This is the cfg80211 change station handler function which invokes
9040 * the internal function @__wlan_hdd_change_station with
9041 * SSR protection.
9042 *
9043 * Return: 0 for success, error number on failure.
9044 */
9045#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
9046static int wlan_hdd_change_station(struct wiphy *wiphy,
9047 struct net_device *dev,
9048 const u8 *mac,
9049 struct station_parameters *params)
9050#else
9051static int wlan_hdd_change_station(struct wiphy *wiphy,
9052 struct net_device *dev,
9053 u8 *mac,
9054 struct station_parameters *params)
9055#endif
9056{
9057 int ret;
9058
9059 cds_ssr_protect(__func__);
9060 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
9061 cds_ssr_unprotect(__func__);
9062
9063 return ret;
9064}
9065
9066/*
9067 * FUNCTION: __wlan_hdd_cfg80211_add_key
9068 * This function is used to initialize the key information
9069 */
9070static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
9071 struct net_device *ndev,
9072 u8 key_index, bool pairwise,
9073 const u8 *mac_addr,
9074 struct key_params *params)
9075{
9076 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9077 tCsrRoamSetKey setKey;
9078 int status;
9079 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009080 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309081 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009082 hdd_context_t *pHddCtx;
9083 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
9084
9085 ENTER();
9086
Anurag Chouhan6d760662016-02-20 16:05:43 +05309087 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009088 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009089 return -EINVAL;
9090 }
9091
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309092 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009093 TRACE_CODE_HDD_CFG80211_ADD_KEY,
9094 pAdapter->sessionId, params->key_len));
9095 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9096 status = wlan_hdd_validate_context(pHddCtx);
9097
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309098 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009099 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009100
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009101 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009102 hdd_device_mode_to_string(pAdapter->device_mode),
9103 pAdapter->device_mode);
9104
9105 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009106 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009107
9108 return -EINVAL;
9109 }
9110
9111 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009112 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009113
9114 return -EINVAL;
9115 }
9116
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009117 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009118
9119 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309120 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009121 setKey.keyId = key_index;
9122 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309123 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009124
9125 switch (params->cipher) {
9126 case WLAN_CIPHER_SUITE_WEP40:
9127 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
9128 break;
9129
9130 case WLAN_CIPHER_SUITE_WEP104:
9131 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
9132 break;
9133
9134 case WLAN_CIPHER_SUITE_TKIP:
9135 {
9136 u8 *pKey = &setKey.Key[0];
9137 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
9138
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309139 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009140
9141 /*Supplicant sends the 32bytes key in this order
9142
9143 |--------------|----------|----------|
9144 | Tk1 |TX-MIC | RX Mic |
9145 |||--------------|----------|----------|
9146 <---16bytes---><--8bytes--><--8bytes-->
9147
9148 */
9149 /*Sme expects the 32 bytes key to be in the below order
9150
9151 |--------------|----------|----------|
9152 | Tk1 |RX-MIC | TX Mic |
9153 |||--------------|----------|----------|
9154 <---16bytes---><--8bytes--><--8bytes-->
9155 */
9156 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309157 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009158
9159 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309160 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009161
9162 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309163 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009164
9165 break;
9166 }
9167
9168 case WLAN_CIPHER_SUITE_CCMP:
9169 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
9170 break;
9171
9172#ifdef FEATURE_WLAN_WAPI
9173 case WLAN_CIPHER_SUITE_SMS4:
9174 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309175 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009176 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
9177 mac_addr, params->key,
9178 params->key_len);
9179 return 0;
9180 }
9181#endif
9182
9183#ifdef FEATURE_WLAN_ESE
9184 case WLAN_CIPHER_SUITE_KRK:
9185 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
9186 break;
9187#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9188 case WLAN_CIPHER_SUITE_BTK:
9189 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
9190 break;
9191#endif
9192#endif
9193
9194#ifdef WLAN_FEATURE_11W
9195 case WLAN_CIPHER_SUITE_AES_CMAC:
9196 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
9197 break;
9198#endif
9199
9200 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009201 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009202 return -EOPNOTSUPP;
9203 }
9204
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009205 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009206
9207 if (!pairwise) {
9208 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009209 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009210 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +05309211 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009212 } else {
9213 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009214 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009215 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309216 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009217 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009218 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009219 /* if a key is already installed, block all subsequent ones */
9220 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009221 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009222 return 0;
9223 }
9224
9225 setKey.keyDirection = eSIR_TX_RX;
9226 /*Set the group key */
9227 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9228 pAdapter->sessionId, &setKey, &roamId);
9229
9230 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009231 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009232 return -EINVAL;
9233 }
9234 /*Save the keys here and call sme_roam_set_key for setting
9235 the PTK after peer joins the IBSS network */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309236 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009237 &setKey, sizeof(tCsrRoamSetKey));
9238
9239 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
9240 return status;
9241 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009242 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9243 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009244 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
9245 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -07009246 status = wlansap_set_key_sta(
9247 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309248 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009249 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009250 __LINE__, status);
9251 }
9252 }
9253
9254 /* Save the key in ap ctx for use on START_BASS and restart */
9255 if (pairwise ||
9256 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
9257 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309258 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009259 sizeof(tCsrRoamSetKey));
9260 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309261 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009262 sizeof(tCsrRoamSetKey));
9263
Krunal Sonib4326f22016-03-10 13:05:51 -08009264 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
9265 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009266 hdd_wext_state_t *pWextState =
9267 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9268 hdd_station_ctx_t *pHddStaCtx =
9269 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9270
9271 if (!pairwise) {
9272 /* set group key */
9273 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009274 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009275 __func__, __LINE__);
9276 hdd_perform_roam_set_key_complete(pAdapter);
9277 }
9278 }
9279
9280 pWextState->roamProfile.Keys.KeyLength[key_index] =
9281 (u8) params->key_len;
9282
9283 pWextState->roamProfile.Keys.defaultIndex = key_index;
9284
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309285 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009286 KeyMaterial[key_index][0], params->key,
9287 params->key_len);
9288
9289 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
9290
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009291 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009292 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
9293 setKey.keyDirection);
9294
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009295 /* The supplicant may attempt to set the PTK once pre-authentication
9296 is done. Save the key in the UMAC and include it in the ADD BSS
9297 request */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309298 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009299 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309300 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009301 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009302 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309303 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009304 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009305 return -EINVAL;
9306 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009307
9308 /* issue set key request to SME */
9309 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9310 pAdapter->sessionId, &setKey, &roamId);
9311
9312 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009313 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009314 pHddStaCtx->roam_info.roamingState =
9315 HDD_ROAM_STATE_NONE;
9316 return -EINVAL;
9317 }
9318
9319 /* in case of IBSS as there was no information available about WEP keys during
9320 * IBSS join, group key intialized with NULL key, so re-initialize group key
9321 * with correct value*/
9322 if ((eCSR_BSS_TYPE_START_IBSS ==
9323 pWextState->roamProfile.BSSType)
9324 &&
9325 !((IW_AUTH_KEY_MGMT_802_1X ==
9326 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
9327 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
9328 pHddStaCtx->conn_info.authType)
9329 )
9330 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
9331 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
9332 )
9333 ) {
9334 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +05309335 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009336
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009337 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009338 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
9339 setKey.keyDirection);
9340
9341 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9342 pAdapter->sessionId, &setKey,
9343 &roamId);
9344
9345 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009346 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009347 pHddStaCtx->roam_info.roamingState =
9348 HDD_ROAM_STATE_NONE;
9349 return -EINVAL;
9350 }
9351 }
9352 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309353 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009354 return 0;
9355}
9356
9357static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
9358 struct net_device *ndev,
9359 u8 key_index, bool pairwise,
9360 const u8 *mac_addr,
9361 struct key_params *params)
9362{
9363 int ret;
9364 cds_ssr_protect(__func__);
9365 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
9366 mac_addr, params);
9367 cds_ssr_unprotect(__func__);
9368
9369 return ret;
9370}
9371
9372/*
9373 * FUNCTION: __wlan_hdd_cfg80211_get_key
9374 * This function is used to get the key information
9375 */
9376static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
9377 struct net_device *ndev,
9378 u8 key_index, bool pairwise,
9379 const u8 *mac_addr, void *cookie,
9380 void (*callback)(void *cookie,
9381 struct key_params *)
9382 )
9383{
9384 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9385 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9386 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
9387 struct key_params params;
9388
9389 ENTER();
9390
Anurag Chouhan6d760662016-02-20 16:05:43 +05309391 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009392 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009393 return -EINVAL;
9394 }
9395
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009396 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009397 hdd_device_mode_to_string(pAdapter->device_mode),
9398 pAdapter->device_mode);
9399
9400 memset(&params, 0, sizeof(params));
9401
9402 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009403 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009404 key_index);
9405 return -EINVAL;
9406 }
9407
9408 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
9409 case eCSR_ENCRYPT_TYPE_NONE:
9410 params.cipher = IW_AUTH_CIPHER_NONE;
9411 break;
9412
9413 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
9414 case eCSR_ENCRYPT_TYPE_WEP40:
9415 params.cipher = WLAN_CIPHER_SUITE_WEP40;
9416 break;
9417
9418 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
9419 case eCSR_ENCRYPT_TYPE_WEP104:
9420 params.cipher = WLAN_CIPHER_SUITE_WEP104;
9421 break;
9422
9423 case eCSR_ENCRYPT_TYPE_TKIP:
9424 params.cipher = WLAN_CIPHER_SUITE_TKIP;
9425 break;
9426
9427 case eCSR_ENCRYPT_TYPE_AES:
9428 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
9429 break;
9430
9431 default:
9432 params.cipher = IW_AUTH_CIPHER_NONE;
9433 break;
9434 }
9435
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309436 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009437 TRACE_CODE_HDD_CFG80211_GET_KEY,
9438 pAdapter->sessionId, params.cipher));
9439
9440 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
9441 params.seq_len = 0;
9442 params.seq = NULL;
9443 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
9444 callback(cookie, &params);
9445
9446 EXIT();
9447 return 0;
9448}
9449
9450static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
9451 struct net_device *ndev,
9452 u8 key_index, bool pairwise,
9453 const u8 *mac_addr, void *cookie,
9454 void (*callback)(void *cookie,
9455 struct key_params *)
9456 )
9457{
9458 int ret;
9459
9460 cds_ssr_protect(__func__);
9461 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
9462 mac_addr, cookie, callback);
9463 cds_ssr_unprotect(__func__);
9464
9465 return ret;
9466}
9467
9468/**
9469 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
9470 * @wiphy: wiphy interface context
9471 * @ndev: pointer to net device
9472 * @key_index: Key index used in 802.11 frames
9473 * @unicast: true if it is unicast key
9474 * @multicast: true if it is multicast key
9475 *
9476 * This function is required for cfg80211_ops API.
9477 * It is used to delete the key information
9478 * Underlying hardware implementation does not have API to delete the
9479 * encryption key. It is automatically deleted when the peer is
9480 * removed. Hence this function currently does nothing.
9481 * Future implementation may interprete delete key operation to
9482 * replacing the key with a random junk value, effectively making it
9483 * useless.
9484 *
9485 * Return: status code, always 0.
9486 */
9487
9488static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
9489 struct net_device *ndev,
9490 u8 key_index,
9491 bool pairwise, const u8 *mac_addr)
9492{
9493 EXIT();
9494 return 0;
9495}
9496
9497/**
9498 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
9499 * @wiphy: Pointer to wiphy structure.
9500 * @dev: Pointer to net_device structure.
9501 * @key_index: key index
9502 * @pairwise: pairwise
9503 * @mac_addr: mac address
9504 *
9505 * This is the cfg80211 delete key handler function which invokes
9506 * the internal function @__wlan_hdd_cfg80211_del_key with
9507 * SSR protection.
9508 *
9509 * Return: 0 for success, error number on failure.
9510 */
9511static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
9512 struct net_device *dev,
9513 u8 key_index,
9514 bool pairwise, const u8 *mac_addr)
9515{
9516 int ret;
9517
9518 cds_ssr_protect(__func__);
9519 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
9520 pairwise, mac_addr);
9521 cds_ssr_unprotect(__func__);
9522
9523 return ret;
9524}
9525
9526/*
9527 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
9528 * This function is used to set the default tx key index
9529 */
9530static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
9531 struct net_device *ndev,
9532 u8 key_index,
9533 bool unicast, bool multicast)
9534{
9535 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9536 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9537 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9538 hdd_context_t *pHddCtx;
9539 int status;
9540
9541 ENTER();
9542
Anurag Chouhan6d760662016-02-20 16:05:43 +05309543 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009544 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009545 return -EINVAL;
9546 }
9547
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309548 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009549 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
9550 pAdapter->sessionId, key_index));
9551
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009552 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009553 hdd_device_mode_to_string(pAdapter->device_mode),
9554 pAdapter->device_mode, key_index);
9555
9556 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009557 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009558 return -EINVAL;
9559 }
9560
9561 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9562 status = wlan_hdd_validate_context(pHddCtx);
9563
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309564 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009565 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009566
Krunal Sonib4326f22016-03-10 13:05:51 -08009567 if ((pAdapter->device_mode == QDF_STA_MODE) ||
9568 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009569 if ((eCSR_ENCRYPT_TYPE_TKIP !=
9570 pHddStaCtx->conn_info.ucEncryptionType) &&
9571 (eCSR_ENCRYPT_TYPE_AES !=
9572 pHddStaCtx->conn_info.ucEncryptionType)) {
9573 /* If default key index is not same as previous one,
9574 * then update the default key index */
9575
9576 tCsrRoamSetKey setKey;
9577 uint32_t roamId = 0xFF;
9578 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
9579
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009580 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009581
9582 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309583 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009584 setKey.keyId = key_index;
9585 setKey.keyLength = Keys->KeyLength[key_index];
9586
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309587 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009588 &Keys->KeyMaterial[key_index][0],
9589 Keys->KeyLength[key_index]);
9590
9591 setKey.keyDirection = eSIR_TX_RX;
9592
Anurag Chouhanc5548422016-02-24 18:33:27 +05309593 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009594 &pHddStaCtx->conn_info.bssId);
9595
9596 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
9597 pWextState->roamProfile.EncryptionType.
9598 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
9599 /* In the case of dynamic wep supplicant hardcodes DWEP type
9600 * to eCSR_ENCRYPT_TYPE_WEP104 even though ap is configured for
9601 * WEP-40 encryption. In this canse the key length is 5 but the
9602 * encryption type is 104 hence checking the key langht(5) and
9603 * encryption type(104) and switching encryption type to 40*/
9604 pWextState->roamProfile.EncryptionType.
9605 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
9606 pWextState->roamProfile.mcEncryptionType.
9607 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
9608 }
9609
9610 setKey.encType =
9611 pWextState->roamProfile.EncryptionType.
9612 encryptionType[0];
9613
9614 /* Issue set key request */
9615 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9616 pAdapter->sessionId, &setKey,
9617 &roamId);
9618
9619 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009620 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009621 status);
9622 return -EINVAL;
9623 }
9624 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009625 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009626 /* In SoftAp mode setting key direction for default mode */
9627 if ((eCSR_ENCRYPT_TYPE_TKIP !=
9628 pWextState->roamProfile.EncryptionType.encryptionType[0])
9629 && (eCSR_ENCRYPT_TYPE_AES !=
9630 pWextState->roamProfile.EncryptionType.
9631 encryptionType[0])) {
9632 /* Saving key direction for default key index to TX default */
9633 hdd_ap_ctx_t *pAPCtx =
9634 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
9635 pAPCtx->wepKey[key_index].keyDirection =
9636 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +05309637 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +05309638 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +05309639 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009640 }
9641 }
9642
9643 EXIT();
9644 return status;
9645}
9646
9647static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
9648 struct net_device *ndev,
9649 u8 key_index,
9650 bool unicast, bool multicast)
9651{
9652 int ret;
9653 cds_ssr_protect(__func__);
9654 ret =
9655 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
9656 multicast);
9657 cds_ssr_unprotect(__func__);
9658
9659 return ret;
9660}
9661
9662/**
9663 * wlan_hdd_cfg80211_update_bss_list() - update bss list to NL80211
9664 * @pAdapter: Pointer to adapter
9665 * @pRoamInfo: Pointer to roam info
9666 *
9667 * Return: struct cfg80211_bss pointer
9668 */
9669struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(hdd_adapter_t *pAdapter,
9670 tCsrRoamInfo *pRoamInfo)
9671{
9672 struct net_device *dev = pAdapter->dev;
9673 struct wireless_dev *wdev = dev->ieee80211_ptr;
9674 struct wiphy *wiphy = wdev->wiphy;
9675 tSirBssDescription *pBssDesc = pRoamInfo->pBssDesc;
9676 int chan_no;
9677 unsigned int freq;
9678 struct ieee80211_channel *chan;
9679 struct cfg80211_bss *bss = NULL;
9680
9681 ENTER();
9682
9683 if (NULL == pBssDesc) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009684 hdd_err("pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009685 return bss;
9686 }
9687
9688 if (NULL == pRoamInfo->pProfile) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009689 hdd_err("Roam profile is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009690 return bss;
9691 }
9692
9693 chan_no = pBssDesc->channelId;
9694
9695 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz)) {
9696 freq =
9697 ieee80211_channel_to_frequency(chan_no,
9698 IEEE80211_BAND_2GHZ);
9699 } else {
9700 freq =
9701 ieee80211_channel_to_frequency(chan_no,
9702 IEEE80211_BAND_5GHZ);
9703 }
9704
9705 chan = __ieee80211_get_channel(wiphy, freq);
9706
9707 if (!chan) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009708 hdd_err("chan pointer is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009709 return NULL;
9710 }
9711
9712 bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
9713 &pRoamInfo->pProfile->SSIDs.SSIDList->SSID.
9714 ssId[0],
9715 pRoamInfo->pProfile->SSIDs.SSIDList->SSID.length,
Ryan Hsu535d16a2016-01-18 16:45:12 -08009716#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009717 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
Ryan Hsu535d16a2016-01-18 16:45:12 -08009718#else
9719 IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY);
9720#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009721 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009722 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009723 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009724 hdd_notice("cfg80211_unlink_bss called for BSSID "
9725 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009726 MAC_ADDR_ARRAY(pBssDesc->bssId));
9727 cfg80211_unlink_bss(wiphy, bss);
9728 }
9729 return bss;
9730}
9731
9732/**
9733 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
9734 * @pAdapter: Pointer to adapter
9735 * @bss_desc: Pointer to bss descriptor
9736 *
9737 * This function is used to inform the BSS details to nl80211 interface.
9738 *
9739 * Return: struct cfg80211_bss pointer
9740 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +05309741struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
9742 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009743{
9744 /*
9745 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
9746 * already exists in bss data base of cfg80211 for that particular BSS
9747 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
9748 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
9749 * As of now there is no possibility to get the mgmt(probe response)
9750 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
9751 * and passing to cfg80211_inform_bss_frame.
9752 */
9753 struct net_device *dev = pAdapter->dev;
9754 struct wireless_dev *wdev = dev->ieee80211_ptr;
9755 struct wiphy *wiphy = wdev->wiphy;
9756 int chan_no = bss_desc->channelId;
9757#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
9758 qcom_ie_age *qie_age = NULL;
9759 int ie_length =
9760 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
9761#else
9762 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
9763#endif
9764 const char *ie =
9765 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
9766 unsigned int freq;
9767 struct ieee80211_channel *chan;
9768 struct ieee80211_mgmt *mgmt = NULL;
9769 struct cfg80211_bss *bss_status = NULL;
9770 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
9771 int rssi = 0;
9772 hdd_context_t *pHddCtx;
9773 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009774 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07009775 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009776
9777 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9778 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309779 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009780 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009781
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07009782 cfg_param = pHddCtx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009783 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
9784 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009785 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009786 return NULL;
9787 }
9788
9789 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
9790
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009791 /* Android does not want the timestamp from the frame.
9792 Instead it wants a monotonic increasing value */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -07009793 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009794 mgmt->u.probe_resp.timestamp =
9795 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009796
9797 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
9798 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
9799
9800#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
9801 /* GPS Requirement: need age ie per entry. Using vendor specific. */
9802 /* Assuming this is the last IE, copy at the end */
9803 ie_length -= sizeof(qcom_ie_age);
9804 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
9805 qie_age->element_id = QCOM_VENDOR_IE_ID;
9806 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
9807 qie_age->oui_1 = QCOM_OUI1;
9808 qie_age->oui_2 = QCOM_OUI2;
9809 qie_age->oui_3 = QCOM_OUI3;
9810 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
9811 qie_age->age =
Anurag Chouhan210db072016-02-22 18:42:15 +05309812 qdf_mc_timer_get_system_ticks() - bss_desc->nReceivedTime;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009813 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -07009814 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
9815 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -07009816 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
9817 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009818#endif
9819
9820 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
9821 if (bss_desc->fProbeRsp) {
9822 mgmt->frame_control |=
9823 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
9824 } else {
9825 mgmt->frame_control |=
9826 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
9827 }
9828
9829 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
9830 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL)) {
9831 freq =
9832 ieee80211_channel_to_frequency(chan_no,
9833 IEEE80211_BAND_2GHZ);
9834 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
9835 && (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL)) {
9836 freq =
9837 ieee80211_channel_to_frequency(chan_no,
9838 IEEE80211_BAND_5GHZ);
9839 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009840 hdd_err("Invalid chan_no %d", chan_no);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009841 kfree(mgmt);
9842 return NULL;
9843 }
9844
9845 chan = __ieee80211_get_channel(wiphy, freq);
9846 /* When the band is changed on the fly using the GUI, three things are done
9847 * 1. scan abort
9848 * 2. flush scan results from cache
9849 * 3. update the band with the new band user specified (refer to the
9850 * hdd_set_band_helper function) as part of the scan abort, message will be
9851 * queued to PE and we proceed with flushing and changinh the band.
9852 * PE will stop the scanning further and report back the results what ever
9853 * it had till now by calling the call back function.
9854 * if the time between update band and scandone call back is sufficient
9855 * enough the band change reflects in SME, SME validates the channels
9856 * and discards the channels correponding to previous band and calls back
9857 * with zero bss results. but if the time between band update and scan done
9858 * callback is very small then band change will not reflect in SME and SME
9859 * reports to HDD all the channels correponding to previous band.this is due
9860 * to race condition.but those channels are invalid to the new band and so
9861 * this function __ieee80211_get_channel will return NULL.Each time we
9862 * report scan result with this pointer null warning kernel trace is printed.
9863 * if the scan results contain large number of APs continuosly kernel
9864 * warning trace is printed and it will lead to apps watch dog bark.
9865 * So drop the bss and continue to next bss.
9866 */
9867 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +05309868 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
9869 chan_no, freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009870 kfree(mgmt);
9871 return NULL;
9872 }
9873
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -07009874 /* Based on .ini configuration, raw rssi can be reported for bss.
9875 * Raw rssi is typically used for estimating power.
9876 */
9877
9878 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
9879 bss_desc->rssi;
9880
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009881 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +05309882 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009883
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009884 hdd_notice("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009885 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -07009886 (int)(rssi / 100),
9887 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009888
9889 bss_status =
9890 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
9891 GFP_KERNEL);
9892 kfree(mgmt);
9893 return bss_status;
9894}
9895
9896/**
9897 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
9898 * @pAdapter: Pointer to adapter
9899 * @pRoamInfo: Pointer to roam info
9900 *
9901 * This function is used to update the BSS data base of CFG8011
9902 *
9903 * Return: struct cfg80211_bss pointer
9904 */
9905struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
9906 tCsrRoamInfo *pRoamInfo)
9907{
9908 tCsrRoamConnectedProfile roamProfile;
9909 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9910 struct cfg80211_bss *bss = NULL;
9911
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009912 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
9913 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
9914
9915 if (NULL != roamProfile.pBssDesc) {
9916 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
9917 roamProfile.pBssDesc);
9918
9919 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009920 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009921
Naveen Rawatdf0a7e72016-01-06 18:35:53 -08009922 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009923 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009924 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009925 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009926 return bss;
9927}
9928/**
9929 * wlan_hdd_cfg80211_update_bss() - update bss
9930 * @wiphy: Pointer to wiphy
9931 * @pAdapter: Pointer to adapter
9932 * @scan_time: scan request timestamp
9933 *
9934 * Return: zero if success, non-zero otherwise
9935 */
9936int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
9937 hdd_adapter_t *pAdapter,
9938 uint32_t scan_time)
9939{
9940 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9941 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309942 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009943 tScanResultHandle pResult;
9944 struct cfg80211_bss *bss_status = NULL;
9945 hdd_context_t *pHddCtx;
9946 int ret;
9947
9948 ENTER();
9949
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309950 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009951 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
9952 NO_SESSION, pAdapter->sessionId));
9953
9954 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9955 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309956 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009957 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009958
9959 /* start getting scan results and populate cgf80211 BSS database */
9960 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
9961
9962 /* no scan results */
9963 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009964 hdd_err("No scan result Status %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009965 return status;
9966 }
9967
9968 pScanResult = sme_scan_result_get_first(hHal, pResult);
9969
9970 while (pScanResult) {
9971 /*
9972 * - cfg80211_inform_bss() is not updating ie field of bss
9973 * entry if entry already exists in bss data base of cfg80211
9974 * for that particular BSS ID. Using cfg80211_inform_bss_frame
9975 * to update thebss entry instead of cfg80211_inform_bss,
9976 * But this call expects mgmt packet as input. As of now
9977 * there is no possibility to get the mgmt(probe response)
9978 * frame from PE, converting bss_desc to
9979 * ieee80211_mgmt(probe response) and passing to c
9980 * fg80211_inform_bss_frame.
9981 * - Update BSS only if beacon timestamp is later than
9982 * scan request timestamp.
9983 */
9984 if ((scan_time == 0) ||
9985 (scan_time <
9986 pScanResult->BssDescriptor.nReceivedTime)) {
9987 bss_status =
9988 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
9989 &pScanResult->BssDescriptor);
9990
9991 if (NULL == bss_status) {
9992 hdd_info("NULL returned by cfg80211_inform_bss_frame");
9993 } else {
9994 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009995 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009996 bss_status);
9997 }
9998 } else {
9999 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
10000 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
10001 }
10002 pScanResult = sme_scan_result_get_next(hHal, pResult);
10003 }
10004
10005 sme_scan_result_purge(hHal, pResult);
10006 /*
10007 * For SAP mode, scan is invoked by hostapd during SAP start
10008 * if hostapd is restarted, we need to flush previous scan
10009 * result so that it will reflect environment change
10010 */
Krunal Sonib4326f22016-03-10 13:05:51 -080010011 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010012#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
10013 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
10014#endif
10015 )
10016 sme_scan_flush_result(hHal);
10017
10018 EXIT();
10019 return 0;
10020}
10021
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010022/**
10023 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
10024 * @pAdapter: Pointer to adapter
10025 * @pRoamInfo: Pointer to roam info
10026 * @index: Index
10027 * @preauth: Preauth flag
10028 *
10029 * This function is used to notify the supplicant of a new PMKSA candidate.
10030 *
10031 * Return: 0 for success, non-zero for failure
10032 */
10033int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
10034 tCsrRoamInfo *pRoamInfo,
10035 int index, bool preauth)
10036{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010037 struct net_device *dev = pAdapter->dev;
10038 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
10039
10040 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010041 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010042
10043 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010044 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010045 return -EINVAL;
10046 }
10047
10048 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010049 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010050 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
10051 cfg80211_pmksa_candidate_notify(dev, index,
10052 pRoamInfo->bssid.bytes,
10053 preauth, GFP_KERNEL);
10054 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010055 return 0;
10056}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010057
10058#ifdef FEATURE_WLAN_LFR_METRICS
10059/**
10060 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
10061 * @pAdapter: Pointer to adapter
10062 * @pRoamInfo: Pointer to roam info
10063 *
10064 * 802.11r/LFR metrics reporting function to report preauth initiation
10065 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010066 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010067 */
10068#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010069QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010070 tCsrRoamInfo *pRoamInfo)
10071{
10072 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10073 union iwreq_data wrqu;
10074
10075 ENTER();
10076
10077 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010078 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010079 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010080 }
10081
10082 /* create the event */
10083 memset(&wrqu, 0, sizeof(wrqu));
10084 memset(metrics_notification, 0, sizeof(metrics_notification));
10085
10086 wrqu.data.pointer = metrics_notification;
10087 wrqu.data.length = scnprintf(metrics_notification,
10088 sizeof(metrics_notification),
10089 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
10090 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10091
10092 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10093 metrics_notification);
10094
10095 EXIT();
10096
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010097 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010098}
10099
10100/**
10101 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
10102 * @pAdapter: Pointer to adapter
10103 * @pRoamInfo: Pointer to roam info
10104 * @preauth_status: Preauth status
10105 *
10106 * 802.11r/LFR metrics reporting function to report handover initiation
10107 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010108 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010109 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010110QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010111wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
10112 tCsrRoamInfo *pRoamInfo,
10113 bool preauth_status)
10114{
10115 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10116 union iwreq_data wrqu;
10117
10118 ENTER();
10119
10120 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010121 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010122 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010123 }
10124
10125 /* create the event */
10126 memset(&wrqu, 0, sizeof(wrqu));
10127 memset(metrics_notification, 0, sizeof(metrics_notification));
10128
10129 scnprintf(metrics_notification, sizeof(metrics_notification),
10130 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
10131 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10132
10133 if (1 == preauth_status)
10134 strlcat(metrics_notification, " true",
10135 sizeof(metrics_notification));
10136 else
10137 strlcat(metrics_notification, " false",
10138 sizeof(metrics_notification));
10139
10140 wrqu.data.pointer = metrics_notification;
10141 wrqu.data.length = strlen(metrics_notification);
10142
10143 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10144 metrics_notification);
10145
10146 EXIT();
10147
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010148 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010149}
10150
10151/**
10152 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
10153 * @pAdapter: Pointer to adapter
10154 * @pRoamInfo: Pointer to roam info
10155 *
10156 * 802.11r/LFR metrics reporting function to report handover initiation
10157 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010158 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010159 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010160QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010161 tCsrRoamInfo *pRoamInfo)
10162{
10163 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10164 union iwreq_data wrqu;
10165
10166 ENTER();
10167
10168 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010169 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010170 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010171 }
10172
10173 /* create the event */
10174 memset(&wrqu, 0, sizeof(wrqu));
10175 memset(metrics_notification, 0, sizeof(metrics_notification));
10176
10177 wrqu.data.pointer = metrics_notification;
10178 wrqu.data.length = scnprintf(metrics_notification,
10179 sizeof(metrics_notification),
10180 "QCOM: LFR_PREAUTH_HANDOVER "
10181 MAC_ADDRESS_STR,
10182 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10183
10184 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10185 metrics_notification);
10186
10187 EXIT();
10188
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010189 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010190}
10191#endif
10192
10193/**
10194 * hdd_select_cbmode() - select channel bonding mode
10195 * @pAdapter: Pointer to adapter
10196 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010197 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010198 *
10199 * Return: none
10200 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010201void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
10202 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010203{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010204 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010205 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070010206 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010207
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070010208 /*
10209 * CDS api expects secondary channel for calculating
10210 * the channel params
10211 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010212 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070010213 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
10214 if (operationChannel >= 1 && operationChannel <= 5)
10215 sec_ch = operationChannel + 4;
10216 else if (operationChannel >= 6 && operationChannel <= 13)
10217 sec_ch = operationChannel - 4;
10218 }
10219
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010220 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010221 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010222
10223 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010224 eHddDot11Mode hdd_dot11_mode;
10225 uint8_t iniDot11Mode =
10226 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
10227
10228 hdd_notice("Dot11Mode is %u", iniDot11Mode);
10229 switch (iniDot11Mode) {
10230 case eHDD_DOT11_MODE_AUTO:
10231 case eHDD_DOT11_MODE_11ac:
10232 case eHDD_DOT11_MODE_11ac_ONLY:
10233 if (sme_is_feature_supported_by_fw(DOT11AC))
10234 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
10235 else
10236 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
10237 break;
10238 case eHDD_DOT11_MODE_11n:
10239 case eHDD_DOT11_MODE_11n_ONLY:
10240 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
10241 break;
10242 default:
10243 hdd_dot11_mode = iniDot11Mode;
10244 break;
10245 }
10246 ch_info->channel_width = ch_params->ch_width;
10247 ch_info->phy_mode =
10248 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010249 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010250 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010251 hdd_info("ch_info width %d, phymode %d channel %d",
10252 ch_info->channel_width, ch_info->phy_mode,
10253 ch_info->channel);
10254 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010255}
10256
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070010257/**
10258 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
10259 * @adapter: STA adapter
10260 * @roam_profile: STA roam profile
10261 *
10262 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
10263 *
10264 * Return: false if sta-sap conc is not allowed, else return true
10265 */
10266static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
10267 tCsrRoamProfile *roam_profile)
10268{
10269 hdd_context_t *hdd_ctx;
10270 hdd_adapter_t *ap_adapter;
10271 hdd_ap_ctx_t *hdd_ap_ctx;
10272 hdd_hostapd_state_t *hostapd_state;
10273 uint8_t channel = 0;
10274 QDF_STATUS status;
10275
10276 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
10277 if (!hdd_ctx) {
10278 hdd_err("HDD context is NULL");
10279 return true;
10280 }
10281
10282 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
10283 /* probably no sap running, no handling required */
10284 if (ap_adapter == NULL)
10285 return true;
10286
10287 /*
10288 * sap is not in started state, so it is fine to go ahead with sta.
10289 * if sap is currently doing CAC then don't allow sta to go further.
10290 */
10291 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
10292 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
10293 return true;
10294
10295 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
10296 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
10297 return false;
10298 }
10299
10300 /*
10301 * log and return error, if we allow STA to go through, we don't
10302 * know what is going to happen better stop sta connection
10303 */
10304 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
10305 if (NULL == hdd_ap_ctx) {
10306 hdd_err("AP context not found");
10307 return false;
10308 }
10309
10310 /* sap is on non-dfs channel, nothing to handle */
10311 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
10312 hdd_info("sap is on non-dfs channel, sta is allowed");
10313 return true;
10314 }
10315 /*
10316 * find out by looking in to scan cache where sta is going to
10317 * connect by passing its roam_profile. if channel is 0 or DFS then
10318 * better to call pcl and find out the best channel. if channel
10319 * is non-dfs then better move SAP to STA's channel to make
10320 * scc, so we have room for 3port MCC scenario
10321 */
10322 status = cds_get_channel_from_scan_result(adapter,
10323 roam_profile, &channel);
10324
10325 if ((QDF_STATUS_SUCCESS != status) || (0 == channel) ||
10326 CDS_IS_DFS_CH(channel))
10327 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
10328 true);
10329
10330 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
10331 qdf_event_reset(&hostapd_state->qdf_event);
10332 status = wlansap_set_channel_change_with_csa(
10333 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
10334 hdd_ap_ctx->sapConfig.ch_width_orig);
10335
10336 if (QDF_STATUS_SUCCESS != status) {
10337 hdd_err("Set channel with CSA IE failed, can't allow STA");
10338 return false;
10339 }
10340
10341 /*
10342 * wait here for SAP to finish the channel switch. When channel
10343 * switch happens, SAP sends few beacons with CSA_IE. After
10344 * successfully Transmission of those beacons, it will move its
10345 * state from started to disconnected and move to new channel.
10346 * once it moves to new channel, sap again moves its state
10347 * machine from disconnected to started and set this event.
10348 * wait for 10 secs to finish this.
10349 */
10350 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
10351 if (!QDF_IS_STATUS_SUCCESS(status)) {
10352 hdd_err("wait for qdf_event failed, STA not allowed!!");
10353 return false;
10354 }
10355
10356 return true;
10357}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010358
Krunal Soni31949422016-07-29 17:17:53 -070010359/**
10360 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010361 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070010362 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010363 * @ssid_len: Length of ssid
10364 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070010365 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010366 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010367 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010368 *
10369 * This function is used to start the association process
10370 *
10371 * Return: 0 for success, non-zero for failure
10372 */
Krunal Soni31949422016-07-29 17:17:53 -070010373static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010374 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070010375 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010376 u8 operatingChannel,
10377 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010378{
10379 int status = 0;
10380 hdd_wext_state_t *pWextState;
10381 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053010382 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010383 uint32_t roamId;
10384 tCsrRoamProfile *pRoamProfile;
10385 eCsrAuthType RSNAuthType;
10386 tSmeConfigParams *sme_config;
10387
10388 ENTER();
10389
10390 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10391 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053010392 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010393
10394 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010395 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010396 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010397
10398 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010399 hdd_err("wrong SSID len");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010400 return -EINVAL;
10401 }
10402
10403 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053010404 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
10405 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010406
10407 if (pRoamProfile) {
10408 hdd_station_ctx_t *pHddStaCtx;
10409 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10410
10411 if (HDD_WMM_USER_MODE_NO_QOS ==
10412 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
10413 /*QoS not enabled in cfg file */
10414 pRoamProfile->uapsd_mask = 0;
10415 } else {
10416 /*QoS enabled, update uapsd mask from cfg file */
10417 pRoamProfile->uapsd_mask =
10418 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
10419 }
10420
10421 pRoamProfile->SSIDs.numOfSSIDs = 1;
10422 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010423 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010424 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010425 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010426 ssid, ssid_len);
10427
10428 if (bssid) {
10429 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010430 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053010431 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070010432 /*
10433 * Save BSSID in seperate variable as
10434 * pRoamProfile's BSSID is getting zeroed out in the
10435 * association process. In case of join failure
10436 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010437 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010438 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053010439 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070010440 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010441 } else if (bssid_hint) {
10442 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010443 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053010444 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070010445 /*
10446 * Save BSSID in a separate variable as
10447 * pRoamProfile's BSSID is getting zeroed out in the
10448 * association process. In case of join failure
10449 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010450 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010451 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053010452 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070010453 hdd_info("bssid_hint is given by upper layer %pM",
10454 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010455 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010456 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053010457 QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070010458 hdd_info("no bssid given by upper layer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010459 }
10460
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010461 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010462 pRoamProfile->SSIDs.SSIDList->SSID.length,
10463 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
10464 operatingChannel);
10465
10466 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
10467 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010468 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010469 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
10470 }
10471#ifdef FEATURE_WLAN_WAPI
10472 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010473 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010474 switch (pAdapter->wapi_info.wapiAuthMode) {
10475 case WAPI_AUTH_MODE_PSK:
10476 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010477 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010478 pAdapter->wapi_info.wapiAuthMode);
10479 pRoamProfile->AuthType.authType[0] =
10480 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
10481 break;
10482 }
10483 case WAPI_AUTH_MODE_CERT:
10484 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010485 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010486 pAdapter->wapi_info.wapiAuthMode);
10487 pRoamProfile->AuthType.authType[0] =
10488 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
10489 break;
10490 }
10491 } /* End of switch */
10492 if (pAdapter->wapi_info.wapiAuthMode ==
10493 WAPI_AUTH_MODE_PSK
10494 || pAdapter->wapi_info.wapiAuthMode ==
10495 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010496 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010497 pRoamProfile->AuthType.numEntries = 1;
10498 pRoamProfile->EncryptionType.numEntries = 1;
10499 pRoamProfile->EncryptionType.encryptionType[0] =
10500 eCSR_ENCRYPT_TYPE_WPI;
10501 pRoamProfile->mcEncryptionType.numEntries = 1;
10502 pRoamProfile->mcEncryptionType.
10503 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
10504 }
10505 }
Krunal Soni31949422016-07-29 17:17:53 -070010506#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010507#ifdef WLAN_FEATURE_GTK_OFFLOAD
10508 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080010509 if ((QDF_STA_MODE == pAdapter->device_mode) ||
10510 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010511 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
10512 sizeof(tSirGtkOffloadParams));
10513 pHddStaCtx->gtkOffloadReqParams.ulFlags =
10514 GTK_OFFLOAD_DISABLE;
10515 }
10516#endif
10517 pRoamProfile->csrPersona = pAdapter->device_mode;
10518
10519 if (operatingChannel) {
10520 pRoamProfile->ChannelInfo.ChannelList =
10521 &operatingChannel;
10522 pRoamProfile->ChannelInfo.numOfChannels = 1;
10523 } else {
10524 pRoamProfile->ChannelInfo.ChannelList = NULL;
10525 pRoamProfile->ChannelInfo.numOfChannels = 0;
10526 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010527 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010528 && operatingChannel) {
10529 /*
10530 * Need to post the IBSS power save parameters
10531 * to WMA. WMA will configure this parameters
10532 * to firmware if power save is enabled by the
10533 * firmware.
10534 */
10535 status = hdd_set_ibss_power_save_params(pAdapter);
10536
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010537 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010538 hdd_err("Set IBSS Power Save Params Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010539 return -EINVAL;
10540 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010541 pRoamProfile->ch_params.ch_width =
10542 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053010543 /*
10544 * In IBSS mode while operating in 2.4 GHz,
10545 * the device supports only 20 MHz.
10546 */
10547 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
10548 pRoamProfile->ch_params.ch_width =
10549 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010550 hdd_select_cbmode(pAdapter, operatingChannel,
10551 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010552 }
Abhishek Singh99bce862016-06-20 15:10:51 +053010553 /*
10554 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
10555 * or pmf=2 is an explicit configuration in the supplicant
10556 * configuration, drop the connection request.
10557 */
10558 if (pWextState->roamProfile.MFPEnabled &&
10559 !(pWextState->roamProfile.MFPRequired ||
10560 pWextState->roamProfile.MFPCapable)) {
10561 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
10562 pWextState->roamProfile.MFPEnabled,
10563 pWextState->roamProfile.MFPRequired,
10564 pWextState->roamProfile.MFPCapable);
10565 return -EINVAL;
10566 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010567
Krunal Soni3091bcc2016-06-23 12:28:21 -070010568 if (true == cds_is_connection_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010569 hdd_err("Connection refused: conn in progress");
10570 return -EINVAL;
10571 }
10572
Krunal Soni31949422016-07-29 17:17:53 -070010573 /*
10574 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010575 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070010576 * enhancements, the supplicant is not issuing the scan command
10577 * now. So the unicast frames which are sent from the host are
10578 * not having the additional IEs. If it is P2P CLIENT and there
10579 * is no additional IE present in roamProfile, then use the
10580 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010581 */
10582
Krunal Sonib4326f22016-03-10 13:05:51 -080010583 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010584 (!pRoamProfile->pAddIEScan)) {
10585 pRoamProfile->pAddIEScan =
10586 &pAdapter->scan_info.scanAddIE.addIEdata[0];
10587 pRoamProfile->nAddIEScanLength =
10588 pAdapter->scan_info.scanAddIE.length;
10589 }
10590 /*
10591 * When policy manager is enabled from ini file, we shouldn't
10592 * check for other concurrency rules.
10593 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070010594 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080010595 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080010596 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010597 pAdapter, pRoamProfile, &roamId))
10598 return 0;
10599 }
10600
Krunal Soni3091bcc2016-06-23 12:28:21 -070010601 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070010602 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
10603 pRoamProfile))) {
10604 hdd_err("sap-sta conc will fail, can't allow sta");
10605 hdd_conn_set_connection_state(pAdapter,
10606 eConnectionState_NotConnected);
10607 return -ENOMEM;
10608 }
10609
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010610 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010611 if (!sme_config) {
10612 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070010613 hdd_conn_set_connection_state(pAdapter,
10614 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010615 return -ENOMEM;
10616 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010617 qdf_mem_zero(sme_config, sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010618 sme_get_config_param(pHddCtx->hHal, sme_config);
10619 /* These values are not sessionized. So, any change in these SME
10620 * configs on an older or parallel interface will affect the
10621 * cb mode. So, restoring the default INI params before starting
10622 * interfaces such as sta, cli etc.,
10623 */
10624 sme_config->csrConfig.channelBondingMode5GHz =
10625 pHddCtx->config->nChannelBondingMode5GHz;
10626 sme_config->csrConfig.channelBondingMode24GHz =
10627 pHddCtx->config->nChannelBondingMode24GHz;
10628 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010629 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053010630 /*
10631 * Change conn_state to connecting before sme_roam_connect(),
10632 * because sme_roam_connect() has a direct path to call
10633 * hdd_sme_roam_callback(), which will change the conn_state
10634 * If direct path, conn_state will be accordingly changed to
10635 * NotConnected or Associated by either
10636 * hdd_association_completion_handler() or
10637 * hdd_dis_connect_handler() in sme_RoamCallback()if
10638 * sme_RomConnect is to be queued,
10639 * Connecting state will remain until it is completed.
10640 *
10641 * If connection state is not changed, connection state will
10642 * remain in eConnectionState_NotConnected state.
10643 * In hdd_association_completion_handler, "hddDisconInProgress"
10644 * is set to true if conn state is
10645 * eConnectionState_NotConnected.
10646 * If "hddDisconInProgress" is set to true then cfg80211 layer
10647 * is not informed of connect result indication which
10648 * is an issue.
10649 */
10650 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053010651 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053010652 hdd_conn_set_connection_state(pAdapter,
10653 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010654
10655 status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
10656 pAdapter->sessionId, pRoamProfile,
10657 &roamId);
10658
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010659 if ((QDF_STATUS_SUCCESS != status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080010660 (QDF_STA_MODE == pAdapter->device_mode ||
10661 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010662 hdd_err("sme_roam_connect (session %d) failed with "
10663 "status %d. -> NotConnected",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010664 pAdapter->sessionId, status);
10665 /* change back to NotAssociated */
10666 hdd_conn_set_connection_state(pAdapter,
10667 eConnectionState_NotConnected);
10668 }
10669
10670 pRoamProfile->ChannelInfo.ChannelList = NULL;
10671 pRoamProfile->ChannelInfo.numOfChannels = 0;
10672
10673 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010674 hdd_err("No valid Roam profile");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010675 return -EINVAL;
10676 }
10677 EXIT();
10678 return status;
10679}
10680
10681/**
10682 * wlan_hdd_cfg80211_set_auth_type() - set auth type
10683 * @pAdapter: Pointer to adapter
10684 * @auth_type: Auth type
10685 *
10686 * This function is used to set the authentication type (OPEN/SHARED).
10687 *
10688 * Return: 0 for success, non-zero for failure
10689 */
10690static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
10691 enum nl80211_auth_type auth_type)
10692{
10693 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10694 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10695
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010696 /*set authentication type */
10697 switch (auth_type) {
10698 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010699 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010700 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
10701 break;
10702
10703 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010704 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010705 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010706 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
10707 break;
10708
10709 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010710 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010711 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
10712 break;
10713#ifdef FEATURE_WLAN_ESE
10714 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010715 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010716 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
10717 break;
10718#endif
10719
10720 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010721 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010722 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
10723 return -EINVAL;
10724 }
10725
10726 pWextState->roamProfile.AuthType.authType[0] =
10727 pHddStaCtx->conn_info.authType;
10728 return 0;
10729}
10730
10731/**
10732 * wlan_hdd_set_akm_suite() - set key management type
10733 * @pAdapter: Pointer to adapter
10734 * @key_mgmt: Key management type
10735 *
10736 * This function is used to set the key mgmt type(PSK/8021x).
10737 *
10738 * Return: 0 for success, non-zero for failure
10739 */
10740static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
10741{
10742 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10743
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010744#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
10745#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
10746 /*set key mgmt type */
10747 switch (key_mgmt) {
10748 case WLAN_AKM_SUITE_PSK:
10749 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010750 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010751 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010752 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
10753 break;
10754
10755 case WLAN_AKM_SUITE_8021X_SHA256:
10756 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010757 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010758 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010759 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
10760 break;
10761#ifdef FEATURE_WLAN_ESE
10762#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
10763#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
10764 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010765 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010766 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
10767 break;
10768#endif
10769#ifndef WLAN_AKM_SUITE_OSEN
10770#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
10771#endif
10772 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010773 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010774 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
10775 break;
10776
10777 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010778 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010779 return -EINVAL;
10780
10781 }
10782 return 0;
10783}
10784
10785/**
10786 * wlan_hdd_cfg80211_set_cipher() - set encryption type
10787 * @pAdapter: Pointer to adapter
10788 * @cipher: Cipher type
10789 * @ucast: Unicast flag
10790 *
10791 * This function is used to set the encryption type
10792 * (NONE/WEP40/WEP104/TKIP/CCMP).
10793 *
10794 * Return: 0 for success, non-zero for failure
10795 */
10796static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
10797 u32 cipher, bool ucast)
10798{
10799 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
10800 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10801 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10802
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010803 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080010804 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010805 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
10806 } else {
10807
10808 /*set encryption method */
10809 switch (cipher) {
10810 case IW_AUTH_CIPHER_NONE:
10811 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
10812 break;
10813
10814 case WLAN_CIPHER_SUITE_WEP40:
10815 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
10816 break;
10817
10818 case WLAN_CIPHER_SUITE_WEP104:
10819 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
10820 break;
10821
10822 case WLAN_CIPHER_SUITE_TKIP:
10823 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
10824 break;
10825
10826 case WLAN_CIPHER_SUITE_CCMP:
10827 encryptionType = eCSR_ENCRYPT_TYPE_AES;
10828 break;
10829#ifdef FEATURE_WLAN_WAPI
10830 case WLAN_CIPHER_SUITE_SMS4:
10831 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
10832 break;
10833#endif
10834
10835#ifdef FEATURE_WLAN_ESE
10836 case WLAN_CIPHER_SUITE_KRK:
10837 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
10838 break;
10839#ifdef WLAN_FEATURE_ROAM_OFFLOAD
10840 case WLAN_CIPHER_SUITE_BTK:
10841 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
10842 break;
10843#endif
10844#endif
10845 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010846 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010847 return -EOPNOTSUPP;
10848 }
10849 }
10850
10851 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010852 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010853 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
10854 pWextState->roamProfile.EncryptionType.numEntries = 1;
10855 pWextState->roamProfile.EncryptionType.encryptionType[0] =
10856 encryptionType;
10857 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010858 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010859 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
10860 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
10861 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
10862 encryptionType;
10863 }
10864
10865 return 0;
10866}
10867
10868/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053010869 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
10870 * @wext_state: Pointer to wext state
10871 * @gen_ie: Pointer to IE data
10872 * @len: length of IE data
10873 *
10874 * Return: 0 for success, non-zero for failure
10875 */
10876static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
10877 const uint8_t *gen_ie, uint16_t len)
10878{
10879 uint16_t cur_add_ie_len =
10880 wext_state->assocAddIE.length;
10881
10882 if (SIR_MAC_MAX_ADD_IE_LENGTH <
10883 (wext_state->assocAddIE.length + len)) {
10884 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
10885 QDF_ASSERT(0);
10886 return -ENOMEM;
10887 }
10888 memcpy(wext_state->assocAddIE.addIEdata +
10889 cur_add_ie_len, gen_ie, len);
10890 wext_state->assocAddIE.length += len;
10891
10892 wext_state->roamProfile.pAddIEAssoc =
10893 wext_state->assocAddIE.addIEdata;
10894 wext_state->roamProfile.nAddIEAssocLength =
10895 wext_state->assocAddIE.length;
10896 return 0;
10897}
10898
10899/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010900 * wlan_hdd_cfg80211_set_ie() - set IEs
10901 * @pAdapter: Pointer to adapter
10902 * @ie: Pointer ot ie
10903 * @ie: IE length
10904 *
10905 * Return: 0 for success, non-zero for failure
10906 */
10907int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
10908 size_t ie_len)
10909{
10910 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10911 const uint8_t *genie = ie;
10912 uint16_t remLen = ie_len;
10913#ifdef FEATURE_WLAN_WAPI
10914 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
10915 u16 *tmp;
10916 uint16_t akmsuiteCount;
10917 int *akmlist;
10918#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053010919 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010920
10921 /* clear previous assocAddIE */
10922 pWextState->assocAddIE.length = 0;
10923 pWextState->roamProfile.bWPSAssociation = false;
10924 pWextState->roamProfile.bOSENAssociation = false;
10925
10926 while (remLen >= 2) {
10927 uint16_t eLen = 0;
10928 uint8_t elementId;
10929 elementId = *genie++;
10930 eLen = *genie++;
10931 remLen -= 2;
10932
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010933 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010934
10935 switch (elementId) {
10936 case DOT11F_EID_WPA:
10937 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 -070010938 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010939 return -EINVAL;
10940 } else if (0 ==
10941 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
10942 uint16_t curAddIELen =
10943 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010944 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010945
10946 if (SIR_MAC_MAX_ADD_IE_LENGTH <
10947 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010948 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010949 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010950 return -ENOMEM;
10951 }
10952 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
10953 memcpy(pWextState->assocAddIE.addIEdata +
10954 curAddIELen, genie - 2, eLen + 2);
10955 pWextState->assocAddIE.length += eLen + 2;
10956
10957 pWextState->roamProfile.bWPSAssociation = true;
10958 pWextState->roamProfile.pAddIEAssoc =
10959 pWextState->assocAddIE.addIEdata;
10960 pWextState->roamProfile.nAddIEAssocLength =
10961 pWextState->assocAddIE.length;
10962 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010963 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010964 memset(pWextState->WPARSNIE, 0,
10965 MAX_WPA_RSN_IE_LEN);
10966 memcpy(pWextState->WPARSNIE, genie - 2,
10967 (eLen + 2));
10968 pWextState->roamProfile.pWPAReqIE =
10969 pWextState->WPARSNIE;
10970 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
10971 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
10972 P2P_OUI_TYPE_SIZE))) {
10973 uint16_t curAddIELen =
10974 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010975 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010976
10977 if (SIR_MAC_MAX_ADD_IE_LENGTH <
10978 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010979 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010980 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010981 return -ENOMEM;
10982 }
10983 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
10984 memcpy(pWextState->assocAddIE.addIEdata +
10985 curAddIELen, genie - 2, eLen + 2);
10986 pWextState->assocAddIE.length += eLen + 2;
10987
10988 pWextState->roamProfile.pAddIEAssoc =
10989 pWextState->assocAddIE.addIEdata;
10990 pWextState->roamProfile.nAddIEAssocLength =
10991 pWextState->assocAddIE.length;
10992 }
10993#ifdef WLAN_FEATURE_WFD
10994 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
10995 WFD_OUI_TYPE_SIZE)) &&
10996 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080010997 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010998 pAdapter->device_mode)) {
10999 uint16_t curAddIELen =
11000 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011001 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011002
11003 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11004 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011005 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011006 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011007 return -ENOMEM;
11008 }
11009 /* WFD IE is saved to Additional IE ; it should
11010 * be accumulated to handle WPS IE + P2P IE +
11011 * WFD IE */
11012 memcpy(pWextState->assocAddIE.addIEdata +
11013 curAddIELen, genie - 2, eLen + 2);
11014 pWextState->assocAddIE.length += eLen + 2;
11015
11016 pWextState->roamProfile.pAddIEAssoc =
11017 pWextState->assocAddIE.addIEdata;
11018 pWextState->roamProfile.nAddIEAssocLength =
11019 pWextState->assocAddIE.length;
11020 }
11021#endif
11022 /* Appending HS 2.0 Indication Element in Assiciation Request */
11023 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
11024 HS20_OUI_TYPE_SIZE))) {
11025 uint16_t curAddIELen =
11026 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011027 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011028
11029 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11030 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011031 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011032 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011033 return -ENOMEM;
11034 }
11035 memcpy(pWextState->assocAddIE.addIEdata +
11036 curAddIELen, genie - 2, eLen + 2);
11037 pWextState->assocAddIE.length += eLen + 2;
11038
11039 pWextState->roamProfile.pAddIEAssoc =
11040 pWextState->assocAddIE.addIEdata;
11041 pWextState->roamProfile.nAddIEAssocLength =
11042 pWextState->assocAddIE.length;
11043 }
11044 /* Appending OSEN Information Element in Assiciation Request */
11045 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
11046 OSEN_OUI_TYPE_SIZE))) {
11047 uint16_t curAddIELen =
11048 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011049 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011050
11051 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11052 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011053 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011054 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011055 return -ENOMEM;
11056 }
11057 memcpy(pWextState->assocAddIE.addIEdata +
11058 curAddIELen, genie - 2, eLen + 2);
11059 pWextState->assocAddIE.length += eLen + 2;
11060
11061 pWextState->roamProfile.bOSENAssociation = true;
11062 pWextState->roamProfile.pAddIEAssoc =
11063 pWextState->assocAddIE.addIEdata;
11064 pWextState->roamProfile.nAddIEAssocLength =
11065 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011066 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
11067 MBO_OUI_TYPE_SIZE))){
11068 hdd_info("Set MBO IE(len %d)", eLen + 2);
11069 status = wlan_hdd_add_assoc_ie(pWextState,
11070 genie - 2, eLen + 2);
11071 if (status)
11072 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011073 } else {
11074 uint16_t add_ie_len =
11075 pWextState->assocAddIE.length;
11076
11077 hdd_info("Set OSEN IE(len %d)", eLen + 2);
11078
11079 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11080 (pWextState->assocAddIE.length + eLen)) {
11081 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011082 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011083 return -ENOMEM;
11084 }
11085
11086 memcpy(pWextState->assocAddIE.addIEdata +
11087 add_ie_len, genie - 2, eLen + 2);
11088 pWextState->assocAddIE.length += eLen + 2;
11089
11090 pWextState->roamProfile.pAddIEAssoc =
11091 pWextState->assocAddIE.addIEdata;
11092 pWextState->roamProfile.nAddIEAssocLength =
11093 pWextState->assocAddIE.length;
11094 }
11095 break;
11096 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011097 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011098 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
11099 memcpy(pWextState->WPARSNIE, genie - 2,
11100 (eLen + 2));
11101 pWextState->roamProfile.pRSNReqIE =
11102 pWextState->WPARSNIE;
11103 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
11104 break;
11105 /*
11106 * Appending Extended Capabilities with Interworking bit set
11107 * in Assoc Req.
11108 *
11109 * In assoc req this EXT Cap will only be taken into account if
11110 * interworkingService bit is set to 1. Currently
11111 * driver is only interested in interworkingService capability
11112 * from supplicant. If in future any other EXT Cap info is
11113 * required from supplicat, it needs to be handled while
11114 * sending Assoc Req in LIM.
11115 */
11116 case DOT11F_EID_EXTCAP:
11117 {
11118 uint16_t curAddIELen =
11119 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011120 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011121
11122 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11123 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011124 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011125 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011126 return -ENOMEM;
11127 }
11128 memcpy(pWextState->assocAddIE.addIEdata +
11129 curAddIELen, genie - 2, eLen + 2);
11130 pWextState->assocAddIE.length += eLen + 2;
11131
11132 pWextState->roamProfile.pAddIEAssoc =
11133 pWextState->assocAddIE.addIEdata;
11134 pWextState->roamProfile.nAddIEAssocLength =
11135 pWextState->assocAddIE.length;
11136 break;
11137 }
11138#ifdef FEATURE_WLAN_WAPI
11139 case WLAN_EID_WAPI:
11140 /* Setting WAPI Mode to ON=1 */
11141 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011142 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011143 tmp = (u16 *) ie;
11144 tmp = tmp + 2; /* Skip element Id and Len, Version */
11145 akmsuiteCount = WPA_GET_LE16(tmp);
11146 tmp = tmp + 1;
11147 akmlist = (int *)(tmp);
11148 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
11149 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
11150 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011151 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011152 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011153 return -EINVAL;
11154 }
11155
11156 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011157 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011158 pAdapter->wapi_info.wapiAuthMode =
11159 WAPI_AUTH_MODE_PSK;
11160 }
11161 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011162 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011163 pAdapter->wapi_info.wapiAuthMode =
11164 WAPI_AUTH_MODE_CERT;
11165 }
11166 break;
11167#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011168 case DOT11F_EID_SUPPOPERATINGCLASSES:
11169 {
11170 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
11171 status = wlan_hdd_add_assoc_ie(pWextState,
11172 genie - 2, eLen + 2);
11173 if (status)
11174 return status;
11175 break;
11176 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011177 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011178 hdd_err("Set UNKNOWN IE %X", elementId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011179 /* when Unknown IE is received we should break and continue
11180 * to the next IE in the buffer instead we were returning
11181 * so changing this to break */
11182 break;
11183 }
11184 genie += eLen;
11185 remLen -= eLen;
11186 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011187 return 0;
11188}
11189
11190/**
11191 * hdd_is_wpaie_present() - check for WPA ie
11192 * @ie: Pointer to ie
11193 * @ie_len: Ie length
11194 *
11195 * Parse the received IE to find the WPA IE
11196 *
11197 * Return: true if wpa ie is found else false
11198 */
11199static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
11200{
11201 uint8_t eLen = 0;
11202 uint16_t remLen = ie_len;
11203 uint8_t elementId = 0;
11204
11205 while (remLen >= 2) {
11206 elementId = *ie++;
11207 eLen = *ie++;
11208 remLen -= 2;
11209 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011210 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011211 return false;
11212 }
11213 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
11214 /* OUI - 0x00 0X50 0XF2
11215 * WPA Information Element - 0x01
11216 * WPA version - 0x01
11217 */
11218 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
11219 return true;
11220 }
11221 ie += eLen;
11222 remLen -= eLen;
11223 }
11224 return false;
11225}
11226
11227/**
11228 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
11229 * @pAdapter: Pointer to adapter
11230 * @req: Pointer to security parameters
11231 *
11232 * Return: 0 for success, non-zero for failure
11233 */
11234int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
11235 struct cfg80211_connect_params *req)
11236{
11237 int status = 0;
11238 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11239 ENTER();
11240
11241 /*set wpa version */
11242 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
11243
11244 if (req->crypto.wpa_versions) {
11245 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
11246 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
11247 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
11248 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
11249 }
11250 }
11251
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011252 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011253
11254 /*set authentication type */
11255 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
11256
11257 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011258 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011259 return status;
11260 }
11261
11262 /*set key mgmt type */
11263 if (req->crypto.n_akm_suites) {
11264 status =
11265 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
11266 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011267 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011268 return status;
11269 }
11270 }
11271
11272 /*set pairwise cipher type */
11273 if (req->crypto.n_ciphers_pairwise) {
11274 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
11275 req->crypto.
11276 ciphers_pairwise[0],
11277 true);
11278 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011279 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011280 return status;
11281 }
11282 } else {
11283 /*Reset previous cipher suite to none */
11284 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
11285 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011286 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011287 return status;
11288 }
11289 }
11290
11291 /*set group cipher type */
11292 status =
11293 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
11294 false);
11295
11296 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011297 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011298 return status;
11299 }
11300#ifdef WLAN_FEATURE_11W
11301 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
11302#endif
11303
11304 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
11305 if (req->ie_len) {
11306 status =
11307 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
11308 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011309 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011310 return status;
11311 }
11312 }
11313
11314 /*incase of WEP set default key information */
11315 if (req->key && req->key_len) {
11316 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
11317 || (WLAN_CIPHER_SUITE_WEP104 ==
11318 req->crypto.ciphers_pairwise[0])
11319 ) {
11320 if (IW_AUTH_KEY_MGMT_802_1X
11321 ==
11322 (pWextState->
11323 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011324 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011325 return -EOPNOTSUPP;
11326 } else {
11327 u8 key_len = req->key_len;
11328 u8 key_idx = req->key_idx;
11329
11330 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
11331 key_len)
11332 && (CSR_MAX_NUM_KEY > key_idx)
11333 ) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011334 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011335 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011336 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011337 Keys.
11338 KeyMaterial[key_idx][0],
11339 req->key, key_len);
11340 pWextState->roamProfile.Keys.
11341 KeyLength[key_idx] = (u8) key_len;
11342 pWextState->roamProfile.Keys.
11343 defaultIndex = (u8) key_idx;
11344 }
11345 }
11346 }
11347 }
11348
11349 return status;
11350}
11351
11352/**
11353 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
11354 * @pAdapter: Pointer to adapter
11355 *
11356 * This function is used to disconnect from previous connection
11357 *
11358 * Return: 0 for success, non-zero for failure
11359 */
11360static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
11361{
11362 unsigned long rc;
11363 hdd_station_ctx_t *pHddStaCtx;
11364 eMib_dot11DesiredBssType connectedBssType;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053011365 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011366
11367 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11368
11369 hdd_conn_get_connected_bss_type(pHddStaCtx, &connectedBssType);
11370
11371 if ((eMib_dot11DesiredBssType_independent == connectedBssType) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053011372 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
11373 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
11374 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011375 hdd_conn_set_connection_state(pAdapter,
11376 eConnectionState_Disconnecting);
11377 /* Issue disconnect to CSR */
11378 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053011379
11380 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
11381 pAdapter->sessionId,
11382 eCSR_DISCONNECT_REASON_UNSPECIFIED);
11383 /*
11384 * Wait here instead of returning directly, this will block the
11385 * next connect command and allow processing of the scan for
11386 * ssid and the previous connect command in CSR. Else we might
11387 * hit some race conditions leading to SME and HDD out of sync.
11388 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011389 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053011390 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
11391 } else if (0 != status) {
11392 hdd_err("csrRoamDisconnect failure, returned %d",
11393 (int)status);
11394 pHddStaCtx->staDebugState = status;
11395 result = -EINVAL;
11396 goto disconnected;
11397 }
11398
11399 rc = wait_for_completion_timeout(
11400 &pAdapter->disconnect_comp_var,
11401 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011402 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053011403 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
11404 pAdapter->sessionId, pHddStaCtx->staDebugState);
11405 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011406 }
11407 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053011408 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011409 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053011410 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011411 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053011412 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011413 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053011414 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011415 }
11416 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053011417disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053011418 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
11419 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011420}
11421
11422/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070011423 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
11424 * @adapter: Pointer to the HDD adapter
11425 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070011426 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070011427 *
11428 * This function will start reassociation if bssid hint, channel hint and
11429 * previous bssid parameters are present in the connect request
11430 *
Naveen Rawat07332902016-07-27 09:13:17 -070011431 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070011432 */
11433#ifdef CFG80211_CONNECT_PREV_BSSID
Naveen Rawat07332902016-07-27 09:13:17 -070011434static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
11435 struct cfg80211_connect_params *req,
11436 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070011437{
Naveen Rawat07332902016-07-27 09:13:17 -070011438 bool reassoc = false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070011439 if (req->bssid_hint && req->channel_hint && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070011440 reassoc = true;
11441 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
11442 req->channel_hint->hw_value,
11443 MAC_ADDR_ARRAY(req->bssid_hint));
11444 *status = hdd_reassoc(adapter, req->bssid_hint,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070011445 req->channel_hint->hw_value,
11446 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070011447 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070011448 }
Naveen Rawat07332902016-07-27 09:13:17 -070011449 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070011450}
11451#else
Naveen Rawat07332902016-07-27 09:13:17 -070011452static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
11453 struct cfg80211_connect_params *req,
11454 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070011455{
Naveen Rawat07332902016-07-27 09:13:17 -070011456 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070011457}
11458#endif
11459
11460/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011461 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
11462 * @wiphy: Pointer to wiphy
11463 * @dev: Pointer to network device
11464 * @req: Pointer to cfg80211 connect request
11465 *
11466 * This function is used to start the association process
11467 *
11468 * Return: 0 for success, non-zero for failure
11469 */
11470static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
11471 struct net_device *ndev,
11472 struct cfg80211_connect_params *req)
11473{
11474 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053011475 u16 channel;
11476#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
11477 const u8 *bssid_hint = req->bssid_hint;
11478#else
11479 const u8 *bssid_hint = NULL;
11480#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011481 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
11482 hdd_context_t *pHddCtx;
11483
11484 ENTER();
11485
Anurag Chouhan6d760662016-02-20 16:05:43 +053011486 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011487 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011488 return -EINVAL;
11489 }
11490
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011491 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011492 TRACE_CODE_HDD_CFG80211_CONNECT,
11493 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011494 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011495 hdd_device_mode_to_string(pAdapter->device_mode),
11496 pAdapter->device_mode);
11497
Krunal Sonib4326f22016-03-10 13:05:51 -080011498 if (pAdapter->device_mode != QDF_STA_MODE &&
11499 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011500 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011501 hdd_device_mode_to_string(pAdapter->device_mode),
11502 pAdapter->device_mode);
11503 return -EINVAL;
11504 }
11505
11506 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11507 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011508 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011509 return -EINVAL;
11510 }
11511
11512 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011513 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011514 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070011515
Naveen Rawat07332902016-07-27 09:13:17 -070011516 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070011517 return status;
11518
Agrawal Ashishf156e942016-08-04 14:54:47 +053011519 wlan_hdd_disable_roaming(pAdapter);
11520
11521 /* Try disconnecting if already in connected state */
11522 status = wlan_hdd_try_disconnect(pAdapter);
11523 if (0 > status) {
11524 hdd_err("Failed to disconnect the existing connection");
11525 return -EALREADY;
11526 }
11527
11528 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011529 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011530 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080011531 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011532 pAdapter->device_mode),
11533 req->channel->hw_value, HW_MODE_20_MHZ)) {
11534 hdd_err("This concurrency combination is not allowed");
11535 return -ECONNREFUSED;
11536 }
11537 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011538 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080011539 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011540 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
11541 hdd_err("This concurrency combination is not allowed");
11542 return -ECONNREFUSED;
11543 }
11544 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070011545
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011546 /*initialise security parameters */
11547 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
11548
11549 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011550 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011551 return status;
11552 }
11553
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053011554 if (req->channel)
11555 channel = req->channel->hw_value;
11556 else
11557 channel = 0;
11558 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
11559 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011560 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011561 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011562 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011563 return status;
11564 }
11565 EXIT();
11566 return status;
11567}
11568
11569/**
11570 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
11571 * @wiphy: Pointer to wiphy
11572 * @dev: Pointer to network device
11573 * @req: Pointer to cfg80211 connect request
11574 *
11575 * Return: 0 for success, non-zero for failure
11576 */
11577static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
11578 struct net_device *ndev,
11579 struct cfg80211_connect_params *req)
11580{
11581 int ret;
11582 cds_ssr_protect(__func__);
11583 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
11584 cds_ssr_unprotect(__func__);
11585
11586 return ret;
11587}
11588
11589/**
11590 * wlan_hdd_disconnect() - hdd disconnect api
11591 * @pAdapter: Pointer to adapter
11592 * @reason: Disconnect reason code
11593 *
11594 * This function is used to issue a disconnect request to SME
11595 *
11596 * Return: 0 for success, non-zero for failure
11597 */
11598int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
11599{
11600 int status, result = 0;
11601 unsigned long rc;
11602 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11603 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11604
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011605 ENTER();
11606
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011607 status = wlan_hdd_validate_context(pHddCtx);
11608
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011609 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011610 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011611
11612 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011613 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011614 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
11615 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011616 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011617 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
11618 INIT_COMPLETION(pAdapter->disconnect_comp_var);
11619
11620 /*issue disconnect */
11621
11622 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
11623 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053011624 /*
11625 * Wait here instead of returning directly, this will block the next
11626 * connect command and allow processing of the scan for ssid and
11627 * the previous connect command in CSR. Else we might hit some
11628 * race conditions leading to SME and HDD out of sync.
11629 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011630 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053011631 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011632 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011633 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011634 (int)status);
11635 pHddStaCtx->staDebugState = status;
11636 result = -EINVAL;
11637 goto disconnected;
11638 }
11639 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
11640 msecs_to_jiffies
11641 (WLAN_WAIT_TIME_DISCONNECT));
11642
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011643 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011644 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011645 result = -ETIMEDOUT;
11646 }
11647disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011648 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
11649#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
11650 /* Sending disconnect event to userspace for kernel version < 3.11
11651 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
11652 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011653 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053011654 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
11655 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011656#endif
11657
11658 return result;
11659}
11660
11661/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080011662 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
11663 * @reason: ieee80211 reason code.
11664 *
11665 * This utility function helps log string conversion of reason code.
11666 *
11667 * Return: string conversion of reason code, if match found;
11668 * "Unknown" otherwise.
11669 */
11670static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
11671{
11672 switch (reason) {
11673 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
11674 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
11675 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
11676 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
11677 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
11678 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
11679 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
11680 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
11681 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
11682 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
11683 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
11684 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
11685 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
11686 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
11687 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
11688 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
11689 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
11690 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
11691 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
11692 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
11693 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
11694 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
11695 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
11696 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
11697 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
11698 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
11699 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
11700 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
11701 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
11702 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
11703 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
11704 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
11705 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
11706 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
11707 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
11708 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
11709 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
11710 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
11711 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
11712 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
11713 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
11714 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
11715 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
11716 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
11717 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
11718 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
11719 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
11720 default:
11721 return "Unknown";
11722 }
11723}
11724
11725/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011726 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
11727 * @wiphy: Pointer to wiphy
11728 * @dev: Pointer to network device
11729 * @reason: Disconnect reason code
11730 *
11731 * This function is used to issue a disconnect request to SME
11732 *
11733 * Return: 0 for success, non-zero for failure
11734 */
11735static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
11736 struct net_device *dev, u16 reason)
11737{
11738 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11739 int status;
11740 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11741 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
11742#ifdef FEATURE_WLAN_TDLS
11743 uint8_t staIdx;
11744#endif
11745
11746 ENTER();
11747
Anurag Chouhan6d760662016-02-20 16:05:43 +053011748 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011749 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011750 return -EINVAL;
11751 }
11752
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011753 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011754 TRACE_CODE_HDD_CFG80211_DISCONNECT,
11755 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011756 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011757 hdd_device_mode_to_string(pAdapter->device_mode),
11758 pAdapter->device_mode, reason);
11759
11760 status = wlan_hdd_validate_context(pHddCtx);
11761
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011762 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011763 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011764
11765 /* Issue disconnect request to SME, if station is in connected state */
11766 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
11767 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
11768 eCsrRoamDisconnectReason reasonCode =
11769 eCSR_DISCONNECT_REASON_UNSPECIFIED;
11770 hdd_scaninfo_t *pScanInfo;
11771
11772 switch (reason) {
11773 case WLAN_REASON_MIC_FAILURE:
11774 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
11775 break;
11776
11777 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
11778 case WLAN_REASON_DISASSOC_AP_BUSY:
11779 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
11780 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
11781 break;
11782
11783 case WLAN_REASON_PREV_AUTH_NOT_VALID:
11784 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
11785 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
11786 break;
11787
11788 case WLAN_REASON_DEAUTH_LEAVING:
11789 reasonCode =
11790 pHddCtx->config->
11791 gEnableDeauthToDisassocMap ?
11792 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
11793 eCSR_DISCONNECT_REASON_DEAUTH;
11794 break;
11795 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
11796 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
11797 break;
11798 default:
11799 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
11800 break;
11801 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011802 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011803 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011804 pScanInfo = &pAdapter->scan_info;
11805 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011806 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011807 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
11808 eCSR_SCAN_ABORT_DEFAULT);
11809 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053011810 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011811#ifdef FEATURE_WLAN_TDLS
11812 /* First clean up the tdls peers if any */
11813 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
11814 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
11815 pAdapter->sessionId)
11816 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
11817 uint8_t *mac;
11818 mac =
11819 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011820 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
11821 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011822 pHddCtx->tdlsConnInfo[staIdx].staId,
11823 pAdapter->sessionId,
11824 MAC_ADDR_ARRAY(mac));
11825 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
11826 (pAdapter),
11827 pAdapter->sessionId, mac);
11828 }
11829 }
11830#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011831 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011832 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080011833 hdd_info("Disconnect request from user space with reason: %s",
11834 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011835 status = wlan_hdd_disconnect(pAdapter, reasonCode);
11836 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011837 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011838 return -EINVAL;
11839 }
11840 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011841 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011842 pHddStaCtx->conn_info.connState);
11843 }
11844
11845 return status;
11846}
11847
11848/**
11849 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
11850 * @wiphy: Pointer to wiphy
11851 * @dev: Pointer to network device
11852 * @reason: Disconnect reason code
11853 *
11854 * Return: 0 for success, non-zero for failure
11855 */
11856static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
11857 struct net_device *dev, u16 reason)
11858{
11859 int ret;
11860 cds_ssr_protect(__func__);
11861 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
11862 cds_ssr_unprotect(__func__);
11863
11864 return ret;
11865}
11866
11867/**
11868 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
11869 * @pAdapter: Pointer to adapter
11870 * @param: Pointer to IBSS parameters
11871 *
11872 * This function is used to initialize the security settings in IBSS mode
11873 *
11874 * Return: 0 for success, non-zero for failure
11875 */
11876static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
11877 struct cfg80211_ibss_params
11878 *params)
11879{
11880 int status = 0;
11881 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11882 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11883 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11884
11885 ENTER();
11886
11887 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011888 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011889 pHddStaCtx->ibss_enc_key_installed = 0;
11890
11891 if (params->ie_len && (NULL != params->ie)) {
11892 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
11893 params->ie_len, WLAN_EID_RSN)) {
11894 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
11895 encryptionType = eCSR_ENCRYPT_TYPE_AES;
11896 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
11897 tDot11fIEWPA dot11WPAIE;
11898 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
11899 u8 *ie;
11900
11901 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
11902 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
11903 params->ie_len,
11904 DOT11F_EID_WPA);
11905 if (NULL != ie) {
11906 pWextState->wpaVersion =
11907 IW_AUTH_WPA_VERSION_WPA;
11908 /* Unpack the WPA IE */
11909 /* Skip past the EID byte and length byte - and four byte WiFi OUI */
11910 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
11911 &ie[2 + 4],
11912 ie[1] - 4, &dot11WPAIE);
11913 /*Extract the multicast cipher, the encType for unicast
11914 cipher for wpa-none is none */
11915 encryptionType =
11916 hdd_translate_wpa_to_csr_encryption_type
11917 (dot11WPAIE.multicast_cipher);
11918 }
11919 }
11920
11921 status =
11922 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
11923 params->ie_len);
11924
11925 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011926 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011927 return status;
11928 }
11929 }
11930
11931 pWextState->roamProfile.AuthType.authType[0] =
11932 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
11933
11934 if (params->privacy) {
11935 /* Security enabled IBSS, At this time there is no information
11936 * available about the security paramters, so initialise the
11937 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
11938 * The correct security parameters will be updated later in
11939 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
11940 * set inorder enable privacy bit in beacons
11941 */
11942
11943 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
11944 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011945 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011946 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
11947 pWextState->roamProfile.EncryptionType.numEntries = 1;
11948 pWextState->roamProfile.EncryptionType.encryptionType[0] =
11949 encryptionType;
11950 return status;
11951}
11952
11953/**
11954 * __wlan_hdd_cfg80211_join_ibss() - join ibss
11955 * @wiphy: Pointer to wiphy
11956 * @dev: Pointer to network device
11957 * @param: Pointer to IBSS join parameters
11958 *
11959 * This function is used to create/join an IBSS network
11960 *
11961 * Return: 0 for success, non-zero for failure
11962 */
11963static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
11964 struct net_device *dev,
11965 struct cfg80211_ibss_params *params)
11966{
11967 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
11968 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11969 tCsrRoamProfile *pRoamProfile;
11970 int status;
11971 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11972 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053011973 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011974 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011975
11976 ENTER();
11977
Anurag Chouhan6d760662016-02-20 16:05:43 +053011978 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011979 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011980 return -EINVAL;
11981 }
11982
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011983 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011984 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
11985 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070011986 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011987 hdd_device_mode_to_string(pAdapter->device_mode),
11988 pAdapter->device_mode);
11989
11990 status = wlan_hdd_validate_context(pHddCtx);
11991
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011992 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011993 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011994
11995 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053011996 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011997 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
11998 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
11999 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12000 int indx;
12001
12002 /* Get channel number */
12003 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012004 params->
12005 chandef.
12006 chan->
12007 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012008
12009 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
12010 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012011 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012012 return -EOPNOTSUPP;
12013 }
12014
12015 for (indx = 0; indx < numChans; indx++) {
12016 if (channelNum == validChan[indx]) {
12017 break;
12018 }
12019 }
12020 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012021 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012022 return -EINVAL;
12023 }
12024 }
12025
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012026 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012027 HW_MODE_20_MHZ)) {
12028 hdd_err("This concurrency combination is not allowed");
12029 return -ECONNREFUSED;
12030 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012031
Krunal Soni3091bcc2016-06-23 12:28:21 -070012032 status = qdf_reset_connection_update();
12033 if (!QDF_IS_STATUS_SUCCESS(status))
12034 hdd_err("ERR: clear event failed");
12035
12036 status = cds_current_connections_update(pAdapter->sessionId,
12037 channelNum,
12038 SIR_UPDATE_REASON_JOIN_IBSS);
12039 if (QDF_STATUS_E_FAILURE == status) {
12040 hdd_err("ERROR: connections update failed!!");
12041 return -EINVAL;
12042 }
12043
12044 if (QDF_STATUS_SUCCESS == status) {
12045 status = qdf_wait_for_connection_update();
12046 if (!QDF_IS_STATUS_SUCCESS(status)) {
12047 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012048 return -EINVAL;
12049 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012050 }
12051
12052 /*Try disconnecting if already in connected state */
12053 status = wlan_hdd_try_disconnect(pAdapter);
12054 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012055 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012056 return -EALREADY;
12057 }
12058
12059 pRoamProfile = &pWextState->roamProfile;
12060
12061 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012062 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012063 return -EINVAL;
12064 }
12065
12066 /* enable selected protection checks in IBSS mode */
12067 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
12068
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012069 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012070 WNI_CFG_IBSS_ATIM_WIN_SIZE,
12071 pHddCtx->config->
12072 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012073 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012074 }
12075
12076 /* BSSID is provided by upper layers hence no need to AUTO generate */
12077 if (NULL != params->bssid) {
12078 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012079 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012080 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012081 return -EIO;
12082 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012083 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012084 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
12085 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012086 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012087 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012088 return -EIO;
12089 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053012090 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012091 }
12092 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
12093 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
12094 pRoamProfile->beaconInterval = params->beacon_interval;
12095 else {
12096 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012097 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012098 params->beacon_interval, pRoamProfile->beaconInterval);
12099 }
12100
12101 /* Set Channel */
12102 if (channelNum) {
12103 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012104 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012105 pRoamProfile->ChannelInfo.numOfChannels = 1;
12106 pHddStaCtx->conn_info.operationChannel = channelNum;
12107 pRoamProfile->ChannelInfo.ChannelList =
12108 &pHddStaCtx->conn_info.operationChannel;
12109 }
12110
12111 /* Initialize security parameters */
12112 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
12113 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012114 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012115 return status;
12116 }
12117
12118 /* Issue connect start */
12119 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
12120 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012121 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012122 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012123 operationChannel,
12124 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012125
12126 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012127 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012128 return status;
12129 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012130 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012131 return 0;
12132}
12133
12134/**
12135 * wlan_hdd_cfg80211_join_ibss() - join ibss
12136 * @wiphy: Pointer to wiphy
12137 * @dev: Pointer to network device
12138 * @param: Pointer to IBSS join parameters
12139 *
12140 * This function is used to create/join an IBSS network
12141 *
12142 * Return: 0 for success, non-zero for failure
12143 */
12144static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
12145 struct net_device *dev,
12146 struct cfg80211_ibss_params *params)
12147{
12148 int ret = 0;
12149
12150 cds_ssr_protect(__func__);
12151 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
12152 cds_ssr_unprotect(__func__);
12153
12154 return ret;
12155}
12156
12157/**
12158 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
12159 * @wiphy: Pointer to wiphy
12160 * @dev: Pointer to network device
12161 *
12162 * This function is used to leave an IBSS network
12163 *
12164 * Return: 0 for success, non-zero for failure
12165 */
12166static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
12167 struct net_device *dev)
12168{
12169 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12170 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12171 tCsrRoamProfile *pRoamProfile;
12172 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12173 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012174 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053012175 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080012176 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012177
12178 ENTER();
12179
Anurag Chouhan6d760662016-02-20 16:05:43 +053012180 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012181 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012182 return -EINVAL;
12183 }
12184
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012185 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012186 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
12187 pAdapter->sessionId,
12188 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
12189 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012190 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012191 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012192
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012193 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012194 hdd_device_mode_to_string(pAdapter->device_mode),
12195 pAdapter->device_mode);
12196 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012197 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012198 return -EIO;
12199 }
12200
12201 pRoamProfile = &pWextState->roamProfile;
12202
12203 /* Issue disconnect only if interface type is set to IBSS */
12204 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012205 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012206 return -EINVAL;
12207 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080012208 /* Clearing add IE of beacon */
12209 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
12210 sizeof(tSirMacAddr));
12211 updateIE.smeSessionId = pAdapter->sessionId;
12212 updateIE.ieBufferlength = 0;
12213 updateIE.pAdditionIEBuffer = NULL;
12214 updateIE.append = true;
12215 updateIE.notify = true;
12216 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
12217 &updateIE,
12218 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012219 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080012220 }
12221
12222 /* Reset WNI_CFG_PROBE_RSP Flags */
12223 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012224
12225 /* Issue Disconnect request */
12226 INIT_COMPLETION(pAdapter->disconnect_comp_var);
12227 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12228 pAdapter->sessionId,
12229 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012230 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012231 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012232 hal_status);
12233 return -EAGAIN;
12234 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053012235
12236 /* wait for mc thread to cleanup and then return to upper stack
12237 * so by the time upper layer calls the change interface, we are
12238 * all set to proceed further
12239 */
12240 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
12241 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
12242 if (!rc) {
12243 hdd_err("Failed to disconnect, timed out");
12244 return -ETIMEDOUT;
12245 }
12246
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012247 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012248 return 0;
12249}
12250
12251/**
12252 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
12253 * @wiphy: Pointer to wiphy
12254 * @dev: Pointer to network device
12255 *
12256 * This function is used to leave an IBSS network
12257 *
12258 * Return: 0 for success, non-zero for failure
12259 */
12260static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
12261 struct net_device *dev)
12262{
12263 int ret = 0;
12264
12265 cds_ssr_protect(__func__);
12266 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
12267 cds_ssr_unprotect(__func__);
12268
12269 return ret;
12270}
12271
12272/**
12273 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
12274 * @wiphy: Pointer to wiphy
12275 * @changed: Parameters changed
12276 *
12277 * This function is used to set the phy parameters. RTS Threshold/FRAG
12278 * Threshold/Retry Count etc.
12279 *
12280 * Return: 0 for success, non-zero for failure
12281 */
12282static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
12283 u32 changed)
12284{
12285 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
12286 tHalHandle hHal = pHddCtx->hHal;
12287 int status;
12288
12289 ENTER();
12290
Anurag Chouhan6d760662016-02-20 16:05:43 +053012291 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012292 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012293 return -EINVAL;
12294 }
12295
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012296 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012297 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
12298 NO_SESSION, wiphy->rts_threshold));
12299 status = wlan_hdd_validate_context(pHddCtx);
12300
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012301 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012302 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012303
12304 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
12305 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
12306 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
12307
12308 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
12309 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012310 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012311 rts_threshold);
12312 return -EINVAL;
12313 }
12314
12315 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
12316 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012317 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012318 rts_threshold);
12319 return -EIO;
12320 }
12321
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012322 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012323 }
12324
12325 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
12326 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
12327 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
12328 wiphy->frag_threshold;
12329
12330 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
12331 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012332 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012333 frag_threshold);
12334 return -EINVAL;
12335 }
12336
12337 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
12338 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012339 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012340 frag_threshold);
12341 return -EIO;
12342 }
12343
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012344 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012345 }
12346
12347 if ((changed & WIPHY_PARAM_RETRY_SHORT)
12348 || (changed & WIPHY_PARAM_RETRY_LONG)) {
12349 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
12350 wiphy->retry_short : wiphy->retry_long;
12351
12352 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
12353 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012354 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012355 return -EINVAL;
12356 }
12357
12358 if (changed & WIPHY_PARAM_RETRY_SHORT) {
12359 if (0 != sme_cfg_set_int(hHal,
12360 WNI_CFG_LONG_RETRY_LIMIT,
12361 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012362 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012363 retry_value);
12364 return -EIO;
12365 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012366 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012367 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
12368 if (0 != sme_cfg_set_int(hHal,
12369 WNI_CFG_SHORT_RETRY_LIMIT,
12370 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012371 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012372 retry_value);
12373 return -EIO;
12374 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012375 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012376 }
12377 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012378 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012379 return 0;
12380}
12381
12382/**
12383 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
12384 * @wiphy: Pointer to wiphy
12385 * @changed: Parameters changed
12386 *
12387 * Return: 0 for success, non-zero for failure
12388 */
12389static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
12390{
12391 int ret;
12392
12393 cds_ssr_protect(__func__);
12394 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
12395 cds_ssr_unprotect(__func__);
12396
12397 return ret;
12398}
12399
12400/**
12401 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
12402 * key
12403 * @wiphy: Pointer to wiphy
12404 * @dev: Pointer to network device
12405 * @key_index: Key index
12406 *
12407 * Return: 0
12408 */
12409static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
12410 struct net_device *netdev,
12411 u8 key_index)
12412{
12413 ENTER();
12414 return 0;
12415}
12416
12417/**
12418 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
12419 * wlan_hdd_set_default_mgmt_key
12420 * @wiphy: pointer to wiphy
12421 * @netdev: pointer to net_device structure
12422 * @key_index: key index
12423 *
12424 * Return: 0 on success, error number on failure
12425 */
12426static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
12427 struct net_device *netdev,
12428 u8 key_index)
12429{
12430 int ret;
12431
12432 cds_ssr_protect(__func__);
12433 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
12434 cds_ssr_unprotect(__func__);
12435
12436 return ret;
12437}
12438
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012439/**
12440 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
12441 * @wiphy: Pointer to wiphy
12442 * @dev: Pointer to network device
12443 * @params: Pointer to tx queue parameters
12444 *
12445 * Return: 0
12446 */
12447static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
12448 struct net_device *dev,
12449 struct ieee80211_txq_params *params)
12450{
12451 ENTER();
12452 return 0;
12453}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012454
12455/**
12456 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
12457 * @wiphy: pointer to wiphy
12458 * @netdev: pointer to net_device structure
12459 * @params: pointer to ieee80211_txq_params
12460 *
12461 * Return: 0 on success, error number on failure
12462 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012463static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
12464 struct net_device *dev,
12465 struct ieee80211_txq_params *params)
12466{
12467 int ret;
12468
12469 cds_ssr_protect(__func__);
12470 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
12471 cds_ssr_unprotect(__func__);
12472
12473 return ret;
12474}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012475
12476/**
12477 * __wlan_hdd_cfg80211_del_station() - delete station v2
12478 * @wiphy: Pointer to wiphy
12479 * @param: Pointer to delete station parameter
12480 *
12481 * Return: 0 for success, non-zero for failure
12482 */
12483static
12484int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
12485 struct net_device *dev,
12486 struct tagCsrDelStaParams *pDelStaParams)
12487{
12488 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12489 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053012490 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012491 hdd_hostapd_state_t *hapd_state;
12492 int status;
12493 uint8_t staId;
12494 uint8_t *mac;
12495
12496 ENTER();
12497
Anurag Chouhan6d760662016-02-20 16:05:43 +053012498 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012499 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012500 return -EINVAL;
12501 }
12502
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012503 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012504 TRACE_CODE_HDD_CFG80211_DEL_STA,
12505 pAdapter->sessionId, pAdapter->device_mode));
12506
12507 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12508 status = wlan_hdd_validate_context(pHddCtx);
12509
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012510 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012511 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012512
12513 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
12514
Krunal Sonib4326f22016-03-10 13:05:51 -080012515 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
12516 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012517
12518 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
12519 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012520 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012521 return 0;
12522 }
12523
Anurag Chouhanc5548422016-02-24 18:33:27 +053012524 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012525 uint16_t i;
12526 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
12527 if ((pAdapter->aStaInfo[i].isUsed) &&
12528 (!pAdapter->aStaInfo[i].
12529 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012530 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012531 mac,
12532 pAdapter->aStaInfo[i].
12533 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053012534 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012535 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
12536 hdd_ipa_wlan_evt(pAdapter,
12537 pAdapter->
12538 aStaInfo[i].
12539 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070012540 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012541 mac);
12542 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012543 hdd_notice("Delete STA with MAC::"
12544 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012545 MAC_ADDR_ARRAY(mac));
12546
12547 if (pHddCtx->dev_dfs_cac_status ==
12548 DFS_CAC_IN_PROGRESS)
12549 goto fn_end;
12550
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012551 qdf_event_reset(&hapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012552 hdd_softap_sta_disassoc(pAdapter,
12553 mac);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012554 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012555 hdd_softap_sta_deauth(pAdapter,
12556 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012557 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012558 pAdapter->aStaInfo[i].
12559 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053012560 qdf_status =
12561 qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012562 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012563 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053012564 if (!QDF_IS_STATUS_SUCCESS(
12565 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012566 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012567 }
12568 }
12569 }
12570 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012571 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012572 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053012573 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012574 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012575 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012576 hdd_notice("Skip DEL STA as this is not used::"
12577 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012578 MAC_ADDR_ARRAY(mac));
12579 return -ENOENT;
12580 }
12581
12582 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
12583 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070012584 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012585 }
12586
12587 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
12588 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012589 hdd_notice("Skip DEL STA as deauth is in progress::"
12590 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012591 MAC_ADDR_ARRAY(mac));
12592 return -ENOENT;
12593 }
12594
12595 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
12596
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012597 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012598 MAC_ADDR_ARRAY(mac));
12599
12600 /* Case: SAP in ACS selected DFS ch and client connected
12601 * Now Radar detected. Then if random channel is another
12602 * DFS ch then new CAC is initiated and no TX allowed.
12603 * So do not send any mgmt frames as it will timeout
12604 * during CAC.
12605 */
12606
12607 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
12608 goto fn_end;
12609
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012610 qdf_event_reset(&hapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012611 hdd_softap_sta_disassoc(pAdapter, mac);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012612 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012613 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012614 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012615 pAdapter->aStaInfo[staId].isDeauthInProgress =
12616 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012617 hdd_notice("STA removal failed for ::"
12618 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012619 MAC_ADDR_ARRAY(mac));
12620 return -ENOENT;
12621 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053012622 qdf_status = qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053012623 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012624 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053012625 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012626 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012627 }
12628 }
12629 }
12630
12631fn_end:
12632 EXIT();
12633 return 0;
12634}
12635
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080012636#if defined(USE_CFG80211_DEL_STA_V2)
12637/**
12638 * wlan_hdd_del_station() - delete station wrapper
12639 * @adapter: pointer to the hdd adapter
12640 *
12641 * Return: None
12642 */
12643void wlan_hdd_del_station(hdd_adapter_t *adapter)
12644{
12645 struct station_del_parameters del_sta;
12646 del_sta.mac = NULL;
12647 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
12648 del_sta.reason_code = eCsrForcedDeauthSta;
12649
12650 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
12651 &del_sta);
12652}
12653#else
12654void wlan_hdd_del_station(hdd_adapter_t *adapter)
12655{
12656 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
12657}
12658#endif
12659
12660#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012661/**
12662 * wlan_hdd_cfg80211_del_station() - delete station v2
12663 * @wiphy: Pointer to wiphy
12664 * @param: Pointer to delete station parameter
12665 *
12666 * Return: 0 for success, non-zero for failure
12667 */
12668int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
12669 struct net_device *dev,
12670 struct station_del_parameters *param)
12671#else
12672/**
12673 * wlan_hdd_cfg80211_del_station() - delete station
12674 * @wiphy: Pointer to wiphy
12675 * @mac: Pointer to station mac address
12676 *
12677 * Return: 0 for success, non-zero for failure
12678 */
12679#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
12680int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
12681 struct net_device *dev,
12682 const uint8_t *mac)
12683#else
12684int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
12685 struct net_device *dev,
12686 uint8_t *mac)
12687#endif
12688#endif
12689{
12690 int ret;
12691 struct tagCsrDelStaParams delStaParams;
12692
12693 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080012694#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012695 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080012696 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012697 return -EINVAL;
12698 }
12699 wlansap_populate_del_sta_params(param->mac, param->reason_code,
12700 param->subtype, &delStaParams);
12701#else
12702 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
12703 (SIR_MAC_MGMT_DEAUTH >> 4),
12704 &delStaParams);
12705#endif
12706 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
12707 cds_ssr_unprotect(__func__);
12708
12709 return ret;
12710}
12711
12712/**
12713 * __wlan_hdd_cfg80211_add_station() - add station
12714 * @wiphy: Pointer to wiphy
12715 * @mac: Pointer to station mac address
12716 * @pmksa: Pointer to add station parameter
12717 *
12718 * Return: 0 for success, non-zero for failure
12719 */
12720static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
12721 struct net_device *dev,
12722 const uint8_t *mac,
12723 struct station_parameters *params)
12724{
12725 int status = -EPERM;
12726#ifdef FEATURE_WLAN_TDLS
12727 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12728 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
12729 u32 mask, set;
12730
12731 ENTER();
12732
Anurag Chouhan6d760662016-02-20 16:05:43 +053012733 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012734 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012735 return -EINVAL;
12736 }
12737
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012738 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012739 TRACE_CODE_HDD_CFG80211_ADD_STA,
12740 pAdapter->sessionId, params->listen_interval));
12741
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012742 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012743 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012744
12745 mask = params->sta_flags_mask;
12746
12747 set = params->sta_flags_set;
12748
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012749 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012750 MAC_ADDR_ARRAY(mac));
12751
12752 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
12753 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
12754 status =
12755 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
12756 }
12757 }
12758#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012759 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012760 return status;
12761}
12762
12763/**
12764 * wlan_hdd_cfg80211_add_station() - add station
12765 * @wiphy: Pointer to wiphy
12766 * @mac: Pointer to station mac address
12767 * @pmksa: Pointer to add station parameter
12768 *
12769 * Return: 0 for success, non-zero for failure
12770 */
12771#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
12772static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
12773 struct net_device *dev,
12774 const uint8_t *mac,
12775 struct station_parameters *params)
12776#else
12777static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
12778 struct net_device *dev, uint8_t *mac,
12779 struct station_parameters *params)
12780#endif
12781{
12782 int ret;
12783
12784 cds_ssr_protect(__func__);
12785 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
12786 cds_ssr_unprotect(__func__);
12787
12788 return ret;
12789}
12790
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012791/**
12792 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
12793 * @wiphy: Pointer to wiphy
12794 * @dev: Pointer to network device
12795 * @pmksa: Pointer to set pmksa parameter
12796 *
12797 * Return: 0 for success, non-zero for failure
12798 */
12799static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
12800 struct net_device *dev,
12801 struct cfg80211_pmksa *pmksa)
12802{
12803 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12804 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12805 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012806 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012807 int status;
12808 tPmkidCacheInfo pmk_id;
12809
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012810 ENTER();
12811
Anurag Chouhan6d760662016-02-20 16:05:43 +053012812 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012813 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012814 return -EINVAL;
12815 }
12816
12817 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012818 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012819 return -EINVAL;
12820 }
12821
12822 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012823 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012824 pmksa->bssid, pmksa->pmkid);
12825 return -EINVAL;
12826 }
12827
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012828 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012829 MAC_ADDR_ARRAY(pmksa->bssid));
12830
12831 status = wlan_hdd_validate_context(pHddCtx);
12832
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012833 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012834 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012835
12836 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
12837
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012838 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
12839 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012840
12841 /* Add to the PMKSA ID Cache in CSR */
12842 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
12843 &pmk_id, 1, false);
12844
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012845 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012846 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
12847 pAdapter->sessionId, result));
12848
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012849 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012850 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012851}
12852
12853/**
12854 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
12855 * @wiphy: Pointer to wiphy
12856 * @dev: Pointer to network device
12857 * @pmksa: Pointer to set pmksa parameter
12858 *
12859 * Return: 0 for success, non-zero for failure
12860 */
12861static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
12862 struct net_device *dev,
12863 struct cfg80211_pmksa *pmksa)
12864{
12865 int ret;
12866
12867 cds_ssr_protect(__func__);
12868 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
12869 cds_ssr_unprotect(__func__);
12870
12871 return ret;
12872}
12873
12874/**
12875 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
12876 * @wiphy: Pointer to wiphy
12877 * @dev: Pointer to network device
12878 * @pmksa: Pointer to pmksa parameter
12879 *
12880 * Return: 0 for success, non-zero for failure
12881 */
12882static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
12883 struct net_device *dev,
12884 struct cfg80211_pmksa *pmksa)
12885{
12886 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12887 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12888 tHalHandle halHandle;
12889 int status = 0;
12890
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012891 ENTER();
12892
Anurag Chouhan6d760662016-02-20 16:05:43 +053012893 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012894 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012895 return -EINVAL;
12896 }
12897
12898 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012899 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012900 return -EINVAL;
12901 }
12902
12903 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012904 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012905 return -EINVAL;
12906 }
12907
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012908 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012909 MAC_ADDR_ARRAY(pmksa->bssid));
12910
12911 status = wlan_hdd_validate_context(pHddCtx);
12912
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012913 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012914 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012915
12916 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
12917
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012918 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053012919 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
12920 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012921 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012922 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012923 sme_roam_del_pmkid_from_cache(halHandle,
12924 pAdapter->sessionId, pmksa->bssid,
12925 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012926 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012927 MAC_ADDR_ARRAY(pmksa->bssid));
12928 status = -EINVAL;
12929 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012930 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012931 return status;
12932}
12933
12934/**
12935 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
12936 * @wiphy: Pointer to wiphy
12937 * @dev: Pointer to network device
12938 * @pmksa: Pointer to pmksa parameter
12939 *
12940 * Return: 0 for success, non-zero for failure
12941 */
12942static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
12943 struct net_device *dev,
12944 struct cfg80211_pmksa *pmksa)
12945{
12946 int ret;
12947
12948 cds_ssr_protect(__func__);
12949 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
12950 cds_ssr_unprotect(__func__);
12951
12952 return ret;
12953
12954}
12955
12956/**
12957 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
12958 * @wiphy: Pointer to wiphy
12959 * @dev: Pointer to network device
12960 *
12961 * Return: 0 for success, non-zero for failure
12962 */
12963static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
12964 struct net_device *dev)
12965{
12966 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12967 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12968 tHalHandle halHandle;
12969 int status = 0;
12970
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012971 ENTER();
12972
Anurag Chouhan6d760662016-02-20 16:05:43 +053012973 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012974 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012975 return -EINVAL;
12976 }
12977
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012978 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012979
12980 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12981 status = wlan_hdd_validate_context(pHddCtx);
12982
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012983 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012984 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012985
12986 /* Retrieve halHandle */
12987 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
12988
12989 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012990 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012991 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
12992 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012993 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012994 status = -EINVAL;
12995 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012996 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012997 return status;
12998}
12999
13000/**
13001 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
13002 * @wiphy: Pointer to wiphy
13003 * @dev: Pointer to network device
13004 *
13005 * Return: 0 for success, non-zero for failure
13006 */
13007static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
13008 struct net_device *dev)
13009{
13010 int ret;
13011
13012 cds_ssr_protect(__func__);
13013 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
13014 cds_ssr_unprotect(__func__);
13015
13016 return ret;
13017}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013018
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080013019#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013020/**
13021 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
13022 * @wiphy: Pointer to wiphy
13023 * @dev: Pointer to network device
13024 * @ftie: Pointer to fast transition ie parameter
13025 *
13026 * Return: 0 for success, non-zero for failure
13027 */
13028static int
13029__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
13030 struct net_device *dev,
13031 struct cfg80211_update_ft_ies_params *ftie)
13032{
13033 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
13034 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13035 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13036 int status;
13037
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013038 ENTER();
13039
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013040 status = wlan_hdd_validate_context(hdd_ctx);
13041 if (status)
13042 return status;
13043
Anurag Chouhan6d760662016-02-20 16:05:43 +053013044 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013045 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013046 return -EINVAL;
13047 }
13048
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013049 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013050 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
13051 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
13052 /* Added for debug on reception of Re-assoc Req. */
13053 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013054 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013055 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013056 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013057 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013058 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013059 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013060
13061 /* Pass the received FT IEs to SME */
13062 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
13063 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013064 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013065 return 0;
13066}
13067
13068/**
13069 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
13070 * @wiphy: Pointer to wiphy
13071 * @dev: Pointer to network device
13072 * @ftie: Pointer to fast transition ie parameter
13073 *
13074 * Return: 0 for success, non-zero for failure
13075 */
13076static int
13077wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
13078 struct net_device *dev,
13079 struct cfg80211_update_ft_ies_params *ftie)
13080{
13081 int ret;
13082
13083 cds_ssr_protect(__func__);
13084 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
13085 cds_ssr_unprotect(__func__);
13086
13087 return ret;
13088}
13089#endif
13090
13091#ifdef WLAN_FEATURE_GTK_OFFLOAD
13092/**
13093 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
13094 * @callbackContext: Callback context
13095 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
13096 *
13097 * Callback rountine called upon receiving response for get offload info
13098 *
13099 * Return: none
13100 */
13101void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
13102 tpSirGtkOffloadGetInfoRspParams
13103 pGtkOffloadGetInfoRsp)
13104{
13105 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
13106 uint8_t tempReplayCounter[8];
13107 hdd_station_ctx_t *pHddStaCtx;
13108
13109 ENTER();
13110
13111 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013112 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013113 return;
13114 }
13115
13116 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013117 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013118 return;
13119 }
13120
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013121 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013122 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013123 return;
13124 }
13125
13126 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13127 /* Update replay counter */
13128 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
13129 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
13130
13131 {
13132 /* changing from little to big endian since supplicant
13133 * works on big endian format
13134 */
13135 int i;
13136 uint8_t *p =
13137 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
13138
13139 for (i = 0; i < 8; i++) {
13140 tempReplayCounter[7 - i] = (uint8_t) p[i];
13141 }
13142 }
13143
13144 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080013145 cfg80211_gtk_rekey_notify(pAdapter->dev,
13146 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013147 tempReplayCounter, GFP_KERNEL);
13148}
13149
13150/**
13151 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
13152 * @wiphy: Pointer to wiphy
13153 * @dev: Pointer to network device
13154 * @data: Pointer to rekey data
13155 *
13156 * This function is used to offload GTK rekeying job to the firmware.
13157 *
13158 * Return: 0 for success, non-zero for failure
13159 */
13160int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
13161 struct net_device *dev,
13162 struct cfg80211_gtk_rekey_data *data)
13163{
13164 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13165 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13166 hdd_station_ctx_t *pHddStaCtx;
13167 tHalHandle hHal;
13168 int result;
13169 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013170 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013171
13172 ENTER();
13173
Anurag Chouhan6d760662016-02-20 16:05:43 +053013174 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013175 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013176 return -EINVAL;
13177 }
13178
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013179 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013180 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
13181 pAdapter->sessionId, pAdapter->device_mode));
13182
13183 result = wlan_hdd_validate_context(pHddCtx);
13184
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013185 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013186 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013187
13188 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13189 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
13190 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013191 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013192 return -EAGAIN;
13193 }
13194
13195 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
13196 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
13197 NL80211_KCK_LEN);
13198 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
13199 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053013200 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080013201 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013202 {
13203 /* changing from big to little endian since driver
13204 * works on little endian format
13205 */
13206 uint8_t *p =
13207 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
13208 ullKeyReplayCounter;
13209 int i;
13210
13211 for (i = 0; i < 8; i++) {
13212 p[7 - i] = data->replay_ctr[i];
13213 }
13214 }
13215
13216 if (true == pHddCtx->hdd_wlan_suspended) {
13217 /* if wlan is suspended, enable GTK offload directly from here */
13218 memcpy(&hddGtkOffloadReqParams,
13219 &pHddStaCtx->gtkOffloadReqParams,
13220 sizeof(tSirGtkOffloadParams));
13221 status =
13222 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
13223 pAdapter->sessionId);
13224
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013225 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013226 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013227 status);
13228 return -EINVAL;
13229 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013230 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013231 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013232 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013233 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013234 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013235 return result;
13236}
13237
13238/**
13239 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
13240 * @wiphy: Pointer to wiphy
13241 * @dev: Pointer to network device
13242 * @data: Pointer to rekey data
13243 *
13244 * This function is used to offload GTK rekeying job to the firmware.
13245 *
13246 * Return: 0 for success, non-zero for failure
13247 */
13248int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
13249 struct net_device *dev,
13250 struct cfg80211_gtk_rekey_data *data)
13251{
13252 int ret;
13253
13254 cds_ssr_protect(__func__);
13255 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
13256 cds_ssr_unprotect(__func__);
13257
13258 return ret;
13259}
13260#endif /*WLAN_FEATURE_GTK_OFFLOAD */
13261
13262/**
13263 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
13264 * @wiphy: Pointer to wiphy
13265 * @dev: Pointer to network device
13266 * @param: Pointer to access control parameter
13267 *
13268 * Return: 0 for success, non-zero for failure
13269 */
13270static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
13271 struct net_device *dev,
13272 const struct cfg80211_acl_data *params)
13273{
13274 int i;
13275 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13276 hdd_hostapd_state_t *pHostapdState;
13277 tsap_Config_t *pConfig;
13278 v_CONTEXT_t p_cds_context = NULL;
13279 hdd_context_t *pHddCtx;
13280 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013281 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013282
13283 ENTER();
13284
Anurag Chouhan6d760662016-02-20 16:05:43 +053013285 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013286 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013287 return -EINVAL;
13288 }
13289
13290 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013291 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013292 return -EINVAL;
13293 }
13294
13295 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13296 status = wlan_hdd_validate_context(pHddCtx);
13297
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013298 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013299 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013300
13301 p_cds_context = pHddCtx->pcds_context;
13302 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
13303
13304 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013305 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013306 return -EINVAL;
13307 }
13308
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013309 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013310 params->n_acl_entries);
13311
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013312 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053013313 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
13314 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080013315 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013316 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
13317
13318 /* default value */
13319 pConfig->num_accept_mac = 0;
13320 pConfig->num_deny_mac = 0;
13321
13322 /**
13323 * access control policy
13324 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
13325 * listed in hostapd.deny file.
13326 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
13327 * listed in hostapd.accept file.
13328 */
13329 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
13330 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
13331 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
13332 params->acl_policy) {
13333 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
13334 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013335 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013336 params->acl_policy);
13337 return -ENOTSUPP;
13338 }
13339
13340 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
13341 pConfig->num_accept_mac = params->n_acl_entries;
13342 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013343 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
13344 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013345 MAC_ADDR_ARRAY(
13346 params->mac_addrs[i].addr));
13347
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013348 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013349 params->mac_addrs[i].addr,
13350 sizeof(qcmacaddr));
13351 }
13352 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
13353 pConfig->num_deny_mac = params->n_acl_entries;
13354 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013355 hdd_notice("** Add ACL MAC entry %i in BlackList :"
13356 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013357 MAC_ADDR_ARRAY(
13358 params->mac_addrs[i].addr));
13359
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013360 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013361 params->mac_addrs[i].addr,
13362 sizeof(qcmacaddr));
13363 }
13364 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070013365 qdf_status = wlansap_set_mac_acl(
13366 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013367 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013368 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013369 return -EINVAL;
13370 }
13371 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013372 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013373 hdd_device_mode_to_string(pAdapter->device_mode),
13374 pAdapter->device_mode);
13375 return -EINVAL;
13376 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013377 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013378 return 0;
13379}
13380
13381/**
13382 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
13383 * __wlan_hdd_cfg80211_set_mac_acl
13384 * @wiphy: pointer to wiphy structure
13385 * @dev: pointer to net_device
13386 * @params: pointer to cfg80211_acl_data
13387 *
13388 * Return; 0 on success, error number otherwise
13389 */
13390static int
13391wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
13392 struct net_device *dev,
13393 const struct cfg80211_acl_data *params)
13394{
13395 int ret;
13396
13397 cds_ssr_protect(__func__);
13398 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
13399 cds_ssr_unprotect(__func__);
13400
13401 return ret;
13402}
13403
13404#ifdef WLAN_NL80211_TESTMODE
13405#ifdef FEATURE_WLAN_LPHB
13406/**
13407 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
13408 * @pHddCtx: Pointer to hdd context
13409 * @lphbInd: Pointer to low power heart beat indication parameter
13410 *
13411 * Return: none
13412 */
13413void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx, tSirLPHBInd *lphbInd)
13414{
13415 struct sk_buff *skb;
13416
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013417 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013418
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013419 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013420 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013421
13422 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013423 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013424 return;
13425 }
13426
13427 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
13428 wiphy, sizeof(tSirLPHBInd),
13429 GFP_ATOMIC);
13430 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013431 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013432 return;
13433 }
13434
13435 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013436 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013437 goto nla_put_failure;
13438 }
13439 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013440 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013441 goto nla_put_failure;
13442 }
13443 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013444 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013445 goto nla_put_failure;
13446 }
13447 cfg80211_testmode_event(skb, GFP_ATOMIC);
13448 return;
13449
13450nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013451 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013452 kfree_skb(skb);
13453
13454 return;
13455}
13456#endif /* FEATURE_WLAN_LPHB */
13457
13458/**
13459 * __wlan_hdd_cfg80211_testmode() - test mode
13460 * @wiphy: Pointer to wiphy
13461 * @data: Data pointer
13462 * @len: Data length
13463 *
13464 * Return: 0 for success, non-zero for failure
13465 */
13466static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
13467 void *data, int len)
13468{
13469 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
13470 int err;
13471 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13472
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013473 ENTER();
13474
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013475 err = wlan_hdd_validate_context(pHddCtx);
13476 if (err)
13477 return err;
13478
13479 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
13480 len, wlan_hdd_tm_policy);
13481 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013482 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013483 return err;
13484 }
13485
13486 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013487 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013488 return -EINVAL;
13489 }
13490
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013491 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053013492 TRACE_CODE_HDD_CFG80211_TESTMODE,
13493 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013494 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
13495#ifdef FEATURE_WLAN_LPHB
13496 /* Low Power Heartbeat configuration request */
13497 case WLAN_HDD_TM_CMD_WLAN_HB:
13498 {
13499 int buf_len;
13500 void *buf;
13501 tSirLPHBReq *hb_params = NULL;
13502 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013503 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013504
13505 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013506 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013507 return -EINVAL;
13508 }
13509
13510 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
13511 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
13512
13513 hb_params_temp = (tSirLPHBReq *) buf;
13514 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
13515 && (hb_params_temp->params.lphbTcpParamReq.
13516 timePeriodSec == 0))
13517 return -EINVAL;
13518
13519 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013520 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013521 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013522 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013523 return -ENOMEM;
13524 }
13525
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013526 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013527 smeStatus =
13528 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
13529 hb_params,
13530 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013531 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013532 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013533 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013534 }
13535 return 0;
13536 }
13537#endif /* FEATURE_WLAN_LPHB */
13538
13539#if defined(QCA_WIFI_FTM)
13540 case WLAN_HDD_TM_CMD_WLAN_FTM:
13541 {
13542 int buf_len;
13543 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013544 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013545 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070013546 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013547 return -EINVAL;
13548 }
13549
13550 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
13551 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
13552
Ryan Hsucfef0ae2016-04-28 10:20:46 -070013553 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013554
13555 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
13556
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013557 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013558 err = -EBUSY;
13559 break;
13560 }
13561#endif
13562
13563 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013564 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013565 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
13566 return -EOPNOTSUPP;
13567 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013568 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013569 return err;
13570}
13571
13572/**
13573 * wlan_hdd_cfg80211_testmode() - test mode
13574 * @wiphy: Pointer to wiphy
13575 * @dev: Pointer to network device
13576 * @data: Data pointer
13577 * @len: Data length
13578 *
13579 * Return: 0 for success, non-zero for failure
13580 */
13581static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
13582#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
13583 struct wireless_dev *wdev,
13584#endif
13585 void *data, int len)
13586{
13587 int ret;
13588
13589 cds_ssr_protect(__func__);
13590 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
13591 cds_ssr_unprotect(__func__);
13592
13593 return ret;
13594}
13595
13596#if defined(QCA_WIFI_FTM)
13597/**
13598 * wlan_hdd_testmode_rx_event() - test mode rx event handler
13599 * @buf: Pointer to buffer
13600 * @buf_len: Buffer length
13601 *
13602 * Return: none
13603 */
13604void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
13605{
13606 struct sk_buff *skb;
13607 hdd_context_t *hdd_ctx;
13608
13609 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013610 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013611 return;
13612 }
13613
Anurag Chouhan6d760662016-02-20 16:05:43 +053013614 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013615 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013616 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013617 return;
13618 }
13619
13620 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
13621 buf_len, GFP_KERNEL);
13622 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013623 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013624 return;
13625 }
13626
13627 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
13628 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
13629 goto nla_put_failure;
13630
Ryan Hsucfef0ae2016-04-28 10:20:46 -070013631 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013632
13633 cfg80211_testmode_event(skb, GFP_KERNEL);
13634 return;
13635
13636nla_put_failure:
13637 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013638 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013639}
13640#endif
13641#endif /* CONFIG_NL80211_TESTMODE */
13642
13643#ifdef QCA_HT_2040_COEX
13644/**
13645 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
13646 * @wiphy: Pointer to wiphy
13647 * @dev: Pointer to network device
13648 * @chandef: Pointer to channel definition parameter
13649 *
13650 * Return: 0 for success, non-zero for failure
13651 */
13652static int
13653__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
13654 struct net_device *dev,
13655 struct cfg80211_chan_def *chandef)
13656{
13657 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13658 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013659 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013660 tSmeConfigParams sme_config;
13661 bool cbModeChange;
13662
Anurag Chouhan6d760662016-02-20 16:05:43 +053013663 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013664 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013665 return -EINVAL;
13666 }
13667
13668 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13669 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053013670 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013671 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013672
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013673 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013674 sme_get_config_param(pHddCtx->hHal, &sme_config);
13675 switch (chandef->width) {
13676 case NL80211_CHAN_WIDTH_20:
13677 if (sme_config.csrConfig.channelBondingMode24GHz !=
13678 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
13679 sme_config.csrConfig.channelBondingMode24GHz =
13680 eCSR_INI_SINGLE_CHANNEL_CENTERED;
13681 sme_update_config(pHddCtx->hHal, &sme_config);
13682 cbModeChange = true;
13683 }
13684 break;
13685
13686 case NL80211_CHAN_WIDTH_40:
13687 if (sme_config.csrConfig.channelBondingMode24GHz ==
13688 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
13689 if (NL80211_CHAN_HT40MINUS ==
13690 cfg80211_get_chandef_type(chandef))
13691 sme_config.csrConfig.channelBondingMode24GHz =
13692 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
13693 else
13694 sme_config.csrConfig.channelBondingMode24GHz =
13695 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
13696 sme_update_config(pHddCtx->hHal, &sme_config);
13697 cbModeChange = true;
13698 }
13699 break;
13700
13701 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013702 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013703 return -EINVAL;
13704 }
13705
13706 if (!cbModeChange)
13707 return 0;
13708
Krunal Sonib4326f22016-03-10 13:05:51 -080013709 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013710 return 0;
13711
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013712 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013713 sme_config.csrConfig.channelBondingMode24GHz);
13714
13715 /* Change SAP ht2040 mode */
13716 status = hdd_set_sap_ht2040_mode(pAdapter,
13717 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013718 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013719 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013720 return -EINVAL;
13721 }
13722
13723 return 0;
13724}
13725
13726/**
13727 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
13728 * @wiphy: Pointer to wiphy
13729 * @dev: Pointer to network device
13730 * @chandef: Pointer to channel definition parameter
13731 *
13732 * Return: 0 for success, non-zero for failure
13733 */
13734static int
13735wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
13736 struct net_device *dev,
13737 struct cfg80211_chan_def *chandef)
13738{
13739 int ret;
13740
13741 cds_ssr_protect(__func__);
13742 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
13743 cds_ssr_unprotect(__func__);
13744
13745 return ret;
13746}
13747#endif
13748
Abhishek Singh1bdb1572015-10-16 16:24:19 +053013749#ifdef CHANNEL_SWITCH_SUPPORTED
13750/**
13751 * __wlan_hdd_cfg80211_channel_switch()- function to switch
13752 * channel in SAP/GO
13753 * @wiphy: wiphy pointer
13754 * @dev: dev pointer.
13755 * @csa_params: Change channel params
13756 *
13757 * This function is called to switch channel in SAP/GO
13758 *
13759 * Return: 0 if success else return non zero
13760 */
13761static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
13762 struct net_device *dev,
13763 struct cfg80211_csa_settings *csa_params)
13764{
13765 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
13766 hdd_context_t *hdd_ctx;
13767 uint8_t channel;
13768 uint16_t freq;
13769 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080013770 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053013771
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013772 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053013773 csa_params->chandef.chan->center_freq);
13774
13775 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
13776 ret = wlan_hdd_validate_context(hdd_ctx);
13777
13778 if (0 != ret)
13779 return ret;
13780
Krunal Sonib4326f22016-03-10 13:05:51 -080013781 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
13782 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053013783 return -ENOTSUPP;
13784
13785 freq = csa_params->chandef.chan->center_freq;
13786 channel = cds_freq_to_chan(freq);
13787
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053013788 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
13789
13790 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053013791 return ret;
13792}
13793
13794/**
13795 * wlan_hdd_cfg80211_channel_switch()- function to switch
13796 * channel in SAP/GO
13797 * @wiphy: wiphy pointer
13798 * @dev: dev pointer.
13799 * @csa_params: Change channel params
13800 *
13801 * This function is called to switch channel in SAP/GO
13802 *
13803 * Return: 0 if success else return non zero
13804 */
13805static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
13806 struct net_device *dev,
13807 struct cfg80211_csa_settings *csa_params)
13808{
13809 int ret;
13810
13811 cds_ssr_protect(__func__);
13812 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
13813 cds_ssr_unprotect(__func__);
13814 return ret;
13815}
13816#endif
13817
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013818/**
13819 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
13820 * translation from NL to policy manager type
13821 * @type: Generic connection mode type defined in NL
13822 *
13823 *
13824 * This function provides the type translation
13825 *
13826 * Return: cds_con_mode enum
13827 */
13828enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
13829 enum nl80211_iftype type)
13830{
13831 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
13832 switch (type) {
13833 case NL80211_IFTYPE_STATION:
13834 mode = CDS_STA_MODE;
13835 break;
13836 case NL80211_IFTYPE_P2P_CLIENT:
13837 mode = CDS_P2P_CLIENT_MODE;
13838 break;
13839 case NL80211_IFTYPE_P2P_GO:
13840 mode = CDS_P2P_GO_MODE;
13841 break;
13842 case NL80211_IFTYPE_AP:
13843 mode = CDS_SAP_MODE;
13844 break;
13845 case NL80211_IFTYPE_ADHOC:
13846 mode = CDS_IBSS_MODE;
13847 break;
13848 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013849 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013850 type);
13851 }
13852 return mode;
13853}
13854
13855/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013856 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
13857 * @wiphy: Handle to struct wiphy to get handle to module context.
13858 * @chandef: Contains information about the capture channel to be set.
13859 *
13860 * This interface is called if and only if monitor mode interface alone is
13861 * active.
13862 *
13863 * Return: 0 success or error code on failure.
13864 */
13865static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
13866 struct cfg80211_chan_def *chandef)
13867{
13868 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
13869 hdd_adapter_t *adapter;
13870 hdd_station_ctx_t *sta_ctx;
13871 struct hdd_mon_set_ch_info *ch_info;
13872 QDF_STATUS status;
13873 tHalHandle hal_hdl;
13874 struct qdf_mac_addr bssid;
13875 tCsrRoamProfile roam_profile;
13876 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013877 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013878 int ret;
13879 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
13880
13881 ENTER();
13882
13883 ret = wlan_hdd_validate_context(hdd_ctx);
13884 if (ret)
13885 return ret;
13886
13887 hal_hdl = hdd_ctx->hHal;
13888
13889 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
13890 if (!adapter)
13891 return -EIO;
13892
13893 hdd_info("%s: set monitor mode Channel %d and freq %d",
13894 adapter->dev->name, chan_num, chandef->chan->center_freq);
13895
13896 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
13897 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013898 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
13899 roam_profile.ChannelInfo.numOfChannels = 1;
13900 roam_profile.phyMode = ch_info->phy_mode;
13901 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013902 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013903
13904 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
13905 QDF_MAC_ADDR_SIZE);
13906
13907 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070013908 /*
13909 * CDS api expects secondary channel for calculating
13910 * the channel params
13911 */
13912 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
13913 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
13914 if (chan_num >= 1 && chan_num <= 5)
13915 sec_ch = chan_num + 4;
13916 else if (chan_num >= 6 && chan_num <= 13)
13917 sec_ch = chan_num - 4;
13918 }
13919 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070013920 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
13921 &roam_profile);
13922 if (status) {
13923 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
13924 status);
13925 ret = qdf_status_to_os_return(status);
13926 return ret;
13927 }
13928 EXIT();
13929 return 0;
13930}
13931
13932/**
13933 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
13934 * @wiphy: Handle to struct wiphy to get handle to module context.
13935 * @chandef: Contains information about the capture channel to be set.
13936 *
13937 * This interface is called if and only if monitor mode interface alone is
13938 * active.
13939 *
13940 * Return: 0 success or error code on failure.
13941 */
13942static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
13943 struct cfg80211_chan_def *chandef)
13944{
13945 int ret;
13946
13947 cds_ssr_protect(__func__);
13948 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
13949 cds_ssr_unprotect(__func__);
13950 return ret;
13951}
13952
13953/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013954 * struct cfg80211_ops - cfg80211_ops
13955 *
13956 * @add_virtual_intf: Add virtual interface
13957 * @del_virtual_intf: Delete virtual interface
13958 * @change_virtual_intf: Change virtual interface
13959 * @change_station: Change station
13960 * @add_beacon: Add beacon in sap mode
13961 * @del_beacon: Delete beacon in sap mode
13962 * @set_beacon: Set beacon in sap mode
13963 * @start_ap: Start ap
13964 * @change_beacon: Change beacon
13965 * @stop_ap: Stop ap
13966 * @change_bss: Change bss
13967 * @add_key: Add key
13968 * @get_key: Get key
13969 * @del_key: Delete key
13970 * @set_default_key: Set default key
13971 * @set_channel: Set channel
13972 * @scan: Scan
13973 * @connect: Connect
13974 * @disconnect: Disconnect
13975 * @join_ibss = Join ibss
13976 * @leave_ibss = Leave ibss
13977 * @set_wiphy_params = Set wiphy params
13978 * @set_tx_power = Set tx power
13979 * @get_tx_power = get tx power
13980 * @remain_on_channel = Remain on channel
13981 * @cancel_remain_on_channel = Cancel remain on channel
13982 * @mgmt_tx = Tx management frame
13983 * @mgmt_tx_cancel_wait = Cancel management tx wait
13984 * @set_default_mgmt_key = Set default management key
13985 * @set_txq_params = Set tx queue parameters
13986 * @get_station = Get station
13987 * @set_power_mgmt = Set power management
13988 * @del_station = Delete station
13989 * @add_station = Add station
13990 * @set_pmksa = Set pmksa
13991 * @del_pmksa = Delete pmksa
13992 * @flush_pmksa = Flush pmksa
13993 * @update_ft_ies = Update FT IEs
13994 * @tdls_mgmt = Tdls management
13995 * @tdls_oper = Tdls operation
13996 * @set_rekey_data = Set rekey data
13997 * @sched_scan_start = Scheduled scan start
13998 * @sched_scan_stop = Scheduled scan stop
13999 * @resume = Resume wlan
14000 * @suspend = Suspend wlan
14001 * @set_mac_acl = Set mac acl
14002 * @testmode_cmd = Test mode command
14003 * @set_ap_chanwidth = Set AP channel bandwidth
14004 * @dump_survey = Dump survey
14005 * @key_mgmt_set_pmk = Set pmk key management
14006 */
14007static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
14008 .add_virtual_intf = wlan_hdd_add_virtual_intf,
14009 .del_virtual_intf = wlan_hdd_del_virtual_intf,
14010 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
14011 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014012 .start_ap = wlan_hdd_cfg80211_start_ap,
14013 .change_beacon = wlan_hdd_cfg80211_change_beacon,
14014 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014015 .change_bss = wlan_hdd_cfg80211_change_bss,
14016 .add_key = wlan_hdd_cfg80211_add_key,
14017 .get_key = wlan_hdd_cfg80211_get_key,
14018 .del_key = wlan_hdd_cfg80211_del_key,
14019 .set_default_key = wlan_hdd_cfg80211_set_default_key,
14020 .scan = wlan_hdd_cfg80211_scan,
14021 .connect = wlan_hdd_cfg80211_connect,
14022 .disconnect = wlan_hdd_cfg80211_disconnect,
14023 .join_ibss = wlan_hdd_cfg80211_join_ibss,
14024 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
14025 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
14026 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
14027 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
14028 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
14029 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
14030 .mgmt_tx = wlan_hdd_mgmt_tx,
14031 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
14032 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
14033 .set_txq_params = wlan_hdd_set_txq_params,
14034 .get_station = wlan_hdd_cfg80211_get_station,
14035 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
14036 .del_station = wlan_hdd_cfg80211_del_station,
14037 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014038 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
14039 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
14040 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080014041#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014042 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
14043#endif
14044#ifdef FEATURE_WLAN_TDLS
14045 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
14046 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
14047#endif
14048#ifdef WLAN_FEATURE_GTK_OFFLOAD
14049 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
14050#endif /* WLAN_FEATURE_GTK_OFFLOAD */
14051#ifdef FEATURE_WLAN_SCAN_PNO
14052 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
14053 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
14054#endif /*FEATURE_WLAN_SCAN_PNO */
14055 .resume = wlan_hdd_cfg80211_resume_wlan,
14056 .suspend = wlan_hdd_cfg80211_suspend_wlan,
14057 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
14058#ifdef WLAN_NL80211_TESTMODE
14059 .testmode_cmd = wlan_hdd_cfg80211_testmode,
14060#endif
14061#ifdef QCA_HT_2040_COEX
14062 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
14063#endif
14064 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014065#ifdef CHANNEL_SWITCH_SUPPORTED
14066 .channel_switch = wlan_hdd_cfg80211_channel_switch,
14067#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014068 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053014069#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
14070 defined(CFG80211_ABORT_SCAN)
14071 .abort_scan = wlan_hdd_cfg80211_abort_scan,
14072#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014073};