blob: d4517ef32b32dfdc7ac3abb29cab856486d306b7 [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"
Agrawal Ashish65634612016-08-18 13:24:32 +053077#include "sap_api.h"
Agrawal Ashish21ba2572016-09-03 16:40:10 +053078#include "csr_api.h"
Agrawal Ashish467dde42016-09-08 18:44:22 +053079#include "pld_common.h"
Agrawal Ashish65634612016-08-18 13:24:32 +053080
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080081
82#ifdef FEATURE_WLAN_EXTSCAN
83#include "wlan_hdd_ext_scan.h"
84#endif
85
86#ifdef WLAN_FEATURE_LINK_LAYER_STATS
87#include "wlan_hdd_stats.h"
88#endif
89#include "cds_concurrency.h"
90#include "qwlan_version.h"
91#include "wlan_hdd_memdump.h"
92
93#include "wlan_hdd_ocb.h"
Manikandan Mohan5356c2b2016-04-03 15:51:35 -070094#include "wlan_hdd_tsf.h"
Manikandan Mohanb6315dd2016-05-10 16:16:36 -070095#include "ol_txrx.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080096
Ravi Joshideb5a8d2015-11-09 19:11:43 -080097#include "wlan_hdd_subnet_detect.h"
Abhishek Singh3e6172f2016-05-04 16:56:48 +053098#include <wlan_hdd_regulatory.h>
Jeff Johnson2b0a7b82016-05-18 15:08:02 -070099#include "wlan_hdd_lpass.h"
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -0700100#include "wlan_hdd_nan_datapath.h"
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +0530101#include "wlan_hdd_disa.h"
Ravi Joshideb5a8d2015-11-09 19:11:43 -0800102
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800103#define g_mode_rates_size (12)
104#define a_mode_rates_size (8)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800105#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
106 ((uintptr_t)OFFSET_OF(tSirBssDescription, ieFields)))
107
108/*
109 * Android CTS verifier needs atleast this much wait time (in msec)
110 */
111#define MAX_REMAIN_ON_CHANNEL_DURATION (5000)
112
113/*
114 * Refer @tCfgProtection structure for definition of the bit map.
115 * below value is obtained by setting the following bit-fields.
116 * enable obss, fromllb, overlapOBSS and overlapFromllb protection.
117 */
118#define IBSS_CFG_PROTECTION_ENABLE_MASK 0x8282
119
120#define HDD2GHZCHAN(freq, chan, flag) { \
121 .band = IEEE80211_BAND_2GHZ, \
122 .center_freq = (freq), \
123 .hw_value = (chan), \
124 .flags = (flag), \
125 .max_antenna_gain = 0, \
126 .max_power = 30, \
127}
128
129#define HDD5GHZCHAN(freq, chan, flag) { \
130 .band = IEEE80211_BAND_5GHZ, \
131 .center_freq = (freq), \
132 .hw_value = (chan), \
133 .flags = (flag), \
134 .max_antenna_gain = 0, \
135 .max_power = 30, \
136}
137
138#define HDD_G_MODE_RATETAB(rate, rate_id, flag) \
139 { \
140 .bitrate = rate, \
141 .hw_value = rate_id, \
142 .flags = flag, \
143 }
144
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800145#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03
146#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800147
148#define HDD_CHANNEL_14 14
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800149
Agrawal Ashish65634612016-08-18 13:24:32 +0530150#define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \
151 mode <= DFS_MODE_DEPRIORITIZE))
152#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \
153 || (channel >= 36 && channel <= 184))
154
Peng Xu4d67c8f2015-10-16 16:02:26 -0700155#define MAX_TXPOWER_SCALE 4
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +0530156#define CDS_MAX_FEATURE_SET 8
Peng Xu4d67c8f2015-10-16 16:02:26 -0700157
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800158static const u32 hdd_cipher_suites[] = {
159 WLAN_CIPHER_SUITE_WEP40,
160 WLAN_CIPHER_SUITE_WEP104,
161 WLAN_CIPHER_SUITE_TKIP,
162#ifdef FEATURE_WLAN_ESE
163#define WLAN_CIPHER_SUITE_BTK 0x004096fe /* use for BTK */
164#define WLAN_CIPHER_SUITE_KRK 0x004096ff /* use for KRK */
165 WLAN_CIPHER_SUITE_BTK,
166 WLAN_CIPHER_SUITE_KRK,
167 WLAN_CIPHER_SUITE_CCMP,
168#else
169 WLAN_CIPHER_SUITE_CCMP,
170#endif
171#ifdef FEATURE_WLAN_WAPI
172 WLAN_CIPHER_SUITE_SMS4,
173#endif
174#ifdef WLAN_FEATURE_11W
175 WLAN_CIPHER_SUITE_AES_CMAC,
176#endif
177};
178
Abhishek Singhf512bf32016-05-04 16:47:46 +0530179static const struct ieee80211_channel hdd_channels_2_4_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800180 HDD2GHZCHAN(2412, 1, 0),
181 HDD2GHZCHAN(2417, 2, 0),
182 HDD2GHZCHAN(2422, 3, 0),
183 HDD2GHZCHAN(2427, 4, 0),
184 HDD2GHZCHAN(2432, 5, 0),
185 HDD2GHZCHAN(2437, 6, 0),
186 HDD2GHZCHAN(2442, 7, 0),
187 HDD2GHZCHAN(2447, 8, 0),
188 HDD2GHZCHAN(2452, 9, 0),
189 HDD2GHZCHAN(2457, 10, 0),
190 HDD2GHZCHAN(2462, 11, 0),
191 HDD2GHZCHAN(2467, 12, 0),
192 HDD2GHZCHAN(2472, 13, 0),
193 HDD2GHZCHAN(2484, 14, 0),
194};
195
Abhishek Singhf512bf32016-05-04 16:47:46 +0530196static const struct ieee80211_channel hdd_channels_5_ghz[] = {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800197 HDD5GHZCHAN(5180, 36, 0),
198 HDD5GHZCHAN(5200, 40, 0),
199 HDD5GHZCHAN(5220, 44, 0),
200 HDD5GHZCHAN(5240, 48, 0),
201 HDD5GHZCHAN(5260, 52, 0),
202 HDD5GHZCHAN(5280, 56, 0),
203 HDD5GHZCHAN(5300, 60, 0),
204 HDD5GHZCHAN(5320, 64, 0),
205 HDD5GHZCHAN(5500, 100, 0),
206 HDD5GHZCHAN(5520, 104, 0),
207 HDD5GHZCHAN(5540, 108, 0),
208 HDD5GHZCHAN(5560, 112, 0),
209 HDD5GHZCHAN(5580, 116, 0),
210 HDD5GHZCHAN(5600, 120, 0),
211 HDD5GHZCHAN(5620, 124, 0),
212 HDD5GHZCHAN(5640, 128, 0),
213 HDD5GHZCHAN(5660, 132, 0),
214 HDD5GHZCHAN(5680, 136, 0),
215 HDD5GHZCHAN(5700, 140, 0),
216 HDD5GHZCHAN(5720, 144, 0),
217 HDD5GHZCHAN(5745, 149, 0),
218 HDD5GHZCHAN(5765, 153, 0),
219 HDD5GHZCHAN(5785, 157, 0),
220 HDD5GHZCHAN(5805, 161, 0),
221 HDD5GHZCHAN(5825, 165, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800222 HDD5GHZCHAN(5852, 170, 0),
223 HDD5GHZCHAN(5855, 171, 0),
224 HDD5GHZCHAN(5860, 172, 0),
225 HDD5GHZCHAN(5865, 173, 0),
226 HDD5GHZCHAN(5870, 174, 0),
227 HDD5GHZCHAN(5875, 175, 0),
228 HDD5GHZCHAN(5880, 176, 0),
229 HDD5GHZCHAN(5885, 177, 0),
230 HDD5GHZCHAN(5890, 178, 0),
231 HDD5GHZCHAN(5895, 179, 0),
232 HDD5GHZCHAN(5900, 180, 0),
233 HDD5GHZCHAN(5905, 181, 0),
234 HDD5GHZCHAN(5910, 182, 0),
235 HDD5GHZCHAN(5915, 183, 0),
236 HDD5GHZCHAN(5920, 184, 0),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800237};
238
239static struct ieee80211_rate g_mode_rates[] = {
240 HDD_G_MODE_RATETAB(10, 0x1, 0),
241 HDD_G_MODE_RATETAB(20, 0x2, 0),
242 HDD_G_MODE_RATETAB(55, 0x4, 0),
243 HDD_G_MODE_RATETAB(110, 0x8, 0),
244 HDD_G_MODE_RATETAB(60, 0x10, 0),
245 HDD_G_MODE_RATETAB(90, 0x20, 0),
246 HDD_G_MODE_RATETAB(120, 0x40, 0),
247 HDD_G_MODE_RATETAB(180, 0x80, 0),
248 HDD_G_MODE_RATETAB(240, 0x100, 0),
249 HDD_G_MODE_RATETAB(360, 0x200, 0),
250 HDD_G_MODE_RATETAB(480, 0x400, 0),
251 HDD_G_MODE_RATETAB(540, 0x800, 0),
252};
253
254static struct ieee80211_rate a_mode_rates[] = {
255 HDD_G_MODE_RATETAB(60, 0x10, 0),
256 HDD_G_MODE_RATETAB(90, 0x20, 0),
257 HDD_G_MODE_RATETAB(120, 0x40, 0),
258 HDD_G_MODE_RATETAB(180, 0x80, 0),
259 HDD_G_MODE_RATETAB(240, 0x100, 0),
260 HDD_G_MODE_RATETAB(360, 0x200, 0),
261 HDD_G_MODE_RATETAB(480, 0x400, 0),
262 HDD_G_MODE_RATETAB(540, 0x800, 0),
263};
264
265static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530266 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800267 .n_channels = ARRAY_SIZE(hdd_channels_2_4_ghz),
268 .band = IEEE80211_BAND_2GHZ,
269 .bitrates = g_mode_rates,
270 .n_bitrates = g_mode_rates_size,
271 .ht_cap.ht_supported = 1,
272 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
273 | IEEE80211_HT_CAP_GRN_FLD
274 | IEEE80211_HT_CAP_DSSSCCK40
275 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
276 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
277 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
278 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
279 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
280 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
281 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
282};
283
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800284static struct ieee80211_supported_band wlan_hdd_band_5_ghz = {
Abhishek Singhf512bf32016-05-04 16:47:46 +0530285 .channels = NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800286 .n_channels = ARRAY_SIZE(hdd_channels_5_ghz),
287 .band = IEEE80211_BAND_5GHZ,
288 .bitrates = a_mode_rates,
289 .n_bitrates = a_mode_rates_size,
290 .ht_cap.ht_supported = 1,
291 .ht_cap.cap = IEEE80211_HT_CAP_SGI_20
292 | IEEE80211_HT_CAP_GRN_FLD
293 | IEEE80211_HT_CAP_DSSSCCK40
294 | IEEE80211_HT_CAP_LSIG_TXOP_PROT
295 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SUP_WIDTH_20_40,
296 .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
297 .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
298 .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
299 .ht_cap.mcs.rx_highest = cpu_to_le16(72),
300 .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
301 .vht_cap.vht_supported = 1,
302};
303
304/* This structure contain information what kind of frame are expected in
305 TX/RX direction for each kind of interface */
306static const struct ieee80211_txrx_stypes
307 wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = {
308 [NL80211_IFTYPE_STATION] = {
309 .tx = 0xffff,
310 .rx = BIT(SIR_MAC_MGMT_ACTION) |
311 BIT(SIR_MAC_MGMT_PROBE_REQ),
312 },
313 [NL80211_IFTYPE_AP] = {
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_ADHOC] = {
324 .tx = 0xffff,
325 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
326 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
327 BIT(SIR_MAC_MGMT_PROBE_REQ) |
328 BIT(SIR_MAC_MGMT_DISASSOC) |
329 BIT(SIR_MAC_MGMT_AUTH) |
330 BIT(SIR_MAC_MGMT_DEAUTH) |
331 BIT(SIR_MAC_MGMT_ACTION),
332 },
333 [NL80211_IFTYPE_P2P_CLIENT] = {
334 .tx = 0xffff,
335 .rx = BIT(SIR_MAC_MGMT_ACTION) |
336 BIT(SIR_MAC_MGMT_PROBE_REQ),
337 },
338 [NL80211_IFTYPE_P2P_GO] = {
339 /* This is also same as for SoftAP */
340 .tx = 0xffff,
341 .rx = BIT(SIR_MAC_MGMT_ASSOC_REQ) |
342 BIT(SIR_MAC_MGMT_REASSOC_REQ) |
343 BIT(SIR_MAC_MGMT_PROBE_REQ) |
344 BIT(SIR_MAC_MGMT_DISASSOC) |
345 BIT(SIR_MAC_MGMT_AUTH) |
346 BIT(SIR_MAC_MGMT_DEAUTH) |
347 BIT(SIR_MAC_MGMT_ACTION),
348 },
349};
350
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800351/* Interface limits and combinations registered by the driver */
352
353/* STA ( + STA ) combination */
354static const struct ieee80211_iface_limit
355 wlan_hdd_sta_iface_limit[] = {
356 {
357 .max = 3, /* p2p0 is a STA as well */
358 .types = BIT(NL80211_IFTYPE_STATION),
359 },
360};
361
362/* ADHOC (IBSS) limit */
363static const struct ieee80211_iface_limit
364 wlan_hdd_adhoc_iface_limit[] = {
365 {
366 .max = 1,
367 .types = BIT(NL80211_IFTYPE_STATION),
368 },
369 {
370 .max = 1,
371 .types = BIT(NL80211_IFTYPE_ADHOC),
372 },
373};
374
375/* AP ( + AP ) combination */
376static const struct ieee80211_iface_limit
377 wlan_hdd_ap_iface_limit[] = {
378 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530379 .max = (QDF_MAX_NO_OF_SAP_MODE + SAP_MAX_OBSS_STA_CNT),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800380 .types = BIT(NL80211_IFTYPE_AP),
381 },
382};
383
384/* P2P limit */
385static const struct ieee80211_iface_limit
386 wlan_hdd_p2p_iface_limit[] = {
387 {
388 .max = 1,
389 .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
390 },
391 {
392 .max = 1,
393 .types = BIT(NL80211_IFTYPE_P2P_GO),
394 },
395};
396
397static const struct ieee80211_iface_limit
398 wlan_hdd_sta_ap_iface_limit[] = {
399 {
400 /* We need 1 extra STA interface for OBSS scan when SAP starts
401 * with HT40 in STA+SAP concurrency mode
402 */
403 .max = (1 + SAP_MAX_OBSS_STA_CNT),
404 .types = BIT(NL80211_IFTYPE_STATION),
405 },
406 {
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530407 .max = QDF_MAX_NO_OF_SAP_MODE,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800408 .types = BIT(NL80211_IFTYPE_AP),
409 },
410};
411
412/* STA + P2P combination */
413static const struct ieee80211_iface_limit
414 wlan_hdd_sta_p2p_iface_limit[] = {
415 {
416 /* One reserved for dedicated P2PDEV usage */
417 .max = 2,
418 .types = BIT(NL80211_IFTYPE_STATION)
419 },
420 {
421 /* Support for two identical (GO + GO or CLI + CLI)
422 * or dissimilar (GO + CLI) P2P interfaces
423 */
424 .max = 2,
425 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
426 },
427};
428
429/* STA + AP + P2PGO combination */
430static const struct ieee80211_iface_limit
431wlan_hdd_sta_ap_p2pgo_iface_limit[] = {
432 /* Support for AP+P2PGO interfaces */
433 {
434 .max = 2,
435 .types = BIT(NL80211_IFTYPE_STATION)
436 },
437 {
438 .max = 1,
439 .types = BIT(NL80211_IFTYPE_P2P_GO)
440 },
441 {
442 .max = 1,
443 .types = BIT(NL80211_IFTYPE_AP)
444 }
445};
446
447/* SAP + P2P combination */
448static const struct ieee80211_iface_limit
449wlan_hdd_sap_p2p_iface_limit[] = {
450 {
451 /* 1 dedicated for p2p0 which is a STA type */
452 .max = 1,
453 .types = BIT(NL80211_IFTYPE_STATION)
454 },
455 {
456 /* The p2p interface in SAP+P2P can be GO/CLI.
457 * The p2p connection can be formed on p2p0 or p2p-p2p0-x.
458 */
459 .max = 1,
460 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
461 },
462 {
463 /* SAP+GO to support only one SAP interface */
464 .max = 1,
465 .types = BIT(NL80211_IFTYPE_AP)
466 }
467};
468
469/* P2P + P2P combination */
470static const struct ieee80211_iface_limit
471wlan_hdd_p2p_p2p_iface_limit[] = {
472 {
473 /* 1 dedicated for p2p0 which is a STA type */
474 .max = 1,
475 .types = BIT(NL80211_IFTYPE_STATION)
476 },
477 {
478 /* The p2p interface in P2P+P2P can be GO/CLI.
479 * For P2P+P2P, the new interfaces are formed on p2p-p2p0-x.
480 */
481 .max = 2,
482 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
483 },
484};
485
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -0700486static const struct ieee80211_iface_limit
487 wlan_hdd_mon_iface_limit[] = {
488 {
489 .max = 3, /* Monitor interface */
490 .types = BIT(NL80211_IFTYPE_MONITOR),
491 },
492};
493
494static struct ieee80211_iface_combination
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800495 wlan_hdd_iface_combination[] = {
496 /* STA */
497 {
498 .limits = wlan_hdd_sta_iface_limit,
499 .num_different_channels = 2,
500 .max_interfaces = 3,
501 .n_limits = ARRAY_SIZE(wlan_hdd_sta_iface_limit),
502 },
503 /* ADHOC */
504 {
505 .limits = wlan_hdd_adhoc_iface_limit,
Krunal Soni2c68f232015-10-26 20:52:51 -0700506 .num_different_channels = 2,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800507 .max_interfaces = 2,
508 .n_limits = ARRAY_SIZE(wlan_hdd_adhoc_iface_limit),
509 },
510 /* AP */
511 {
512 .limits = wlan_hdd_ap_iface_limit,
513 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530514 .max_interfaces = (SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800515 .n_limits = ARRAY_SIZE(wlan_hdd_ap_iface_limit),
516 },
517 /* P2P */
518 {
519 .limits = wlan_hdd_p2p_iface_limit,
520 .num_different_channels = 2,
521 .max_interfaces = 2,
522 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
523 },
524 /* STA + AP */
525 {
526 .limits = wlan_hdd_sta_ap_iface_limit,
527 .num_different_channels = 2,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530528 .max_interfaces = (1 + SAP_MAX_OBSS_STA_CNT + QDF_MAX_NO_OF_SAP_MODE),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800529 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
530 .beacon_int_infra_match = true,
531 },
532 /* STA + P2P */
533 {
534 .limits = wlan_hdd_sta_p2p_iface_limit,
535 .num_different_channels = 2,
536 /* one interface reserved for P2PDEV dedicated usage */
537 .max_interfaces = 4,
538 .n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
539 .beacon_int_infra_match = true,
540 },
541 /* STA + P2P GO + SAP */
542 {
543 .limits = wlan_hdd_sta_ap_p2pgo_iface_limit,
544 /* we can allow 3 channels for three different persona
545 * but due to firmware limitation, allow max 2 concrnt channels.
546 */
547 .num_different_channels = 2,
548 /* one interface reserved for P2PDEV dedicated usage */
549 .max_interfaces = 4,
550 .n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2pgo_iface_limit),
551 .beacon_int_infra_match = true,
552 },
553 /* SAP + P2P */
554 {
555 .limits = wlan_hdd_sap_p2p_iface_limit,
556 .num_different_channels = 2,
557 /* 1-p2p0 + 1-SAP + 1-P2P (on p2p0 or p2p-p2p0-x) */
558 .max_interfaces = 3,
559 .n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
560 .beacon_int_infra_match = true,
561 },
562 /* P2P + P2P */
563 {
564 .limits = wlan_hdd_p2p_p2p_iface_limit,
565 .num_different_channels = 2,
566 /* 1-p2p0 + 2-P2P (on p2p-p2p0-x) */
567 .max_interfaces = 3,
568 .n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
569 .beacon_int_infra_match = true,
570 },
Arun Khandavallifae92942016-08-01 13:31:08 +0530571 /* Monitor */
572 {
573 .limits = wlan_hdd_mon_iface_limit,
574 .max_interfaces = 3,
575 .num_different_channels = 2,
576 .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
577 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800578};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800579
580static struct cfg80211_ops wlan_hdd_cfg80211_ops;
Arun Khandavalli2476ef52016-04-26 20:19:43 +0530581struct hdd_bpf_context bpf_context;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800582
583#ifdef WLAN_NL80211_TESTMODE
584enum wlan_hdd_tm_attr {
585 WLAN_HDD_TM_ATTR_INVALID = 0,
586 WLAN_HDD_TM_ATTR_CMD = 1,
587 WLAN_HDD_TM_ATTR_DATA = 2,
588 WLAN_HDD_TM_ATTR_STREAM_ID = 3,
589 WLAN_HDD_TM_ATTR_TYPE = 4,
590 /* keep last */
591 WLAN_HDD_TM_ATTR_AFTER_LAST,
592 WLAN_HDD_TM_ATTR_MAX = WLAN_HDD_TM_ATTR_AFTER_LAST - 1,
593};
594
595enum wlan_hdd_tm_cmd {
596 WLAN_HDD_TM_CMD_WLAN_FTM = 0,
597 WLAN_HDD_TM_CMD_WLAN_HB = 1,
598};
599
600#define WLAN_HDD_TM_DATA_MAX_LEN 5000
601
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +0530602enum wlan_hdd_vendor_ie_access_policy {
603 WLAN_HDD_VENDOR_IE_ACCESS_NONE = 0,
604 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED,
605};
606
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800607static const struct nla_policy wlan_hdd_tm_policy[WLAN_HDD_TM_ATTR_MAX + 1] = {
608 [WLAN_HDD_TM_ATTR_CMD] = {.type = NLA_U32},
609 [WLAN_HDD_TM_ATTR_DATA] = {.type = NLA_BINARY,
610 .len = WLAN_HDD_TM_DATA_MAX_LEN},
611};
612#endif /* WLAN_NL80211_TESTMODE */
613
614#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
615static const struct wiphy_wowlan_support wowlan_support_cfg80211_init = {
616 .flags = WIPHY_WOWLAN_MAGIC_PKT,
617 .n_patterns = WOWL_MAX_PTRNS_ALLOWED,
618 .pattern_min_len = 1,
619 .pattern_max_len = WOWL_PTRN_MAX_SIZE,
620};
621#endif
622
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800623/**
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530624 * hdd_add_channel_switch_support()- Adds Channel Switch flag if supported
625 * @flags: Pointer to the flags to Add channel switch flag.
626 *
627 * This Function adds Channel Switch support flag, if channel switch is
628 * supported by kernel.
629 * Return: void.
630 */
631#ifdef CHANNEL_SWITCH_SUPPORTED
632static inline void hdd_add_channel_switch_support(uint32_t *flags)
633{
Krishna Kumaar Natarajan8a8df262015-12-04 11:43:46 -0800634 *flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530635 return;
636}
637#else
638static inline void hdd_add_channel_switch_support(uint32_t *flags)
639{
640 return;
641}
642#endif
643
Manikandan Mohan22b83722015-12-15 15:03:23 -0800644#ifdef FEATURE_WLAN_TDLS
645
646/* TDLS capabilities params */
647#define PARAM_MAX_TDLS_SESSION \
648 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS
649#define PARAM_TDLS_FEATURE_SUPPORT \
650 QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED
651
Abhishek Singh1bdb1572015-10-16 16:24:19 +0530652/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800653 * __wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
654 * @wiphy: WIPHY structure pointer
655 * @wdev: Wireless device structure pointer
656 * @data: Pointer to the data received
657 * @data_len: Length of the data received
658 *
659 * This function provides TDLS capabilities
660 *
661 * Return: 0 on success and errno on failure
662 */
663static int __wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
664 struct wireless_dev *wdev,
665 const void *data,
666 int data_len)
667{
668 int status;
669 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
670 struct sk_buff *skb;
671 uint32_t set = 0;
672
Jeff Johnson1f61b612016-02-12 16:28:33 -0800673 ENTER_DEV(wdev->netdev);
674
Anurag Chouhan6d760662016-02-20 16:05:43 +0530675 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800676 hdd_err("Command not allowed in FTM mode");
677 return -EPERM;
678 }
679
680 status = wlan_hdd_validate_context(hdd_ctx);
681 if (status)
682 return status;
683
684 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, (2 * sizeof(u32)) +
685 NLMSG_HDRLEN);
686 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -0700687 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800688 goto fail;
689 }
690
691 if (false == hdd_ctx->config->fEnableTDLSSupport) {
Jeff Johnson020db452016-06-29 14:37:26 -0700692 hdd_err("TDLS feature not Enabled or Not supported in FW");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800693 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION, 0) ||
694 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT, 0)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700695 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800696 goto fail;
697 }
698 } else {
699 set = set | WIFI_TDLS_SUPPORT;
700 set = set | (hdd_ctx->config->fTDLSExternalControl ?
701 WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT : 0);
702 set = set | (hdd_ctx->config->fEnableTDLSOffChannel ?
703 WIIF_TDLS_OFFCHANNEL_SUPPORT : 0);
Jeff Johnson020db452016-06-29 14:37:26 -0700704 hdd_notice("TDLS Feature supported value %x", set);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800705 if (nla_put_u32(skb, PARAM_MAX_TDLS_SESSION,
706 hdd_ctx->max_num_tdls_sta) ||
707 nla_put_u32(skb, PARAM_TDLS_FEATURE_SUPPORT,
708 set)) {
Jeff Johnson020db452016-06-29 14:37:26 -0700709 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800710 goto fail;
711 }
712 }
713 return cfg80211_vendor_cmd_reply(skb);
714fail:
715 if (skb)
716 kfree_skb(skb);
717 return -EINVAL;
718}
719
720/**
721 * wlan_hdd_cfg80211_get_tdls_capabilities() - Provide TDLS Capabilites.
722 * @wiphy: WIPHY structure pointer
723 * @wdev: Wireless device structure pointer
724 * @data: Pointer to the data received
725 * @data_len: Length of the data received
726 *
727 * This function provides TDLS capabilities
728 *
729 * Return: 0 on success and errno on failure
730 */
731static int
732wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy,
733 struct wireless_dev *wdev,
734 const void *data,
735 int data_len)
736{
737 int ret;
738
739 cds_ssr_protect(__func__);
740 ret = __wlan_hdd_cfg80211_get_tdls_capabilities(wiphy, wdev,
741 data, data_len);
742 cds_ssr_unprotect(__func__);
743
744 return ret;
745}
746#endif
747
748#ifdef QCA_HT_2040_COEX
749static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
750#endif
751
752#if defined(FEATURE_WLAN_CH_AVOID) || defined(FEATURE_WLAN_FORCE_SAP_SCC)
753/*
754 * FUNCTION: wlan_hdd_send_avoid_freq_event
755 * This is called when wlan driver needs to send vendor specific
756 * avoid frequency range event to userspace
757 */
758int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx,
759 tHddAvoidFreqList *pAvoidFreqList)
760{
761 struct sk_buff *vendor_event;
762
763 ENTER();
764
765 if (!pHddCtx) {
Jeff Johnson020db452016-06-29 14:37:26 -0700766 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800767 return -EINVAL;
768 }
769
770 if (!pAvoidFreqList) {
Jeff Johnson020db452016-06-29 14:37:26 -0700771 hdd_err("pAvoidFreqList is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800772 return -EINVAL;
773 }
774
775 vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy,
776 NULL,
777 sizeof(tHddAvoidFreqList),
778 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX,
779 GFP_KERNEL);
780 if (!vendor_event) {
Jeff Johnson020db452016-06-29 14:37:26 -0700781 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800782 return -EINVAL;
783 }
784
785 memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)),
786 (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList));
787
788 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
789
790 EXIT();
791 return 0;
792}
793#endif /* FEATURE_WLAN_CH_AVOID || FEATURE_WLAN_FORCE_SAP_SCC */
794
795/* vendor specific events */
796static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] = {
797#ifdef FEATURE_WLAN_CH_AVOID
798 [QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX] = {
799 .vendor_id =
800 QCA_NL80211_VENDOR_ID,
801 .subcmd =
802 QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY
803 },
804#endif /* FEATURE_WLAN_CH_AVOID */
805
806#ifdef WLAN_FEATURE_NAN
807 [QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX] = {
808 .vendor_id =
809 QCA_NL80211_VENDOR_ID,
810 .subcmd =
811 QCA_NL80211_VENDOR_SUBCMD_NAN
812 },
813#endif
814
815#ifdef WLAN_FEATURE_STATS_EXT
816 [QCA_NL80211_VENDOR_SUBCMD_STATS_EXT_INDEX] = {
817 .vendor_id =
818 QCA_NL80211_VENDOR_ID,
819 .subcmd =
820 QCA_NL80211_VENDOR_SUBCMD_STATS_EXT
821 },
822#endif /* WLAN_FEATURE_STATS_EXT */
823#ifdef FEATURE_WLAN_EXTSCAN
824 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START_INDEX] = {
825 .vendor_id =
826 QCA_NL80211_VENDOR_ID,
827 .subcmd =
828 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START
829 },
830 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP_INDEX] = {
831 .vendor_id =
832 QCA_NL80211_VENDOR_ID,
833 .subcmd =
834 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP
835 },
836 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES_INDEX] = {
837 .
838 vendor_id
839 =
840 QCA_NL80211_VENDOR_ID,
841 .subcmd =
842 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES
843 },
844 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS_INDEX] = {
845 .
846 vendor_id
847 =
848 QCA_NL80211_VENDOR_ID,
849 .
850 subcmd =
851 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS
852 },
853 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE_INDEX] = {
854 .
855 vendor_id
856 =
857 QCA_NL80211_VENDOR_ID,
858 .
859 subcmd
860 =
861 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_RESULTS_AVAILABLE
862 },
863 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT_INDEX] = {
864 .
865 vendor_id
866 =
867 QCA_NL80211_VENDOR_ID,
868 .subcmd =
869 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_FULL_SCAN_RESULT
870 },
871 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT_INDEX] = {
872 .vendor_id =
873 QCA_NL80211_VENDOR_ID,
874 .subcmd =
875 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SCAN_EVENT
876 },
877 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND_INDEX] = {
878 .
879 vendor_id
880 =
881 QCA_NL80211_VENDOR_ID,
882 .subcmd =
883 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_FOUND
884 },
885 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST_INDEX] = {
886 .
887 vendor_id
888 =
889 QCA_NL80211_VENDOR_ID,
890 .subcmd =
891 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST
892 },
893 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST_INDEX] = {
894 .
895 vendor_id
896 =
897 QCA_NL80211_VENDOR_ID,
898 .
899 subcmd
900 =
901 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST
902 },
903 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE_INDEX] = {
904 .
905 vendor_id
906 =
907 QCA_NL80211_VENDOR_ID,
908 .
909 subcmd =
910 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SIGNIFICANT_CHANGE
911 },
912 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE_INDEX] = {
913 .
914 vendor_id
915 =
916 QCA_NL80211_VENDOR_ID,
917 .
918 subcmd
919 =
920 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE
921 },
922 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE_INDEX] = {
923 .
924 vendor_id
925 =
926 QCA_NL80211_VENDOR_ID,
927 .
928 subcmd
929 =
930 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE
931 },
932 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND_INDEX] = {
933 .vendor_id = QCA_NL80211_VENDOR_ID,
934 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_FOUND
935 },
936 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST_INDEX] = {
937 .vendor_id = QCA_NL80211_VENDOR_ID,
938 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_SSID_LOST
939 },
940#endif /* FEATURE_WLAN_EXTSCAN */
941
942#ifdef WLAN_FEATURE_LINK_LAYER_STATS
943 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET_INDEX] = {
944 .vendor_id =
945 QCA_NL80211_VENDOR_ID,
946 .subcmd =
947 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET
948 },
949 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET_INDEX] = {
950 .vendor_id =
951 QCA_NL80211_VENDOR_ID,
952 .subcmd =
953 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET
954 },
955 [QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR_INDEX] = {
956 .vendor_id =
957 QCA_NL80211_VENDOR_ID,
958 .subcmd =
959 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR
960 },
961 [QCA_NL80211_VENDOR_SUBCMD_LL_RADIO_STATS_INDEX] = {
962 .vendor_id =
963 QCA_NL80211_VENDOR_ID,
964 .subcmd =
965 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS
966 },
967 [QCA_NL80211_VENDOR_SUBCMD_LL_IFACE_STATS_INDEX] = {
968 .vendor_id =
969 QCA_NL80211_VENDOR_ID,
970 .subcmd =
971 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS
972 },
973 [QCA_NL80211_VENDOR_SUBCMD_LL_PEER_INFO_STATS_INDEX] = {
974 .vendor_id =
975 QCA_NL80211_VENDOR_ID,
976 .subcmd =
977 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS
978 },
979#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
980 [QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE_CHANGE_INDEX] = {
981 .vendor_id =
982 QCA_NL80211_VENDOR_ID,
983 .subcmd =
984 QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE
985 },
986 [QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX] = {
987 .vendor_id = QCA_NL80211_VENDOR_ID,
988 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS
989 },
990#ifdef WLAN_FEATURE_ROAM_OFFLOAD
991 [QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX] = {
992 .vendor_id =
993 QCA_NL80211_VENDOR_ID,
994 .subcmd =
995 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH
996 },
997#endif
998 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED_INDEX] = {
999 .vendor_id =
1000 QCA_NL80211_VENDOR_ID,
1001 .subcmd =
1002 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED
1003 },
1004 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED_INDEX] = {
1005 .vendor_id =
1006 QCA_NL80211_VENDOR_ID,
1007 .subcmd =
1008 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED
1009 },
1010 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED_INDEX] = {
1011 .vendor_id =
1012 QCA_NL80211_VENDOR_ID,
1013 .subcmd =
1014 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED
1015 },
1016 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED_INDEX] = {
1017 .vendor_id =
1018 QCA_NL80211_VENDOR_ID,
1019 .subcmd =
1020 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED
1021 },
1022 [QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED_INDEX] = {
1023 .vendor_id =
1024 QCA_NL80211_VENDOR_ID,
1025 .subcmd =
1026 QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED
1027 },
1028#ifdef FEATURE_WLAN_EXTSCAN
1029 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND_INDEX] = {
1030 .vendor_id = QCA_NL80211_VENDOR_ID,
1031 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_NETWORK_FOUND
1032 },
1033 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND_INDEX] = {
1034 .vendor_id = QCA_NL80211_VENDOR_ID,
1035 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_PASSPOINT_NETWORK_FOUND
1036 },
1037 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST_INDEX] = {
1038 .vendor_id = QCA_NL80211_VENDOR_ID,
1039 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST
1040 },
1041 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST_INDEX] = {
1042 .vendor_id = QCA_NL80211_VENDOR_ID,
1043 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST
1044 },
1045 [QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST_INDEX] = {
1046 .vendor_id = QCA_NL80211_VENDOR_ID,
1047 .subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_HOTLIST_AP_LOST
1048 },
1049#endif /* FEATURE_WLAN_EXTSCAN */
1050 [QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX] = {
1051 .vendor_id = QCA_NL80211_VENDOR_ID,
1052 .subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI
1053 },
1054#ifdef WLAN_FEATURE_MEMDUMP
1055 [QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP_INDEX] = {
1056 .vendor_id = QCA_NL80211_VENDOR_ID,
1057 .subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP
1058 },
1059#endif /* WLAN_FEATURE_MEMDUMP */
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07001060#ifdef WLAN_FEATURE_TSF
1061 [QCA_NL80211_VENDOR_SUBCMD_TSF_INDEX] = {
1062 .vendor_id = QCA_NL80211_VENDOR_ID,
1063 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF
1064 },
1065#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001066 [QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX] = {
1067 .vendor_id = QCA_NL80211_VENDOR_ID,
1068 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE
1069 },
1070 [QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX] = {
1071 .vendor_id = QCA_NL80211_VENDOR_ID,
1072 .subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN
1073 },
1074 /* OCB events */
1075 [QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX] = {
1076 .vendor_id = QCA_NL80211_VENDOR_ID,
1077 .subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
1078 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08001079#ifdef FEATURE_LFR_SUBNET_DETECTION
1080 [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
1081 .vendor_id = QCA_NL80211_VENDOR_ID,
1082 .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
1083 },
1084#endif /*FEATURE_LFR_SUBNET_DETECTION */
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07001085
1086#ifdef WLAN_FEATURE_NAN_DATAPATH
1087 [QCA_NL80211_VENDOR_SUBCMD_NDP_INDEX] = {
1088 .vendor_id = QCA_NL80211_VENDOR_ID,
1089 .subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP
1090 },
1091#endif /* WLAN_FEATURE_NAN_DATAPATH */
Peng Xu8fdaa492016-06-22 10:20:47 -07001092
1093 [QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX] = {
1094 .vendor_id = QCA_NL80211_VENDOR_ID,
1095 .subcmd = QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP
1096 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05301097 [QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH_INDEX] = {
1098 .vendor_id = QCA_NL80211_VENDOR_ID,
1099 .subcmd = QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH
1100 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001101};
1102
1103/**
1104 * __is_driver_dfs_capable() - get driver DFS capability
1105 * @wiphy: pointer to wireless wiphy structure.
1106 * @wdev: pointer to wireless_dev structure.
1107 * @data: Pointer to the data to be passed via vendor interface
1108 * @data_len:Length of the data to be passed
1109 *
1110 * This function is called by userspace to indicate whether or not
1111 * the driver supports DFS offload.
1112 *
1113 * Return: 0 on success, negative errno on failure
1114 */
1115static int __is_driver_dfs_capable(struct wiphy *wiphy,
1116 struct wireless_dev *wdev,
1117 const void *data,
1118 int data_len)
1119{
1120 u32 dfs_capability = 0;
1121 struct sk_buff *temp_skbuff;
1122 int ret_val;
1123 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1124
Jeff Johnson1f61b612016-02-12 16:28:33 -08001125 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001126
1127 ret_val = wlan_hdd_validate_context(hdd_ctx);
1128 if (ret_val)
1129 return ret_val;
1130
Anurag Chouhan6d760662016-02-20 16:05:43 +05301131 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001132 hdd_err("Command not allowed in FTM mode");
1133 return -EPERM;
1134 }
1135
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001136 dfs_capability = !!(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001137
1138 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
1139 NLMSG_HDRLEN);
1140
1141 if (temp_skbuff != NULL) {
1142 ret_val = nla_put_u32(temp_skbuff, QCA_WLAN_VENDOR_ATTR_DFS,
1143 dfs_capability);
1144 if (ret_val) {
Jeff Johnson020db452016-06-29 14:37:26 -07001145 hdd_err("QCA_WLAN_VENDOR_ATTR_DFS put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001146 kfree_skb(temp_skbuff);
1147
1148 return ret_val;
1149 }
1150
1151 return cfg80211_vendor_cmd_reply(temp_skbuff);
1152 }
1153
Jeff Johnson020db452016-06-29 14:37:26 -07001154 hdd_err("dfs capability: buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001155 return -ENOMEM;
1156}
1157
1158/**
1159 * is_driver_dfs_capable() - get driver DFS capability
1160 * @wiphy: pointer to wireless wiphy structure.
1161 * @wdev: pointer to wireless_dev structure.
1162 * @data: Pointer to the data to be passed via vendor interface
1163 * @data_len:Length of the data to be passed
1164 *
1165 * This function is called by userspace to indicate whether or not
1166 * the driver supports DFS offload. This is an SSR-protected
1167 * wrapper function.
1168 *
1169 * Return: 0 on success, negative errno on failure
1170 */
1171static int is_driver_dfs_capable(struct wiphy *wiphy,
1172 struct wireless_dev *wdev,
1173 const void *data,
1174 int data_len)
1175{
1176 int ret;
1177
1178 cds_ssr_protect(__func__);
1179 ret = __is_driver_dfs_capable(wiphy, wdev, data, data_len);
1180 cds_ssr_unprotect(__func__);
1181
1182 return ret;
1183}
1184
1185/**
1186 * wlan_hdd_sap_cfg_dfs_override() - DFS MCC restriction check
1187 *
1188 * @adapter: SAP adapter pointer
1189 *
1190 * DFS in MCC is not supported for Multi bssid SAP mode due to single physical
1191 * radio. So in case of DFS MCC scenario override current SAP given config
1192 * to follow concurrent SAP DFS config
1193 *
1194 * Return: 0 - No DFS issue, 1 - Override done and negative error codes
1195 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001196int wlan_hdd_sap_cfg_dfs_override(hdd_adapter_t *adapter)
1197{
1198 hdd_adapter_t *con_sap_adapter;
1199 tsap_Config_t *sap_config, *con_sap_config;
1200 int con_ch;
1201
1202 /*
1203 * Check if AP+AP case, once primary AP chooses a DFS
1204 * channel secondary AP should always follow primary APs channel
1205 */
1206 if (!cds_concurrent_beaconing_sessions_running())
1207 return 0;
1208
1209 con_sap_adapter = hdd_get_con_sap_adapter(adapter, true);
1210 if (!con_sap_adapter)
1211 return 0;
1212
1213 sap_config = &adapter->sessionCtx.ap.sapConfig;
1214 con_sap_config = &con_sap_adapter->sessionCtx.ap.sapConfig;
1215 con_ch = con_sap_adapter->sessionCtx.ap.operatingChannel;
1216
1217 if (!CDS_IS_DFS_CH(con_ch))
1218 return 0;
1219
Jeff Johnson020db452016-06-29 14:37:26 -07001220 hdd_err("Only SCC AP-AP DFS Permitted (ch=%d, con_ch=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001221 sap_config->channel, con_ch);
Jeff Johnson020db452016-06-29 14:37:26 -07001222 hdd_notice("Overriding guest AP's channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001223 sap_config->channel = con_ch;
1224
1225 if (con_sap_config->acs_cfg.acs_mode == true) {
1226 if (con_ch != con_sap_config->acs_cfg.pri_ch &&
1227 con_ch != con_sap_config->acs_cfg.ht_sec_ch) {
Jeff Johnson020db452016-06-29 14:37:26 -07001228 hdd_err("Primary AP channel config error");
1229 hdd_err("Operating ch: %d ACS ch: %d %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001230 con_ch, con_sap_config->acs_cfg.pri_ch,
1231 con_sap_config->acs_cfg.ht_sec_ch);
1232 return -EINVAL;
1233 }
1234 /* Sec AP ACS info is overwritten with Pri AP due to DFS
1235 * MCC restriction. So free ch list allocated in do_acs
1236 * func for Sec AP and realloc for Pri AP ch list size
1237 */
1238 if (sap_config->acs_cfg.ch_list)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301239 qdf_mem_free(sap_config->acs_cfg.ch_list);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001240
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301241 qdf_mem_copy(&sap_config->acs_cfg,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001242 &con_sap_config->acs_cfg,
1243 sizeof(struct sap_acs_cfg));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301244 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001245 sizeof(uint8_t) *
1246 con_sap_config->acs_cfg.ch_list_count);
1247 if (!sap_config->acs_cfg.ch_list) {
Jeff Johnson020db452016-06-29 14:37:26 -07001248 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001249 return -ENOMEM;
1250 }
1251
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301252 qdf_mem_copy(sap_config->acs_cfg.ch_list,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001253 con_sap_config->acs_cfg.ch_list,
1254 con_sap_config->acs_cfg.ch_list_count);
1255
1256 } else {
1257 sap_config->acs_cfg.pri_ch = con_ch;
1258 if (sap_config->acs_cfg.ch_width > eHT_CHANNEL_WIDTH_20MHZ)
1259 sap_config->acs_cfg.ht_sec_ch = con_sap_config->sec_ch;
1260 }
1261
1262 return con_ch;
1263}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001264
1265/**
1266 * wlan_hdd_set_acs_ch_range : Start ACS channel range values
1267 * @sap_cfg: pointer to SAP config struct
1268 *
1269 * This function sets the default ACS start and end channel for the given band
1270 * and also parses the given ACS channel list.
1271 *
1272 * Return: None
1273 */
1274
1275static void wlan_hdd_set_acs_ch_range(tsap_Config_t *sap_cfg, bool ht_enabled,
1276 bool vht_enabled)
1277{
1278 int i;
1279 if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211B) {
1280 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11b;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001281 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1282 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_14);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001283 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211G) {
1284 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11g;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001285 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1286 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_13);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001287 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211A) {
1288 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11a;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001289 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_36);
1290 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001291 } else if (sap_cfg->acs_cfg.hw_mode == QCA_ACS_MODE_IEEE80211ANY) {
1292 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_abg;
Amar Singhalb8d4f152016-02-10 10:21:43 -08001293 sap_cfg->acs_cfg.start_ch = CDS_CHANNEL_NUM(CHAN_ENUM_1);
1294 sap_cfg->acs_cfg.end_ch = CDS_CHANNEL_NUM(CHAN_ENUM_165);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001295 }
1296
1297 if (ht_enabled)
1298 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11n;
1299
1300 if (vht_enabled)
1301 sap_cfg->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1302
1303
1304 /* Parse ACS Chan list from hostapd */
1305 if (!sap_cfg->acs_cfg.ch_list)
1306 return;
1307
1308 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[0];
1309 sap_cfg->acs_cfg.end_ch =
1310 sap_cfg->acs_cfg.ch_list[sap_cfg->acs_cfg.ch_list_count - 1];
1311 for (i = 0; i < sap_cfg->acs_cfg.ch_list_count; i++) {
Manjeet Singh2d3b0c52016-09-02 13:31:48 +05301312 /* avoid channel as start channel */
1313 if (sap_cfg->acs_cfg.start_ch > sap_cfg->acs_cfg.ch_list[i] &&
1314 sap_cfg->acs_cfg.ch_list[i] != 0)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001315 sap_cfg->acs_cfg.start_ch = sap_cfg->acs_cfg.ch_list[i];
1316 if (sap_cfg->acs_cfg.end_ch < sap_cfg->acs_cfg.ch_list[i])
1317 sap_cfg->acs_cfg.end_ch = sap_cfg->acs_cfg.ch_list[i];
1318 }
1319}
1320
1321
1322static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work);
1323
1324/**
1325 * wlan_hdd_cfg80211_start_acs : Start ACS Procedure for SAP
1326 * @adapter: pointer to SAP adapter struct
1327 *
1328 * This function starts the ACS procedure if there are no
1329 * constraints like MBSSID DFS restrictions.
1330 *
1331 * Return: Status of ACS Start procedure
1332 */
1333
1334static int wlan_hdd_cfg80211_start_acs(hdd_adapter_t *adapter)
1335{
1336
1337 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1338 tsap_Config_t *sap_config;
1339 tpWLAN_SAPEventCB acs_event_callback;
1340 int status;
1341
1342 sap_config = &adapter->sessionCtx.ap.sapConfig;
Agrawal Ashish65634612016-08-18 13:24:32 +05301343 if (hdd_ctx->acs_policy.acs_channel)
1344 sap_config->channel = hdd_ctx->acs_policy.acs_channel;
1345 else
1346 sap_config->channel = AUTO_CHANNEL_SELECT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001347
1348 status = wlan_hdd_sap_cfg_dfs_override(adapter);
1349 if (status < 0) {
1350 return status;
1351 } else {
1352 if (status > 0) {
1353 /*notify hostapd about channel override */
1354 wlan_hdd_cfg80211_acs_ch_select_evt(adapter);
1355 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1356 return 0;
1357 }
1358 }
1359 status = wlan_hdd_config_acs(hdd_ctx, adapter);
1360 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001361 hdd_err("ACS config failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001362 return -EINVAL;
1363 }
1364
1365 acs_event_callback = hdd_hostapd_sap_event_cb;
1366
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301367 qdf_mem_copy(sap_config->self_macaddr.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05301368 adapter->macAddressCurrent.bytes, sizeof(struct qdf_mac_addr));
Jeff Johnson020db452016-06-29 14:37:26 -07001369 hdd_notice("ACS Started for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001370 status = wlansap_acs_chselect(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001371 WLAN_HDD_GET_SAP_CTX_PTR(adapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001372 acs_event_callback, sap_config, adapter->dev);
1373
1374
1375 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001376 hdd_err("ACS channel select failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001377 return -EINVAL;
1378 }
1379 sap_config->acs_cfg.acs_mode = true;
1380 set_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1381
1382 return 0;
1383}
1384
1385/**
1386 * __wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1387 * @wiphy: Linux wiphy struct pointer
1388 * @wdev: Linux wireless device struct pointer
1389 * @data: ACS information from hostapd
1390 * @data_len: ACS information length
1391 *
1392 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1393 * and starts ACS procedure.
1394 *
1395 * Return: ACS procedure start status
1396 */
1397
1398static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1399 struct wireless_dev *wdev,
1400 const void *data, int data_len)
1401{
1402 struct net_device *ndev = wdev->netdev;
1403 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
1404 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
1405 tsap_Config_t *sap_config;
1406 struct sk_buff *temp_skbuff;
1407 int status = -EINVAL, i = 0;
1408 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_MAX + 1];
1409 bool ht_enabled, ht40_enabled, vht_enabled;
1410 uint8_t ch_width;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05301411 uint8_t weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001412
1413 /* ***Note*** Donot set SME config related to ACS operation here because
1414 * ACS operation is not synchronouse and ACS for Second AP may come when
1415 * ACS operation for first AP is going on. So only do_acs is split to
1416 * seperate start_acs routine. Also SME-PMAC struct that is used to
1417 * pass paremeters from HDD to SAP is global. Thus All ACS related SME
1418 * config shall be set only from start_acs.
1419 */
1420
1421 /* nla_policy Policy template. Policy not applied as some attributes are
1422 * optional and QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST has variable length
1423 *
1424 * [QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE] = { .type = NLA_U8 },
1425 * [QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED] = { .type = NLA_FLAG },
1426 * [QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED] = { .type = NLA_FLAG },
1427 * [QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED] = { .type = NLA_FLAG },
1428 * [QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH] = { .type = NLA_U16 },
1429 * [QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST] = { .type = NLA_NESTED },
1430 */
1431
Jeff Johnson1f61b612016-02-12 16:28:33 -08001432 ENTER_DEV(ndev);
1433
Anurag Chouhan6d760662016-02-20 16:05:43 +05301434 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001435 hdd_err("Command not allowed in FTM mode");
1436 return -EPERM;
1437 }
1438
1439 if (hdd_ctx->config->force_sap_acs) {
Jeff Johnson020db452016-06-29 14:37:26 -07001440 hdd_err("Hostapd ACS rejected as Driver ACS enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001441 return -EPERM;
1442 }
1443
1444 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301445 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001446 goto out;
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301447
Naveen Rawat64e477e2016-05-20 10:34:56 -07001448 if (cds_is_sub_20_mhz_enabled()) {
1449 hdd_err("ACS not supported in sub 20 MHz ch wd.");
1450 status = -EINVAL;
1451 goto out;
1452 }
1453
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001454 sap_config = &adapter->sessionCtx.ap.sapConfig;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301455 qdf_mem_zero(&sap_config->acs_cfg, sizeof(struct sap_acs_cfg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001456
1457 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_MAX, data, data_len,
1458 NULL);
1459 if (status) {
Jeff Johnson020db452016-06-29 14:37:26 -07001460 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001461 goto out;
1462 }
1463
1464 if (!tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001465 hdd_err("Attr hw_mode failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001466 goto out;
1467 }
1468 sap_config->acs_cfg.hw_mode = nla_get_u8(
1469 tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]);
1470
1471 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED])
1472 ht_enabled =
1473 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED]);
1474 else
1475 ht_enabled = 0;
1476
1477 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED])
1478 ht40_enabled =
1479 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED]);
1480 else
1481 ht40_enabled = 0;
1482
1483 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED])
1484 vht_enabled =
1485 nla_get_flag(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED]);
1486 else
1487 vht_enabled = 0;
1488
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301489 if (hdd_ctx->config->sap_force_11n_for_11ac) {
1490 vht_enabled = 0;
1491 hdd_log(LOG1, FL("VHT is Disabled in ACS"));
1492 }
1493
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001494 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) {
1495 ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]);
1496 } else {
1497 if (ht_enabled && ht40_enabled)
1498 ch_width = 40;
1499 else
1500 ch_width = 20;
1501 }
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301502
1503 /* this may be possible, when sap_force_11n_for_11ac is set */
1504 if ((ch_width == 80 || ch_width == 160) && !vht_enabled) {
1505 if (ht_enabled && ht40_enabled)
1506 ch_width = 40;
1507 else
1508 ch_width = 20;
1509 }
1510
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001511 if (ch_width == 80)
1512 sap_config->acs_cfg.ch_width = CH_WIDTH_80MHZ;
1513 else if (ch_width == 40)
1514 sap_config->acs_cfg.ch_width = CH_WIDTH_40MHZ;
1515 else
1516 sap_config->acs_cfg.ch_width = CH_WIDTH_20MHZ;
1517
1518 /* hw_mode = a/b/g: QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST and
1519 * QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attrs are present, and
1520 * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is used for obtaining the
1521 * channel list, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST is ignored
1522 * since it contains the frequency values of the channels in
1523 * the channel list.
1524 * hw_mode = any: only QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST attr
1525 * is present
1526 */
1527 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]) {
1528 char *tmp = nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1529 sap_config->acs_cfg.ch_list_count = nla_len(
1530 tb[QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST]);
1531 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301532 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001533 sizeof(uint8_t) *
1534 sap_config->acs_cfg.ch_list_count);
1535 if (sap_config->acs_cfg.ch_list == NULL)
1536 goto out;
1537
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301538 qdf_mem_copy(sap_config->acs_cfg.ch_list, tmp,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001539 sap_config->acs_cfg.ch_list_count);
1540 }
1541 } else if (tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) {
1542 uint32_t *freq =
1543 nla_data(tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]);
1544 sap_config->acs_cfg.ch_list_count = nla_len(
1545 tb[QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST]) /
1546 sizeof(uint32_t);
1547 if (sap_config->acs_cfg.ch_list_count) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301548 sap_config->acs_cfg.ch_list = qdf_mem_malloc(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001549 sap_config->acs_cfg.ch_list_count);
1550 if (sap_config->acs_cfg.ch_list == NULL) {
Jeff Johnson020db452016-06-29 14:37:26 -07001551 hdd_err("ACS config alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001552 status = -ENOMEM;
1553 goto out;
1554 }
1555
1556 /* convert frequency to channel */
1557 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
1558 sap_config->acs_cfg.ch_list[i] =
1559 ieee80211_frequency_to_channel(freq[i]);
1560 }
1561 }
1562
1563 hdd_debug("get pcl for DO_ACS vendor command");
1564
1565 /* consult policy manager to get PCL */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08001566 status = cds_get_pcl(CDS_SAP_MODE,
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05301567 sap_config->acs_cfg.pcl_channels,
1568 &sap_config->acs_cfg.pcl_ch_count,
1569 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301570 if (QDF_STATUS_SUCCESS != status)
Jeff Johnson020db452016-06-29 14:37:26 -07001571 hdd_err("Get PCL failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001572
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001573 /* ACS override for android */
Rajeev Kumar Sirasanagandlab79b5462016-09-06 18:33:17 +05301574 if (hdd_ctx->config->sap_p2p_11ac_override && ht_enabled &&
1575 !hdd_ctx->config->sap_force_11n_for_11ac) {
Jeff Johnson020db452016-06-29 14:37:26 -07001576 hdd_notice("ACS Config override for 11AC");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001577 vht_enabled = 1;
1578 sap_config->acs_cfg.hw_mode = eCSR_DOT11_MODE_11ac;
1579 sap_config->acs_cfg.ch_width =
1580 hdd_ctx->config->vhtChannelWidth;
1581 /* No VHT80 in 2.4G so perform ACS accordingly */
1582 if (sap_config->acs_cfg.end_ch <= 14 &&
1583 sap_config->acs_cfg.ch_width == eHT_CHANNEL_WIDTH_80MHZ)
1584 sap_config->acs_cfg.ch_width = eHT_CHANNEL_WIDTH_40MHZ;
1585 }
1586
Manishekar Chandrasekaran44e334f2016-05-30 16:42:50 +05301587 wlan_hdd_set_acs_ch_range(sap_config, ht_enabled, vht_enabled);
1588
Jeff Johnson020db452016-06-29 14:37:26 -07001589 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 -08001590 adapter->dev->ifindex, sap_config->acs_cfg.hw_mode,
1591 ch_width, ht_enabled, vht_enabled,
1592 sap_config->acs_cfg.start_ch, sap_config->acs_cfg.end_ch);
1593
1594 if (sap_config->acs_cfg.ch_list_count) {
Jeff Johnson020db452016-06-29 14:37:26 -07001595 hdd_notice("ACS channel list: len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001596 sap_config->acs_cfg.ch_list_count);
1597 for (i = 0; i < sap_config->acs_cfg.ch_list_count; i++)
Jeff Johnson020db452016-06-29 14:37:26 -07001598 hdd_notice("%d ", sap_config->acs_cfg.ch_list[i]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001599 }
1600 sap_config->acs_cfg.acs_mode = true;
1601 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001602 /* ***Note*** Completion variable usage is not allowed
1603 * here since ACS scan operation may take max 2.2 sec
1604 * for 5G band:
1605 * 9 Active channel X 40 ms active scan time +
1606 * 16 Passive channel X 110ms passive scan time
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001607 * Since this CFG80211 call lock rtnl mutex, we cannot hold on
1608 * for this long. So we split up the scanning part.
1609 */
1610 set_bit(ACS_PENDING, &adapter->event_flags);
Jeff Johnson020db452016-06-29 14:37:26 -07001611 hdd_notice("ACS Pending for wlan%d", adapter->dev->ifindex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001612 status = 0;
1613 } else {
1614 status = wlan_hdd_cfg80211_start_acs(adapter);
1615 }
1616
1617out:
1618 if (0 == status) {
1619 temp_skbuff = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1620 NLMSG_HDRLEN);
1621 if (temp_skbuff != NULL)
1622 return cfg80211_vendor_cmd_reply(temp_skbuff);
1623 }
1624
1625 clear_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags);
1626
1627 return status;
1628}
1629
1630 /**
1631 * wlan_hdd_cfg80211_do_acs : CFG80211 handler function for DO_ACS Vendor CMD
1632 * @wiphy: Linux wiphy struct pointer
1633 * @wdev: Linux wireless device struct pointer
1634 * @data: ACS information from hostapd
1635 * @data_len: ACS information len
1636 *
1637 * This function handle DO_ACS Vendor command from hostapd, parses ACS config
1638 * and starts ACS procedure.
1639 *
1640 * Return: ACS procedure start status
1641 */
1642
1643static int wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
1644 struct wireless_dev *wdev,
1645 const void *data, int data_len)
1646{
1647 int ret;
1648
1649 cds_ssr_protect(__func__);
1650 ret = __wlan_hdd_cfg80211_do_acs(wiphy, wdev, data, data_len);
1651 cds_ssr_unprotect(__func__);
1652
1653 return ret;
1654}
1655
1656/**
1657 * wlan_hdd_cfg80211_start_pending_acs : Start pending ACS procedure for SAP
1658 * @work: Linux workqueue struct pointer for ACS work
1659 *
1660 * This function starts the ACS procedure which was marked pending when an ACS
1661 * procedure was in progress for a concurrent SAP interface.
1662 *
1663 * Return: None
1664 */
1665
1666static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work)
1667{
1668 hdd_adapter_t *adapter = container_of(work, hdd_adapter_t,
1669 acs_pending_work.work);
1670 wlan_hdd_cfg80211_start_acs(adapter);
1671}
1672
1673/**
1674 * wlan_hdd_cfg80211_acs_ch_select_evt: Callback function for ACS evt
1675 * @adapter: Pointer to SAP adapter struct
1676 * @pri_channel: SAP ACS procedure selected Primary channel
1677 * @sec_channel: SAP ACS procedure selected secondary channel
1678 *
1679 * This is a callback function from SAP module on ACS procedure is completed.
1680 * This function send the ACS selected channel information to hostapd
1681 *
1682 * Return: None
1683 */
1684
1685void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter)
1686{
1687 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1688 tsap_Config_t *sap_cfg = &(WLAN_HDD_GET_AP_CTX_PTR(adapter))->sapConfig;
1689 struct sk_buff *vendor_event;
1690 int ret_val;
1691 hdd_adapter_t *con_sap_adapter;
1692 uint16_t ch_width;
1693
1694 vendor_event = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
Ryan Hsu9206a4e2016-01-19 17:23:13 -08001695 &(adapter->wdev),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001696 4 * sizeof(u8) + 1 * sizeof(u16) + 4 + NLMSG_HDRLEN,
1697 QCA_NL80211_VENDOR_SUBCMD_DO_ACS_INDEX,
1698 GFP_KERNEL);
1699
1700 if (!vendor_event) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001701 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001702 return;
1703 }
1704
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001705 ret_val = nla_put_u8(vendor_event,
1706 QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
1707 sap_cfg->acs_cfg.pri_ch);
1708 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001709 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001710 kfree_skb(vendor_event);
1711 return;
1712 }
1713
1714 ret_val = nla_put_u8(vendor_event,
1715 QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
1716 sap_cfg->acs_cfg.ht_sec_ch);
1717 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001718 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001719 kfree_skb(vendor_event);
1720 return;
1721 }
1722
1723 ret_val = nla_put_u8(vendor_event,
1724 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
1725 sap_cfg->acs_cfg.vht_seg0_center_ch);
1726 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001727 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001728 kfree_skb(vendor_event);
1729 return;
1730 }
1731
1732 ret_val = nla_put_u8(vendor_event,
1733 QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
1734 sap_cfg->acs_cfg.vht_seg1_center_ch);
1735 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001736 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001737 kfree_skb(vendor_event);
1738 return;
1739 }
1740
1741 if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_80MHZ)
1742 ch_width = 80;
1743 else if (sap_cfg->acs_cfg.ch_width == CH_WIDTH_40MHZ)
1744 ch_width = 40;
1745 else
1746 ch_width = 20;
1747
1748 ret_val = nla_put_u16(vendor_event,
1749 QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
1750 ch_width);
1751 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001752 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001753 kfree_skb(vendor_event);
1754 return;
1755 }
1756 if (sap_cfg->acs_cfg.pri_ch > 14)
1757 ret_val = nla_put_u8(vendor_event,
1758 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1759 QCA_ACS_MODE_IEEE80211A);
1760 else
1761 ret_val = nla_put_u8(vendor_event,
1762 QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
1763 QCA_ACS_MODE_IEEE80211G);
1764
1765 if (ret_val) {
Jeff Johnson46b40792016-06-29 14:03:14 -07001766 hdd_err("QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001767 kfree_skb(vendor_event);
1768 return;
1769 }
1770
Jeff Johnson46b40792016-06-29 14:03:14 -07001771 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 -08001772 adapter->dev->ifindex, sap_cfg->acs_cfg.pri_ch,
1773 sap_cfg->acs_cfg.ht_sec_ch, sap_cfg->acs_cfg.vht_seg0_center_ch,
1774 sap_cfg->acs_cfg.vht_seg1_center_ch, ch_width);
1775
1776 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1777 /* ***Note*** As already mentioned Completion variable usage is not
1778 * allowed here since ACS scan operation may take max 2.2 sec.
1779 * Further in AP-AP mode pending ACS is resumed here to serailize ACS
1780 * operation.
1781 * TODO: Delayed operation is used since SME-PMAC strut is global. Thus
1782 * when Primary AP ACS is complete and secondary AP ACS is started here
1783 * immediately, Primary AP start_bss may come inbetween ACS operation
1784 * and overwrite Sec AP ACS paramters. Thus Sec AP ACS is executed with
1785 * delay. This path and below constraint will be removed on sessionizing
1786 * SAP acs parameters and decoupling SAP from PMAC (WIP).
1787 * As per design constraint user space control application must take
1788 * care of serailizing hostapd start for each VIF in AP-AP mode to avoid
1789 * this code path. Sec AP hostapd should be started after Primary AP
1790 * start beaconing which can be confirmed by getchannel iwpriv command
1791 */
1792
1793 con_sap_adapter = hdd_get_con_sap_adapter(adapter, false);
1794 if (con_sap_adapter &&
1795 test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001796 INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work,
1797 wlan_hdd_cfg80211_start_pending_acs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001798 /* Lets give 500ms for OBSS + START_BSS to complete */
1799 schedule_delayed_work(&con_sap_adapter->acs_pending_work,
1800 msecs_to_jiffies(500));
1801 clear_bit(ACS_PENDING, &con_sap_adapter->event_flags);
1802 }
1803
1804 return;
1805}
1806
1807static int
1808__wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1809 struct wireless_dev *wdev,
1810 const void *data,
1811 int data_len)
1812{
1813 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1814 struct sk_buff *skb = NULL;
1815 uint32_t fset = 0;
1816 int ret;
1817
Srinivas Girigowdadbfb2642016-08-28 21:32:38 -07001818 /* ENTER_DEV() intentionally not used in a frequently invoked API */
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301819
Anurag Chouhan6d760662016-02-20 16:05:43 +05301820 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001821 hdd_err("Command not allowed in FTM mode");
1822 return -EPERM;
1823 }
1824
1825 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301826 if (ret)
1827 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001828
1829 if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001830 hdd_notice("Infra Station mode is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001831 fset |= WIFI_FEATURE_INFRA;
1832 }
1833 if (true == hdd_is_5g_supported(pHddCtx)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001834 hdd_notice("INFRA_5G is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001835 fset |= WIFI_FEATURE_INFRA_5G;
1836 }
1837#ifdef WLAN_FEATURE_P2P
1838 if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
1839 (wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO))) {
Jeff Johnson020db452016-06-29 14:37:26 -07001840 hdd_notice("WiFi-Direct is supported by driver");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001841 fset |= WIFI_FEATURE_P2P;
1842 }
1843#endif
1844 fset |= WIFI_FEATURE_SOFT_AP;
1845
1846 /* HOTSPOT is a supplicant feature, enable it by default */
1847 fset |= WIFI_FEATURE_HOTSPOT;
1848
1849#ifdef FEATURE_WLAN_EXTSCAN
Manjeet Singh0f2ce5c2016-09-01 12:08:57 +05301850 if (pHddCtx->config->extscan_enabled &&
1851 sme_is_feature_supported_by_fw(EXTENDED_SCAN)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001852 hdd_notice("EXTScan is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001853 fset |= WIFI_FEATURE_EXTSCAN | WIFI_FEATURE_HAL_EPNO;
1854 }
1855#endif
1856 if (wlan_hdd_nan_is_supported()) {
Jeff Johnson020db452016-06-29 14:37:26 -07001857 hdd_notice("NAN is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001858 fset |= WIFI_FEATURE_NAN;
1859 }
1860 if (sme_is_feature_supported_by_fw(RTT)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001861 hdd_notice("RTT is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001862 fset |= WIFI_FEATURE_D2D_RTT;
1863 fset |= WIFI_FEATURE_D2AP_RTT;
1864 }
1865#ifdef FEATURE_WLAN_SCAN_PNO
1866 if (pHddCtx->config->configPNOScanSupport &&
1867 sme_is_feature_supported_by_fw(PNO)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001868 hdd_notice("PNO is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001869 fset |= WIFI_FEATURE_PNO;
1870 }
1871#endif
1872 fset |= WIFI_FEATURE_ADDITIONAL_STA;
1873#ifdef FEATURE_WLAN_TDLS
1874 if ((true == pHddCtx->config->fEnableTDLSSupport) &&
1875 sme_is_feature_supported_by_fw(TDLS)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001876 hdd_notice("TDLS is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001877 fset |= WIFI_FEATURE_TDLS;
1878 }
1879 if (sme_is_feature_supported_by_fw(TDLS) &&
1880 (true == pHddCtx->config->fEnableTDLSOffChannel) &&
1881 sme_is_feature_supported_by_fw(TDLS_OFF_CHANNEL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001882 hdd_notice("TDLS off-channel is supported by firmware");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001883 fset |= WIFI_FEATURE_TDLS_OFFCHANNEL;
1884 }
1885#endif
1886#ifdef WLAN_AP_STA_CONCURRENCY
1887 fset |= WIFI_FEATURE_AP_STA;
1888#endif
1889 fset |= WIFI_FEATURE_RSSI_MONITOR;
1890
1891 if (hdd_link_layer_stats_supported())
1892 fset |= WIFI_FEATURE_LINK_LAYER_STATS;
1893
1894 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(fset) +
1895 NLMSG_HDRLEN);
1896 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07001897 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001898 return -EINVAL;
1899 }
Jeff Johnson020db452016-06-29 14:37:26 -07001900 hdd_notice("Supported Features : 0x%x", fset);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001901 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_SET, fset)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001902 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001903 goto nla_put_failure;
1904 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301905 ret = cfg80211_vendor_cmd_reply(skb);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05301906 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001907nla_put_failure:
1908 kfree_skb(skb);
1909 return -EINVAL;
1910}
1911
1912/**
1913 * wlan_hdd_cfg80211_get_supported_features() - get supported features
1914 * @wiphy: pointer to wireless wiphy structure.
1915 * @wdev: pointer to wireless_dev structure.
1916 * @data: Pointer to the data to be passed via vendor interface
1917 * @data_len:Length of the data to be passed
1918 *
1919 * Return: Return the Success or Failure code.
1920 */
1921static int
1922wlan_hdd_cfg80211_get_supported_features(struct wiphy *wiphy,
1923 struct wireless_dev *wdev,
1924 const void *data, int data_len)
1925{
1926 int ret = 0;
1927
1928 cds_ssr_protect(__func__);
1929 ret = __wlan_hdd_cfg80211_get_supported_features(wiphy, wdev,
1930 data, data_len);
1931 cds_ssr_unprotect(__func__);
1932
1933 return ret;
1934}
1935
1936/**
1937 * __wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
1938 * @wiphy: pointer to wireless wiphy structure.
1939 * @wdev: pointer to wireless_dev structure.
1940 * @data: Pointer to the data to be passed via vendor interface
1941 * @data_len:Length of the data to be passed
1942 *
1943 * Set the MAC address that is to be used for scanning.
1944 *
1945 * Return: Return the Success or Failure code.
1946 */
1947static int
1948__wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
1949 struct wireless_dev *wdev,
1950 const void *data,
1951 int data_len)
1952{
1953 tpSirScanMacOui pReqMsg = NULL;
1954 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
1955 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX + 1];
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301956 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001957 int ret;
1958
Jeff Johnson1f61b612016-02-12 16:28:33 -08001959 ENTER_DEV(wdev->netdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001960
Anurag Chouhan6d760662016-02-20 16:05:43 +05301961 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001962 hdd_err("Command not allowed in FTM mode");
1963 return -EPERM;
1964 }
1965
1966 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05301967 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001968 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001969
1970 if (false == pHddCtx->config->enable_mac_spoofing) {
Jeff Johnson020db452016-06-29 14:37:26 -07001971 hdd_warn("MAC address spoofing is not enabled");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001972 return -ENOTSUPP;
1973 }
1974
1975 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX,
1976 data, data_len, NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001977 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001978 return -EINVAL;
1979 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301980 pReqMsg = qdf_mem_malloc(sizeof(*pReqMsg));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001981 if (!pReqMsg) {
Jeff Johnson020db452016-06-29 14:37:26 -07001982 hdd_err("qdf_mem_malloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001983 return -ENOMEM;
1984 }
1985 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI]) {
Jeff Johnson020db452016-06-29 14:37:26 -07001986 hdd_err("attr mac oui failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001987 goto fail;
1988 }
1989 nla_memcpy(&pReqMsg->oui[0],
1990 tb[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI],
1991 sizeof(pReqMsg->oui));
Jeff Johnson020db452016-06-29 14:37:26 -07001992 hdd_notice("Oui (%02x:%02x:%02x)", pReqMsg->oui[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001993 pReqMsg->oui[1], pReqMsg->oui[2]);
1994 status = sme_set_scanning_mac_oui(pHddCtx->hHal, pReqMsg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301995 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07001996 hdd_err("sme_set_scanning_mac_oui failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001997 goto fail;
1998 }
1999 return 0;
2000fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302001 qdf_mem_free(pReqMsg);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002002 return -EINVAL;
2003}
2004
2005/**
2006 * wlan_hdd_cfg80211_set_scanning_mac_oui() - set scan MAC
2007 * @wiphy: pointer to wireless wiphy structure.
2008 * @wdev: pointer to wireless_dev structure.
2009 * @data: Pointer to the data to be passed via vendor interface
2010 * @data_len:Length of the data to be passed
2011 *
2012 * Set the MAC address that is to be used for scanning. This is an
2013 * SSR-protecting wrapper function.
2014 *
2015 * Return: Return the Success or Failure code.
2016 */
2017static int
2018wlan_hdd_cfg80211_set_scanning_mac_oui(struct wiphy *wiphy,
2019 struct wireless_dev *wdev,
2020 const void *data,
2021 int data_len)
2022{
2023 int ret;
2024
2025 cds_ssr_protect(__func__);
2026 ret = __wlan_hdd_cfg80211_set_scanning_mac_oui(wiphy, wdev,
2027 data, data_len);
2028 cds_ssr_unprotect(__func__);
2029
2030 return ret;
2031}
2032
2033/**
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302034 * __wlan_hdd_cfg80211_get_concurrency_matrix() - to retrieve concurrency matrix
2035 * @wiphy: pointer phy adapter
2036 * @wdev: pointer to wireless device structure
2037 * @data: pointer to data buffer
2038 * @data_len: length of data
2039 *
2040 * This routine will give concurrency matrix
2041 *
2042 * Return: int status code
2043 */
2044static int __wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2045 struct wireless_dev *wdev,
2046 const void *data,
2047 int data_len)
2048{
2049 uint32_t feature_set_matrix[CDS_MAX_FEATURE_SET] = {0};
2050 uint8_t i, feature_sets, max_feature_sets;
2051 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
2052 struct sk_buff *reply_skb;
2053 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2054 int ret;
2055
2056 ENTER_DEV(wdev->netdev);
2057
2058 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2059 hdd_err("Command not allowed in FTM mode");
2060 return -EPERM;
2061 }
2062
2063 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302064 if (ret)
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302065 return ret;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302066
2067 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
2068 data, data_len, NULL)) {
2069 hdd_err("Invalid ATTR");
2070 return -EINVAL;
2071 }
2072
2073 /* Parse and fetch max feature set */
2074 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]) {
2075 hdd_err("Attr max feature set size failed");
2076 return -EINVAL;
2077 }
2078 max_feature_sets = nla_get_u32(tb[
2079 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX]);
2080 hdd_info("Max feature set size: %d", max_feature_sets);
2081
2082 /* Fill feature combination matrix */
2083 feature_sets = 0;
2084 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002085 WIFI_FEATURE_P2P;
2086 feature_set_matrix[feature_sets++] = WIFI_FEATURE_INFRA |
2087 WIFI_FEATURE_NAN;
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302088 /* Add more feature combinations here */
2089
2090 feature_sets = QDF_MIN(feature_sets, max_feature_sets);
Srinivas Girigowdaca422922016-08-17 18:29:42 -07002091 hdd_info("Number of feature sets: %d", feature_sets);
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05302092 hdd_info("Feature set matrix");
2093 for (i = 0; i < feature_sets; i++)
2094 hdd_info("[%d] 0x%02X", i, feature_set_matrix[i]);
2095
2096 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
2097 sizeof(u32) * feature_sets + NLMSG_HDRLEN);
2098 if (!reply_skb) {
2099 hdd_err("Feature set matrix: buffer alloc fail");
2100 return -ENOMEM;
2101 }
2102
2103 if (nla_put_u32(reply_skb,
2104 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE,
2105 feature_sets) ||
2106 nla_put(reply_skb,
2107 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET,
2108 sizeof(u32) * feature_sets,
2109 feature_set_matrix)) {
2110 hdd_err("nla put fail");
2111 kfree_skb(reply_skb);
2112 return -EINVAL;
2113 }
2114 return cfg80211_vendor_cmd_reply(reply_skb);
2115}
2116
2117/**
2118 * wlan_hdd_cfg80211_get_concurrency_matrix() - get concurrency matrix
2119 * @wiphy: pointer to wireless wiphy structure.
2120 * @wdev: pointer to wireless_dev structure.
2121 * @data: Pointer to the data to be passed via vendor interface
2122 * @data_len:Length of the data to be passed
2123 *
2124 * Retrieves the concurrency feature set matrix
2125 *
2126 * Return: 0 on success, negative errno on failure
2127 */
2128static int
2129wlan_hdd_cfg80211_get_concurrency_matrix(struct wiphy *wiphy,
2130 struct wireless_dev *wdev,
2131 const void *data,
2132 int data_len)
2133{
2134 int ret;
2135
2136 cds_ssr_protect(__func__);
2137 ret = __wlan_hdd_cfg80211_get_concurrency_matrix(wiphy, wdev,
2138 data, data_len);
2139 cds_ssr_unprotect(__func__);
2140
2141 return ret;
2142}
2143
2144/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002145 * wlan_hdd_cfg80211_set_feature() - Set the bitmask for supported features
2146 * @feature_flags: pointer to the byte array of features.
2147 * @feature: Feature to be turned ON in the byte array.
2148 *
2149 * Return: None
2150 *
2151 * This is called to turn ON or SET the feature flag for the requested feature.
2152 **/
2153#define NUM_BITS_IN_BYTE 8
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07002154static void wlan_hdd_cfg80211_set_feature(uint8_t *feature_flags,
2155 uint8_t feature)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002156{
2157 uint32_t index;
2158 uint8_t bit_mask;
2159
2160 index = feature / NUM_BITS_IN_BYTE;
2161 bit_mask = 1 << (feature % NUM_BITS_IN_BYTE);
2162 feature_flags[index] |= bit_mask;
2163}
2164
2165/**
2166 * __wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2167 * @wiphy: pointer to wireless wiphy structure.
2168 * @wdev: pointer to wireless_dev structure.
2169 * @data: Pointer to the data to be passed via vendor interface
2170 * @data_len:Length of the data to be passed
2171 *
2172 * This is called when wlan driver needs to send supported feature set to
2173 * supplicant upon a request/query from the supplicant.
2174 *
2175 * Return: Return the Success or Failure code.
2176 **/
2177#define MAX_CONCURRENT_CHAN_ON_24G 2
2178#define MAX_CONCURRENT_CHAN_ON_5G 2
2179static int
2180__wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2181 struct wireless_dev *wdev,
2182 const void *data, int data_len)
2183{
2184 struct sk_buff *skb = NULL;
2185 uint32_t dbs_capability = 0;
2186 bool one_by_one_dbs, two_by_two_dbs;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302187 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002188 int ret_val;
2189
2190 uint8_t feature_flags[(NUM_QCA_WLAN_VENDOR_FEATURES + 7) / 8] = {0};
2191 hdd_context_t *hdd_ctx_ptr = wiphy_priv(wiphy);
2192
Jeff Johnson1f61b612016-02-12 16:28:33 -08002193 ENTER_DEV(wdev->netdev);
2194
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002195 ret_val = wlan_hdd_validate_context(hdd_ctx_ptr);
2196 if (ret_val)
2197 return ret_val;
2198
Anurag Chouhan6d760662016-02-20 16:05:43 +05302199 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002200 hdd_err("Command not allowed in FTM mode");
2201 return -EPERM;
2202 }
2203
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07002204 if (roaming_offload_enabled(hdd_ctx_ptr)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002205 hdd_notice("Key Mgmt Offload is supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002206 wlan_hdd_cfg80211_set_feature(feature_flags,
2207 QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD);
2208 }
2209
2210 wlan_hdd_cfg80211_set_feature(feature_flags,
2211 QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY);
2212 if (wma_is_scan_simultaneous_capable())
2213 wlan_hdd_cfg80211_set_feature(feature_flags,
2214 QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS);
Peng Xu8fdaa492016-06-22 10:20:47 -07002215
2216 if (wma_is_p2p_lo_capable())
2217 wlan_hdd_cfg80211_set_feature(feature_flags,
2218 QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD);
2219
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002220 skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(feature_flags) +
2221 NLMSG_HDRLEN);
2222
2223 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07002224 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002225 return -ENOMEM;
2226 }
2227
2228 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS,
2229 sizeof(feature_flags), feature_flags))
2230 goto nla_put_failure;
2231
2232 ret = wma_get_dbs_hw_modes(&one_by_one_dbs, &two_by_two_dbs);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302233 if (QDF_STATUS_SUCCESS == ret) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002234 if (one_by_one_dbs)
2235 dbs_capability = DRV_DBS_CAPABILITY_1X1;
2236
2237 if (two_by_two_dbs)
2238 dbs_capability = DRV_DBS_CAPABILITY_2X2;
2239
2240 if (!one_by_one_dbs && !two_by_two_dbs)
2241 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2242 } else {
2243 hdd_err("wma_get_dbs_hw_mode failed");
2244 dbs_capability = DRV_DBS_CAPABILITY_DISABLED;
2245 }
2246
2247 hdd_info("dbs_capability is %d", dbs_capability);
2248
2249 if (nla_put_u32(skb,
2250 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND,
2251 MAX_CONCURRENT_CHAN_ON_24G))
2252 goto nla_put_failure;
2253
2254 if (nla_put_u32(skb,
2255 QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND,
2256 MAX_CONCURRENT_CHAN_ON_5G))
2257 goto nla_put_failure;
2258
2259 return cfg80211_vendor_cmd_reply(skb);
2260
2261nla_put_failure:
2262 kfree_skb(skb);
2263 return -EINVAL;
2264}
2265
2266/**
2267 * wlan_hdd_cfg80211_get_features() - Get the Driver Supported features
2268 * @wiphy: pointer to wireless wiphy structure.
2269 * @wdev: pointer to wireless_dev structure.
2270 * @data: Pointer to the data to be passed via vendor interface
2271 * @data_len:Length of the data to be passed
2272 *
2273 * This is called when wlan driver needs to send supported feature set to
2274 * supplicant upon a request/query from the supplicant.
2275 *
2276 * Return: Return the Success or Failure code.
2277 */
2278static int
2279wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
2280 struct wireless_dev *wdev,
2281 const void *data, int data_len)
2282{
2283 int ret;
2284
2285 cds_ssr_protect(__func__);
2286 ret = __wlan_hdd_cfg80211_get_features(wiphy, wdev,
2287 data, data_len);
2288 cds_ssr_unprotect(__func__);
2289
2290 return ret;
2291}
2292
2293
2294/**
2295 * __wlan_hdd_cfg80211_set_ext_roam_params() - Settings for roaming parameters
2296 * @wiphy: The wiphy structure
2297 * @wdev: The wireless device
2298 * @data: Data passed by framework
2299 * @data_len: Parameters to be configured passed as data
2300 *
2301 * The roaming related parameters are configured by the framework
2302 * using this interface.
2303 *
2304 * Return: Return either success or failure code.
2305 */
2306static int
2307__wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2308 struct wireless_dev *wdev, const void *data, int data_len)
2309{
2310 struct net_device *dev = wdev->netdev;
2311 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2312 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
2313 uint8_t session_id;
2314 struct roam_ext_params roam_params;
2315 uint32_t cmd_type, req_id;
2316 struct nlattr *curr_attr;
2317 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2318 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX + 1];
2319 int rem, i;
2320 uint32_t buf_len = 0;
2321 int ret;
2322
Jeff Johnson1f61b612016-02-12 16:28:33 -08002323 ENTER_DEV(dev);
2324
Anurag Chouhan6d760662016-02-20 16:05:43 +05302325 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002326 hdd_err("Command not allowed in FTM mode");
2327 return -EPERM;
2328 }
2329
2330 ret = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302331 if (ret)
2332 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002333
2334 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2335 data, data_len,
2336 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002337 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002338 return -EINVAL;
2339 }
2340 /* Parse and fetch Command Type*/
2341 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002342 hdd_err("roam cmd type failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002343 goto fail;
2344 }
2345 session_id = pAdapter->sessionId;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05302346 qdf_mem_set(&roam_params, sizeof(roam_params), 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002347 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD]);
2348 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002349 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002350 goto fail;
2351 }
2352 req_id = nla_get_u32(
2353 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002354 hdd_debug("Req Id (%d)", req_id);
2355 hdd_debug("Cmd Type (%d)", cmd_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002356 switch (cmd_type) {
2357 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST:
2358 i = 0;
2359 nla_for_each_nested(curr_attr,
2360 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST],
2361 rem) {
2362 if (nla_parse(tb2,
2363 QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX,
2364 nla_data(curr_attr), nla_len(curr_attr),
2365 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002366 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002367 goto fail;
2368 }
2369 /* Parse and Fetch allowed SSID list*/
2370 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002371 hdd_err("attr allowed ssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002372 goto fail;
2373 }
2374 buf_len = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID]);
2375 /*
2376 * Upper Layers include a null termination character.
2377 * Check for the actual permissible length of SSID and
2378 * also ensure not to copy the NULL termination
2379 * character to the driver buffer.
2380 */
2381 if (buf_len && (i < MAX_SSID_ALLOWED_LIST) &&
2382 ((buf_len - 1) <= SIR_MAC_MAX_SSID_LENGTH)) {
2383 nla_memcpy(
2384 roam_params.ssid_allowed_list[i].ssId,
2385 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID],
2386 buf_len - 1);
2387 roam_params.ssid_allowed_list[i].length =
2388 buf_len - 1;
Jeff Johnson020db452016-06-29 14:37:26 -07002389 hdd_debug("SSID[%d]: %.*s,length = %d", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002390 roam_params.ssid_allowed_list[i].length,
2391 roam_params.ssid_allowed_list[i].ssId,
2392 roam_params.ssid_allowed_list[i].length);
2393 i++;
2394 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002395 hdd_err("Invalid buffer length");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002396 }
2397 }
2398 roam_params.num_ssid_allowed_list = i;
Jeff Johnson020db452016-06-29 14:37:26 -07002399 hdd_debug("Num of Allowed SSID %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002400 roam_params.num_ssid_allowed_list);
2401 sme_update_roam_params(pHddCtx->hHal, session_id,
2402 roam_params, REASON_ROAM_SET_SSID_ALLOWED);
2403 break;
2404 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_EXTSCAN_ROAM_PARAMS:
2405 /* Parse and fetch 5G Boost Threshold */
2406 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002407 hdd_err("5G boost threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002408 goto fail;
2409 }
2410 roam_params.raise_rssi_thresh_5g = nla_get_s32(
2411 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002412 hdd_debug("5G Boost Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002413 roam_params.raise_rssi_thresh_5g);
2414 /* Parse and fetch 5G Penalty Threshold */
2415 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002416 hdd_err("5G penalty threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002417 goto fail;
2418 }
2419 roam_params.drop_rssi_thresh_5g = nla_get_s32(
2420 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD]);
Jeff Johnson020db452016-06-29 14:37:26 -07002421 hdd_debug("5G Penalty Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002422 roam_params.drop_rssi_thresh_5g);
2423 /* Parse and fetch 5G Boost Factor */
2424 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002425 hdd_err("5G boost Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002426 goto fail;
2427 }
2428 roam_params.raise_factor_5g = nla_get_u32(
2429 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002430 hdd_debug("5G Boost Factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002431 roam_params.raise_factor_5g);
2432 /* Parse and fetch 5G Penalty factor */
2433 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002434 hdd_err("5G Penalty Factor failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002435 goto fail;
2436 }
2437 roam_params.drop_factor_5g = nla_get_u32(
2438 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR]);
Jeff Johnson020db452016-06-29 14:37:26 -07002439 hdd_debug("5G Penalty factor (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002440 roam_params.drop_factor_5g);
2441 /* Parse and fetch 5G Max Boost */
2442 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002443 hdd_err("5G Max Boost failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002444 goto fail;
2445 }
2446 roam_params.max_raise_rssi_5g = nla_get_u32(
2447 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST]);
Jeff Johnson020db452016-06-29 14:37:26 -07002448 hdd_debug("5G Max Boost (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002449 roam_params.max_raise_rssi_5g);
2450 /* Parse and fetch Rssi Diff */
2451 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002452 hdd_err("Rssi Diff failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002453 goto fail;
2454 }
2455 roam_params.rssi_diff = nla_get_s32(
2456 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS]);
Jeff Johnson020db452016-06-29 14:37:26 -07002457 hdd_debug("RSSI Diff (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002458 roam_params.rssi_diff);
2459 /* Parse and fetch Alert Rssi Threshold */
2460 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002461 hdd_err("Alert Rssi Threshold failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002462 goto fail;
2463 }
2464 roam_params.alert_rssi_threshold = nla_get_u32(
2465 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002466 hdd_debug("Alert RSSI Threshold (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002467 roam_params.alert_rssi_threshold);
2468 sme_update_roam_params(pHddCtx->hHal, session_id,
2469 roam_params,
2470 REASON_ROAM_EXT_SCAN_PARAMS_CHANGED);
2471 break;
2472 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM:
2473 /* Parse and fetch Activate Good Rssi Roam */
2474 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002475 hdd_err("Activate Good Rssi Roam failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002476 goto fail;
2477 }
2478 roam_params.good_rssi_roam = nla_get_s32(
2479 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE]);
Jeff Johnson020db452016-06-29 14:37:26 -07002480 hdd_debug("Activate Good Rssi Roam (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002481 roam_params.good_rssi_roam);
2482 sme_update_roam_params(pHddCtx->hHal, session_id,
2483 roam_params, REASON_ROAM_GOOD_RSSI_CHANGED);
2484 break;
2485 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS:
2486 /* Parse and fetch number of preferred BSSID */
2487 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002488 hdd_err("attr num of preferred bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002489 goto fail;
2490 }
2491 roam_params.num_bssid_favored = nla_get_u32(
2492 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002493 hdd_debug("Num of Preferred BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002494 roam_params.num_bssid_favored);
2495 i = 0;
2496 nla_for_each_nested(curr_attr,
2497 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS],
2498 rem) {
2499 if (nla_parse(tb2,
2500 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2501 nla_data(curr_attr), nla_len(curr_attr),
2502 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002503 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002504 goto fail;
2505 }
2506 /* Parse and fetch MAC address */
2507 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002508 hdd_err("attr mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002509 goto fail;
2510 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002511 nla_memcpy(roam_params.bssid_favored[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002512 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302513 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002514 hdd_debug(MAC_ADDRESS_STR,
2515 MAC_ADDR_ARRAY(roam_params.bssid_favored[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002516 /* Parse and fetch preference factor*/
2517 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002518 hdd_err("BSSID Preference score failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002519 goto fail;
2520 }
2521 roam_params.bssid_favored_factor[i] = nla_get_u32(
2522 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER]);
Jeff Johnson020db452016-06-29 14:37:26 -07002523 hdd_debug("BSSID Preference score (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002524 roam_params.bssid_favored_factor[i]);
2525 i++;
2526 }
2527 sme_update_roam_params(pHddCtx->hHal, session_id,
2528 roam_params, REASON_ROAM_SET_FAVORED_BSSID);
2529 break;
2530 case QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID:
2531 /* Parse and fetch number of blacklist BSSID */
2532 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002533 hdd_err("attr num of blacklist bssid failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002534 goto fail;
2535 }
2536 roam_params.num_bssid_avoid_list = nla_get_u32(
2537 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID]);
Jeff Johnson020db452016-06-29 14:37:26 -07002538 hdd_debug("Num of blacklist BSSID (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002539 roam_params.num_bssid_avoid_list);
2540 i = 0;
2541 nla_for_each_nested(curr_attr,
2542 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS],
2543 rem) {
2544 if (nla_parse(tb2,
2545 QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX,
2546 nla_data(curr_attr), nla_len(curr_attr),
2547 NULL)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002548 hdd_err("nla_parse failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002549 goto fail;
2550 }
2551 /* Parse and fetch MAC address */
2552 if (!tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID]) {
Jeff Johnson020db452016-06-29 14:37:26 -07002553 hdd_err("attr blacklist addr failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002554 goto fail;
2555 }
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002556 nla_memcpy(roam_params.bssid_avoid_list[i].bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002557 tb2[QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID],
Anurag Chouhan6d760662016-02-20 16:05:43 +05302558 QDF_MAC_ADDR_SIZE);
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002559 hdd_debug(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002560 MAC_ADDR_ARRAY(
Srinivas Girigowdab0532392015-11-24 11:50:16 -08002561 roam_params.bssid_avoid_list[i].bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002562 i++;
2563 }
2564 sme_update_roam_params(pHddCtx->hHal, session_id,
2565 roam_params, REASON_ROAM_SET_BLACKLIST_BSSID);
2566 break;
2567 }
2568 return 0;
2569fail:
2570 return -EINVAL;
2571}
2572
2573/**
2574 * wlan_hdd_cfg80211_set_ext_roam_params() - set ext scan roam params
2575 * @wiphy: pointer to wireless wiphy structure.
2576 * @wdev: pointer to wireless_dev structure.
2577 * @data: Pointer to the data to be passed via vendor interface
2578 * @data_len:Length of the data to be passed
2579 *
2580 * Return: Return the Success or Failure code.
2581 */
2582static int
2583wlan_hdd_cfg80211_set_ext_roam_params(struct wiphy *wiphy,
2584 struct wireless_dev *wdev,
2585 const void *data,
2586 int data_len)
2587{
2588 int ret;
2589
2590 cds_ssr_protect(__func__);
2591 ret = __wlan_hdd_cfg80211_set_ext_roam_params(wiphy, wdev,
2592 data, data_len);
2593 cds_ssr_unprotect(__func__);
2594
2595 return ret;
2596}
2597
2598static const struct nla_policy
2599wlan_hdd_set_no_dfs_flag_config_policy[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX
2600 +1] = {
2601 [QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG] = {.type = NLA_U32 },
2602};
2603
2604/**
2605 * wlan_hdd_check_dfs_channel_for_adapter() - check dfs channel in adapter
2606 * @hdd_ctx: HDD context
2607 * @device_mode: device mode
2608 * Return: bool
2609 */
2610static bool wlan_hdd_check_dfs_channel_for_adapter(hdd_context_t *hdd_ctx,
Krunal Sonib4326f22016-03-10 13:05:51 -08002611 enum tQDF_ADAPTER_MODE device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002612{
2613 hdd_adapter_t *adapter;
2614 hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL;
2615 hdd_ap_ctx_t *ap_ctx;
2616 hdd_station_ctx_t *sta_ctx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302617 QDF_STATUS qdf_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002618
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302619 qdf_status = hdd_get_front_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002620 &adapter_node);
2621
2622 while ((NULL != adapter_node) &&
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302623 (QDF_STATUS_SUCCESS == qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002624 adapter = adapter_node->pAdapter;
2625
2626 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002627 (device_mode == QDF_SAP_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002628 ap_ctx =
2629 WLAN_HDD_GET_AP_CTX_PTR(adapter);
2630
2631 /*
2632 * if there is SAP already running on DFS channel,
2633 * do not disable scan on dfs channels. Note that
2634 * with SAP on DFS, there cannot be conurrency on
2635 * single radio. But then we can have multiple
2636 * radios !!
2637 */
2638 if (CHANNEL_STATE_DFS ==
2639 cds_get_channel_state(
2640 ap_ctx->operatingChannel)) {
Jeff Johnson020db452016-06-29 14:37:26 -07002641 hdd_err("SAP running on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002642 return true;
2643 }
2644 }
2645
2646 if ((device_mode == adapter->device_mode) &&
Krunal Sonib4326f22016-03-10 13:05:51 -08002647 (device_mode == QDF_STA_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002648 sta_ctx =
2649 WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2650
2651 /*
2652 * if STA is already connected on DFS channel,
2653 * do not disable scan on dfs channels
2654 */
2655 if (hdd_conn_is_connected(sta_ctx) &&
2656 (CHANNEL_STATE_DFS ==
2657 cds_get_channel_state(
2658 sta_ctx->conn_info.operationChannel))) {
Jeff Johnson020db452016-06-29 14:37:26 -07002659 hdd_err("client connected on DFS channel");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002660 return true;
2661 }
2662 }
2663
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302664 qdf_status = hdd_get_next_adapter(hdd_ctx,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002665 adapter_node,
2666 &next);
2667 adapter_node = next;
2668 }
2669
2670 return false;
2671}
2672
2673/**
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002674 * wlan_hdd_disable_dfs_chan_scan() - disable/enable DFS channels
2675 * @hdd_ctx: HDD context within host driver
2676 * @adapter: Adapter pointer
2677 * @no_dfs_flag: If TRUE, DFS channels cannot be used for scanning
2678 *
2679 * Loops through devices to see who is operating on DFS channels
2680 * and then disables/enables DFS channels by calling SME API.
2681 * Fails the disable request if any device is active on a DFS channel.
2682 *
2683 * Return: 0 or other error codes.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002684 */
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002685
2686int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx,
2687 hdd_adapter_t *adapter,
2688 uint32_t no_dfs_flag)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002689{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002690 tHalHandle h_hal = WLAN_HDD_GET_HAL_CTX(adapter);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302691 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002692 int ret_val = -EPERM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002693
2694 if (no_dfs_flag == hdd_ctx->config->enableDFSChnlScan) {
2695 if (no_dfs_flag) {
2696 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002697 hdd_ctx, QDF_STA_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002698
2699 if (true == status)
2700 return -EOPNOTSUPP;
2701
2702 status = wlan_hdd_check_dfs_channel_for_adapter(
Krunal Sonib4326f22016-03-10 13:05:51 -08002703 hdd_ctx, QDF_SAP_MODE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002704
2705 if (true == status)
2706 return -EOPNOTSUPP;
2707 }
2708
2709 hdd_ctx->config->enableDFSChnlScan = !no_dfs_flag;
2710
2711 hdd_abort_mac_scan_all_adapters(hdd_ctx);
2712
2713 /*
2714 * call the SME API to tunnel down the new channel list
2715 * to the firmware
2716 */
2717 status = sme_handle_dfs_chan_scan(
2718 h_hal, hdd_ctx->config->enableDFSChnlScan);
2719
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302720 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002721 ret_val = 0;
2722
2723 /*
2724 * Clear the SME scan cache also. Note that the
2725 * clearing of scan results is independent of session;
2726 * so no need to iterate over
2727 * all sessions
2728 */
2729 status = sme_scan_flush_result(h_hal);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302730 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002731 ret_val = -EPERM;
2732 }
2733
2734 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07002735 hdd_notice(" the DFS flag has not changed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002736 ret_val = 0;
2737 }
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002738 return ret_val;
2739}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002740
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002741/**
2742 * __wlan_hdd_cfg80211_disable_dfs_chan_scan() - DFS channel configuration
2743 * @wiphy: corestack handler
2744 * @wdev: wireless device
2745 * @data: data
2746 * @data_len: data length
2747 * Return: success(0) or reason code for failure
2748 */
2749static int __wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2750 struct wireless_dev *wdev,
2751 const void *data,
2752 int data_len)
2753{
2754 struct net_device *dev = wdev->netdev;
2755 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2756 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2757 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX + 1];
2758 int ret_val;
2759 uint32_t no_dfs_flag = 0;
2760
Jeff Johnson1f61b612016-02-12 16:28:33 -08002761 ENTER_DEV(dev);
2762
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002763 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05302764 if (ret_val)
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002765 return ret_val;
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002766
2767 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX,
2768 data, data_len,
2769 wlan_hdd_set_no_dfs_flag_config_policy)) {
2770 hdd_err("invalid attr");
2771 return -EINVAL;
2772 }
2773
2774 if (!tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]) {
2775 hdd_err("attr dfs flag failed");
2776 return -EINVAL;
2777 }
2778
2779 no_dfs_flag = nla_get_u32(
2780 tb[QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG]);
2781
Jeff Johnson020db452016-06-29 14:37:26 -07002782 hdd_notice(" DFS flag = %d", no_dfs_flag);
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002783
2784 if (no_dfs_flag > 1) {
Jeff Johnson020db452016-06-29 14:37:26 -07002785 hdd_err("invalid value of dfs flag");
Deepak Dhamdhere29b3b2f2015-01-22 11:09:55 -08002786 return -EINVAL;
2787 }
2788
2789 ret_val = wlan_hdd_disable_dfs_chan_scan(hdd_ctx, adapter,
2790 no_dfs_flag);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002791 return ret_val;
2792}
2793
2794/**
2795 * wlan_hdd_cfg80211_disable_dfs_chan_scan () - DFS scan vendor command
2796 *
2797 * @wiphy: wiphy device pointer
2798 * @wdev: wireless device pointer
Manikandan Mohan80dea792016-04-28 16:36:48 -07002799 * @data: Vendor command data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08002800 * @data_len: Buffer length
2801 *
2802 * Handles QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG_MAX. Validate it and
2803 * call wlan_hdd_disable_dfs_chan_scan to send it to firmware.
2804 *
2805 * Return: EOK or other error codes.
2806 */
2807
2808static int wlan_hdd_cfg80211_disable_dfs_chan_scan(struct wiphy *wiphy,
2809 struct wireless_dev *wdev,
2810 const void *data,
2811 int data_len)
2812{
2813 int ret;
2814
2815 cds_ssr_protect(__func__);
2816 ret = __wlan_hdd_cfg80211_disable_dfs_chan_scan(wiphy, wdev,
2817 data, data_len);
2818 cds_ssr_unprotect(__func__);
2819
2820 return ret;
2821}
2822
Manikandan Mohan80dea792016-04-28 16:36:48 -07002823static const struct nla_policy
2824wlan_hdd_wisa_cmd_policy[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1] = {
2825 [QCA_WLAN_VENDOR_ATTR_WISA_MODE] = {.type = NLA_U32 },
2826};
2827
2828/**
2829 * __wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2830 * @wiphy: wiphy device pointer
2831 * @wdev: wireless device pointer
2832 * @data: Vendor command data buffer
2833 * @data_len: Buffer length
2834 *
2835 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2836 * setup WISA Mode features.
2837 *
2838 * Return: Success(0) or reason code for failure
2839 */
2840static int __wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2841 struct wireless_dev *wdev, const void *data, int data_len)
2842{
2843 struct net_device *dev = wdev->netdev;
2844 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
2845 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
2846 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WISA_MAX + 1];
2847 struct sir_wisa_params wisa;
2848 int ret_val;
2849 QDF_STATUS status;
2850 bool wisa_mode;
2851
2852 ENTER_DEV(dev);
2853 ret_val = wlan_hdd_validate_context(hdd_ctx);
2854 if (ret_val)
2855 goto err;
2856
2857 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
2858 hdd_err("Command not allowed in FTM mode");
2859 return -EPERM;
2860 }
2861
2862 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WISA_MAX, data, data_len,
2863 wlan_hdd_wisa_cmd_policy)) {
2864 hdd_err("Invalid WISA cmd attributes");
2865 ret_val = -EINVAL;
2866 goto err;
2867 }
2868 if (!tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]) {
2869 hdd_err("Invalid WISA mode");
2870 ret_val = -EINVAL;
2871 goto err;
2872 }
2873
2874 wisa_mode = !!nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_WISA_MODE]);
2875 hdd_info("WISA Mode: %d", wisa_mode);
2876 wisa.mode = wisa_mode;
2877 wisa.vdev_id = adapter->sessionId;
2878 status = sme_set_wisa_params(hdd_ctx->hHal, &wisa);
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002879 if (!QDF_IS_STATUS_SUCCESS(status)) {
2880 hdd_err("Unable to set WISA mode: %d to FW", wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002881 ret_val = -EINVAL;
Manikandan Mohanb6315dd2016-05-10 16:16:36 -07002882 }
2883 if (QDF_IS_STATUS_SUCCESS(status) || wisa_mode == false)
2884 ol_txrx_set_wisa_mode(ol_txrx_get_vdev_from_vdev_id(
2885 adapter->sessionId), wisa_mode);
Manikandan Mohan80dea792016-04-28 16:36:48 -07002886err:
2887 EXIT();
2888 return ret_val;
2889}
2890
2891/**
2892 * wlan_hdd_cfg80211_handle_wisa_cmd() - Handle WISA vendor cmd
2893 * @wiphy: corestack handler
2894 * @wdev: wireless device
2895 * @data: data
2896 * @data_len: data length
2897 *
2898 * Handles QCA_WLAN_VENDOR_SUBCMD_WISA. Validate cmd attributes and
2899 * setup WISA mode features.
2900 *
2901 * Return: Success(0) or reason code for failure
2902 */
2903static int wlan_hdd_cfg80211_handle_wisa_cmd(struct wiphy *wiphy,
2904 struct wireless_dev *wdev,
2905 const void *data,
2906 int data_len)
2907{
2908 int ret;
2909
2910 cds_ssr_protect(__func__);
2911 ret = __wlan_hdd_cfg80211_handle_wisa_cmd(wiphy, wdev, data, data_len);
2912 cds_ssr_unprotect(__func__);
2913
2914 return ret;
2915}
2916
Anurag Chouhan96919482016-07-13 16:36:57 +05302917/*
2918 * define short names for the global vendor params
2919 * used by __wlan_hdd_cfg80211_get_station_cmd()
2920 */
2921#define STATION_INVALID \
2922 QCA_WLAN_VENDOR_ATTR_GET_STATION_INVALID
2923#define STATION_INFO \
2924 QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO
2925#define STATION_ASSOC_FAIL_REASON \
2926 QCA_WLAN_VENDOR_ATTR_GET_STATION_ASSOC_FAIL_REASON
2927#define STATION_MAX \
2928 QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX
2929
2930static const struct nla_policy
2931hdd_get_station_policy[STATION_MAX + 1] = {
2932 [STATION_INFO] = {.type = NLA_FLAG},
2933 [STATION_ASSOC_FAIL_REASON] = {.type = NLA_FLAG},
2934};
2935
2936/**
2937 * hdd_get_station_assoc_fail() - Handle get station assoc fail
2938 * @hdd_ctx: HDD context within host driver
2939 * @wdev: wireless device
2940 *
2941 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION_ASSOC_FAIL.
2942 * Validate cmd attributes and send the station info to upper layers.
2943 *
2944 * Return: Success(0) or reason code for failure
2945 */
2946static int hdd_get_station_assoc_fail(hdd_context_t *hdd_ctx,
2947 hdd_adapter_t *adapter)
2948{
2949 struct sk_buff *skb = NULL;
2950 uint32_t nl_buf_len;
2951 hdd_station_ctx_t *hdd_sta_ctx;
2952
2953 nl_buf_len = NLMSG_HDRLEN;
2954 nl_buf_len += sizeof(uint32_t);
2955 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
2956
2957 if (!skb) {
2958 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
2959 return -ENOMEM;
2960 }
2961
2962 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
2963
2964 if (nla_put_u32(skb, INFO_ASSOC_FAIL_REASON,
2965 hdd_sta_ctx->conn_info.assoc_status_code)) {
2966 hdd_err("put fail");
2967 goto fail;
2968 }
2969 return cfg80211_vendor_cmd_reply(skb);
2970fail:
2971 if (skb)
2972 kfree_skb(skb);
2973 return -EINVAL;
2974}
2975
2976/**
2977 * hdd_map_auth_type() - transform auth type specific to
2978 * vendor command
2979 * @auth_type: csr auth type
2980 *
2981 * Return: Success(0) or reason code for failure
2982 */
2983static int hdd_convert_auth_type(uint32_t auth_type)
2984{
2985 uint32_t ret_val;
2986
2987 switch (auth_type) {
2988 case eCSR_AUTH_TYPE_OPEN_SYSTEM:
2989 ret_val = QCA_WLAN_AUTH_TYPE_OPEN;
2990 break;
2991 case eCSR_AUTH_TYPE_SHARED_KEY:
2992 ret_val = QCA_WLAN_AUTH_TYPE_SHARED;
2993 break;
2994 case eCSR_AUTH_TYPE_WPA:
2995 ret_val = QCA_WLAN_AUTH_TYPE_WPA;
2996 break;
2997 case eCSR_AUTH_TYPE_WPA_PSK:
2998 ret_val = QCA_WLAN_AUTH_TYPE_WPA_PSK;
2999 break;
3000 case eCSR_AUTH_TYPE_AUTOSWITCH:
3001 ret_val = QCA_WLAN_AUTH_TYPE_AUTOSWITCH;
3002 break;
3003 case eCSR_AUTH_TYPE_WPA_NONE:
3004 ret_val = QCA_WLAN_AUTH_TYPE_WPA_NONE;
3005 break;
3006 case eCSR_AUTH_TYPE_RSN:
3007 ret_val = QCA_WLAN_AUTH_TYPE_RSN;
3008 break;
3009 case eCSR_AUTH_TYPE_RSN_PSK:
3010 ret_val = QCA_WLAN_AUTH_TYPE_RSN_PSK;
3011 break;
3012 case eCSR_AUTH_TYPE_FT_RSN:
3013 ret_val = QCA_WLAN_AUTH_TYPE_FT;
3014 break;
3015 case eCSR_AUTH_TYPE_FT_RSN_PSK:
3016 ret_val = QCA_WLAN_AUTH_TYPE_FT_PSK;
3017 break;
3018 case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
3019 ret_val = QCA_WLAN_AUTH_TYPE_WAI;
3020 break;
3021 case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
3022 ret_val = QCA_WLAN_AUTH_TYPE_WAI_PSK;
3023 break;
3024 case eCSR_AUTH_TYPE_CCKM_WPA:
3025 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_WPA;
3026 break;
3027 case eCSR_AUTH_TYPE_CCKM_RSN:
3028 ret_val = QCA_WLAN_AUTH_TYPE_CCKM_RSN;
3029 break;
3030 case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
3031 ret_val = QCA_WLAN_AUTH_TYPE_SHA256_PSK;
3032 break;
3033 case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
3034 ret_val = QCA_WLAN_AUTH_TYPE_SHA256;
3035 break;
3036 case eCSR_NUM_OF_SUPPORT_AUTH_TYPE:
3037 case eCSR_AUTH_TYPE_FAILED:
3038 case eCSR_AUTH_TYPE_NONE:
3039 default:
3040 ret_val = QCA_WLAN_AUTH_TYPE_INVALID;
3041 break;
3042 }
3043 return ret_val;
3044}
3045
3046/**
3047 * hdd_map_dot_11_mode() - transform dot11mode type specific to
3048 * vendor command
3049 * @dot11mode: dot11mode
3050 *
3051 * Return: Success(0) or reason code for failure
3052 */
3053static int hdd_convert_dot11mode(uint32_t dot11mode)
3054{
3055 uint32_t ret_val;
3056
3057 switch (dot11mode) {
3058 case eCSR_CFG_DOT11_MODE_11A:
3059 ret_val = QCA_WLAN_802_11_MODE_11A;
3060 break;
3061 case eCSR_CFG_DOT11_MODE_11B:
3062 ret_val = QCA_WLAN_802_11_MODE_11B;
3063 break;
3064 case eCSR_CFG_DOT11_MODE_11G:
3065 ret_val = QCA_WLAN_802_11_MODE_11G;
3066 break;
3067 case eCSR_CFG_DOT11_MODE_11N:
3068 ret_val = QCA_WLAN_802_11_MODE_11N;
3069 break;
3070 case eCSR_CFG_DOT11_MODE_11AC:
3071 ret_val = QCA_WLAN_802_11_MODE_11AC;
3072 break;
3073 case eCSR_CFG_DOT11_MODE_AUTO:
3074 case eCSR_CFG_DOT11_MODE_ABG:
3075 default:
3076 ret_val = QCA_WLAN_802_11_MODE_INVALID;
3077 }
3078 return ret_val;
3079}
3080
3081/**
3082 * hdd_add_tx_bitrate() - add tx bitrate attribute
3083 * @skb: pointer to sk buff
3084 * @hdd_sta_ctx: pointer to hdd station context
3085 * @idx: attribute index
3086 *
3087 * Return: Success(0) or reason code for failure
3088 */
3089static int32_t hdd_add_tx_bitrate(struct sk_buff *skb,
3090 hdd_station_ctx_t *hdd_sta_ctx,
3091 int idx)
3092{
3093 struct nlattr *nla_attr;
3094 uint32_t bitrate, bitrate_compat;
3095
3096 nla_attr = nla_nest_start(skb, idx);
3097 if (!nla_attr)
3098 goto fail;
3099 /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
3100 bitrate = cfg80211_calculate_bitrate(&hdd_sta_ctx->conn_info.txrate);
3101
3102 /* report 16-bit bitrate only if we can */
3103 bitrate_compat = bitrate < (1UL << 16) ? bitrate : 0;
3104 if (bitrate > 0 &&
3105 nla_put_u32(skb, NL80211_RATE_INFO_BITRATE32, bitrate)) {
3106 hdd_err("put fail");
3107 goto fail;
3108 }
3109 if (bitrate_compat > 0 &&
3110 nla_put_u16(skb, NL80211_RATE_INFO_BITRATE, bitrate_compat)) {
3111 hdd_err("put fail");
3112 goto fail;
3113 }
3114 if (nla_put_u8(skb, NL80211_RATE_INFO_VHT_NSS,
3115 hdd_sta_ctx->conn_info.txrate.nss)) {
3116 hdd_err("put fail");
3117 goto fail;
3118 }
3119 nla_nest_end(skb, nla_attr);
3120 return 0;
3121fail:
3122 return -EINVAL;
3123}
3124
3125/**
3126 * hdd_add_sta_info() - add station info attribute
3127 * @skb: pointer to sk buff
3128 * @hdd_sta_ctx: pointer to hdd station context
3129 * @idx: attribute index
3130 *
3131 * Return: Success(0) or reason code for failure
3132 */
3133static int32_t hdd_add_sta_info(struct sk_buff *skb,
3134 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3135{
3136 struct nlattr *nla_attr;
3137
3138 nla_attr = nla_nest_start(skb, idx);
3139 if (!nla_attr)
3140 goto fail;
3141 if (nla_put_u8(skb, NL80211_STA_INFO_SIGNAL,
3142 (hdd_sta_ctx->conn_info.signal + 100))) {
3143 hdd_err("put fail");
3144 goto fail;
3145 }
3146 if (hdd_add_tx_bitrate(skb, hdd_sta_ctx, NL80211_STA_INFO_TX_BITRATE))
3147 goto fail;
3148 nla_nest_end(skb, nla_attr);
3149 return 0;
3150fail:
3151 return -EINVAL;
3152}
3153
3154/**
3155 * hdd_add_survey_info() - add survey info attribute
3156 * @skb: pointer to sk buff
3157 * @hdd_sta_ctx: pointer to hdd station context
3158 * @idx: attribute index
3159 *
3160 * Return: Success(0) or reason code for failure
3161 */
3162static int32_t hdd_add_survey_info(struct sk_buff *skb,
3163 hdd_station_ctx_t *hdd_sta_ctx,
3164 int idx)
3165{
3166 struct nlattr *nla_attr;
3167
3168 nla_attr = nla_nest_start(skb, idx);
3169 if (!nla_attr)
3170 goto fail;
3171 if (nla_put_u32(skb, NL80211_SURVEY_INFO_FREQUENCY,
3172 hdd_sta_ctx->conn_info.freq) ||
3173 nla_put_u8(skb, NL80211_SURVEY_INFO_NOISE,
3174 (hdd_sta_ctx->conn_info.noise + 100))) {
3175 hdd_err("put fail");
3176 goto fail;
3177 }
3178 nla_nest_end(skb, nla_attr);
3179 return 0;
3180fail:
3181 return -EINVAL;
3182}
3183
3184/**
3185 * hdd_add_link_standard_info() - add link info attribute
3186 * @skb: pointer to sk buff
3187 * @hdd_sta_ctx: pointer to hdd station context
3188 * @idx: attribute index
3189 *
3190 * Return: Success(0) or reason code for failure
3191 */
3192static int32_t
3193hdd_add_link_standard_info(struct sk_buff *skb,
3194 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3195{
3196 struct nlattr *nla_attr;
3197
3198 nla_attr = nla_nest_start(skb, idx);
3199 if (!nla_attr)
3200 goto fail;
3201 if (nla_put(skb,
3202 NL80211_ATTR_SSID,
3203 hdd_sta_ctx->conn_info.SSID.SSID.length,
3204 hdd_sta_ctx->conn_info.SSID.SSID.ssId)) {
3205 hdd_err("put fail");
3206 goto fail;
3207 }
3208 if (hdd_add_survey_info(skb, hdd_sta_ctx, NL80211_ATTR_SURVEY_INFO))
3209 goto fail;
3210 if (hdd_add_sta_info(skb, hdd_sta_ctx, NL80211_ATTR_STA_INFO))
3211 goto fail;
3212 nla_nest_end(skb, nla_attr);
3213 return 0;
3214fail:
3215 return -EINVAL;
3216}
3217
3218/**
3219 * hdd_add_ap_standard_info() - add ap info attribute
3220 * @skb: pointer to sk buff
3221 * @hdd_sta_ctx: pointer to hdd station context
3222 * @idx: attribute index
3223 *
3224 * Return: Success(0) or reason code for failure
3225 */
3226static int32_t
3227hdd_add_ap_standard_info(struct sk_buff *skb,
3228 hdd_station_ctx_t *hdd_sta_ctx, int idx)
3229{
3230 struct nlattr *nla_attr;
3231
3232 nla_attr = nla_nest_start(skb, idx);
3233 if (!nla_attr)
3234 goto fail;
3235 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3236 if (nla_put(skb, NL80211_ATTR_VHT_CAPABILITY,
3237 sizeof(hdd_sta_ctx->conn_info.vht_caps),
3238 &hdd_sta_ctx->conn_info.vht_caps)) {
3239 hdd_err("put fail");
3240 goto fail;
3241 }
3242 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3243 if (nla_put(skb, NL80211_ATTR_HT_CAPABILITY,
3244 sizeof(hdd_sta_ctx->conn_info.ht_caps),
3245 &hdd_sta_ctx->conn_info.ht_caps)) {
3246 hdd_err("put fail");
3247 goto fail;
3248 }
3249 nla_nest_end(skb, nla_attr);
3250 return 0;
3251fail:
3252 return -EINVAL;
3253}
3254
3255/**
3256 * hdd_get_station_info() - send BSS information to supplicant
3257 * @hdd_ctx: pointer to hdd context
3258 * @adapter: pointer to adapter
3259 *
3260 * Return: 0 if success else error status
3261 */
3262static int hdd_get_station_info(hdd_context_t *hdd_ctx,
3263 hdd_adapter_t *adapter)
3264{
3265 struct sk_buff *skb = NULL;
3266 uint8_t *tmp_hs20 = NULL;
3267 uint32_t nl_buf_len;
3268 hdd_station_ctx_t *hdd_sta_ctx;
3269
3270 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
3271
3272 nl_buf_len = NLMSG_HDRLEN;
3273 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.SSID.SSID.length) +
3274 sizeof(hdd_sta_ctx->conn_info.freq) +
3275 sizeof(hdd_sta_ctx->conn_info.noise) +
3276 sizeof(hdd_sta_ctx->conn_info.signal) +
3277 (sizeof(uint32_t) * 2) +
3278 sizeof(hdd_sta_ctx->conn_info.txrate.nss) +
3279 sizeof(hdd_sta_ctx->conn_info.roam_count) +
3280 sizeof(hdd_sta_ctx->conn_info.authType) +
3281 sizeof(hdd_sta_ctx->conn_info.dot11Mode);
3282 if (hdd_sta_ctx->conn_info.conn_flag.vht_present)
3283 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_caps);
3284 if (hdd_sta_ctx->conn_info.conn_flag.ht_present)
3285 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_caps);
3286 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present) {
3287 tmp_hs20 = (uint8_t *)&(hdd_sta_ctx->conn_info.hs20vendor_ie);
3288 nl_buf_len += (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) -
3289 1);
3290 }
3291 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3292 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.ht_operation);
3293 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3294 nl_buf_len += sizeof(hdd_sta_ctx->conn_info.vht_operation);
3295
3296
3297 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
3298 if (!skb) {
3299 hdd_err(FL("cfg80211_vendor_cmd_alloc_reply_skb failed"));
3300 return -ENOMEM;
3301 }
3302
3303 if (hdd_add_link_standard_info(skb, hdd_sta_ctx,
3304 LINK_INFO_STANDARD_NL80211_ATTR)) {
3305 hdd_err("put fail");
3306 goto fail;
3307 }
3308 if (hdd_add_ap_standard_info(skb, hdd_sta_ctx,
3309 AP_INFO_STANDARD_NL80211_ATTR)) {
3310 hdd_err("put fail");
3311 goto fail;
3312 }
3313 if (nla_put_u32(skb, INFO_ROAM_COUNT,
3314 hdd_sta_ctx->conn_info.roam_count) ||
3315 nla_put_u32(skb, INFO_AKM,
3316 hdd_convert_auth_type(
3317 hdd_sta_ctx->conn_info.authType)) ||
3318 nla_put_u32(skb, WLAN802_11_MODE,
3319 hdd_convert_dot11mode(
3320 hdd_sta_ctx->conn_info.dot11Mode))) {
3321 hdd_err("put fail");
3322 goto fail;
3323 }
3324 if (hdd_sta_ctx->conn_info.conn_flag.ht_op_present)
3325 if (nla_put(skb, HT_OPERATION,
3326 (sizeof(hdd_sta_ctx->conn_info.ht_operation)),
3327 &hdd_sta_ctx->conn_info.ht_operation)) {
3328 hdd_err("put fail");
3329 goto fail;
3330 }
3331 if (hdd_sta_ctx->conn_info.conn_flag.vht_op_present)
3332 if (nla_put(skb, VHT_OPERATION,
3333 (sizeof(hdd_sta_ctx->conn_info.vht_operation)),
3334 &hdd_sta_ctx->conn_info.vht_operation)) {
3335 hdd_err("put fail");
3336 goto fail;
3337 }
3338 if (hdd_sta_ctx->conn_info.conn_flag.hs20_present)
3339 if (nla_put(skb, AP_INFO_HS20_INDICATION,
3340 (sizeof(hdd_sta_ctx->conn_info.hs20vendor_ie) - 1),
3341 tmp_hs20 + 1)) {
3342 hdd_err("put fail");
3343 goto fail;
3344 }
3345
3346 return cfg80211_vendor_cmd_reply(skb);
3347fail:
3348 if (skb)
3349 kfree_skb(skb);
3350 return -EINVAL;
3351}
3352
3353/**
3354 * __hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3355 * @wiphy: corestack handler
3356 * @wdev: wireless device
3357 * @data: data
3358 * @data_len: data length
3359 *
3360 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3361 * Validate cmd attributes and send the station info to upper layers.
3362 *
3363 * Return: Success(0) or reason code for failure
3364 */
Anurag Chouhand939d3d2016-07-20 17:45:48 +05303365static int
Anurag Chouhan96919482016-07-13 16:36:57 +05303366__hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3367 struct wireless_dev *wdev,
3368 const void *data,
3369 int data_len)
3370{
3371 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3372 struct net_device *dev = wdev->netdev;
3373 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3374 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX + 1];
3375 int32_t status;
3376
3377 ENTER_DEV(dev);
3378 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
3379 hdd_err("Command not allowed in FTM mode");
3380 status = -EPERM;
3381 goto out;
3382 }
3383
3384 status = wlan_hdd_validate_context(hdd_ctx);
3385 if (0 != status)
3386 goto out;
3387
3388
3389 status = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_STATION_MAX,
3390 data, data_len, NULL);
3391 if (status) {
3392 hdd_err("Invalid ATTR");
3393 goto out;
3394 }
3395
3396 /* Parse and fetch Command Type*/
3397 if (tb[STATION_INFO]) {
3398 status = hdd_get_station_info(hdd_ctx, adapter);
3399 } else if (tb[STATION_ASSOC_FAIL_REASON]) {
3400 status = hdd_get_station_assoc_fail(hdd_ctx, adapter);
3401 } else {
3402 hdd_err("get station info cmd type failed");
3403 status = -EINVAL;
3404 goto out;
3405 }
3406 EXIT();
3407out:
3408 return status;
3409}
3410
3411/**
3412 * wlan_hdd_cfg80211_get_station_cmd() - Handle get station vendor cmd
3413 * @wiphy: corestack handler
3414 * @wdev: wireless device
3415 * @data: data
3416 * @data_len: data length
3417 *
3418 * Handles QCA_NL80211_VENDOR_SUBCMD_GET_STATION.
3419 * Validate cmd attributes and send the station info to upper layers.
3420 *
3421 * Return: Success(0) or reason code for failure
3422 */
3423static int32_t
3424hdd_cfg80211_get_station_cmd(struct wiphy *wiphy,
3425 struct wireless_dev *wdev,
3426 const void *data,
3427 int data_len)
3428{
3429 int ret;
3430
3431 cds_ssr_protect(__func__);
3432 ret = __hdd_cfg80211_get_station_cmd(wiphy, wdev, data, data_len);
3433 cds_ssr_unprotect(__func__);
3434
3435 return ret;
3436}
3437
3438/*
3439 * undef short names defined for get station command
3440 * used by __wlan_hdd_cfg80211_get_station_cmd()
3441 */
3442#undef STATION_INVALID
3443#undef STATION_INFO
3444#undef STATION_ASSOC_FAIL_REASON
3445#undef STATION_MAX
3446
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003447#ifdef WLAN_FEATURE_ROAM_OFFLOAD
3448/**
3449 * __wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3450 * @wiphy: pointer to wireless wiphy structure.
3451 * @wdev: pointer to wireless_dev structure.
3452 * @data: Pointer to the Key data
3453 * @data_len:Length of the data passed
3454 *
3455 * This is called when wlan driver needs to save the keys received via
3456 * vendor specific command.
3457 *
3458 * Return: Return the Success or Failure code.
3459 */
3460static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3461 struct wireless_dev *wdev,
3462 const void *data, int data_len)
3463{
3464 uint8_t local_pmk[SIR_ROAM_SCAN_PSK_SIZE];
3465 struct net_device *dev = wdev->netdev;
3466 hdd_adapter_t *hdd_adapter_ptr = WLAN_HDD_GET_PRIV_PTR(dev);
3467 hdd_context_t *hdd_ctx_ptr;
3468 int status;
3469
Jeff Johnson1f61b612016-02-12 16:28:33 -08003470 ENTER_DEV(dev);
3471
Anurag Chouhan6d760662016-02-20 16:05:43 +05303472 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003473 hdd_err("Command not allowed in FTM mode");
3474 return -EPERM;
3475 }
3476
3477 if ((data == NULL) || (data_len == 0) ||
3478 (data_len > SIR_ROAM_SCAN_PSK_SIZE)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003479 hdd_err("Invalid data");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003480 return -EINVAL;
3481 }
3482
3483 hdd_ctx_ptr = WLAN_HDD_GET_CTX(hdd_adapter_ptr);
3484 if (!hdd_ctx_ptr) {
Jeff Johnson020db452016-06-29 14:37:26 -07003485 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003486 return -EINVAL;
3487 }
3488
3489 status = wlan_hdd_validate_context(hdd_ctx_ptr);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303490 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003491 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003492 sme_update_roam_key_mgmt_offload_enabled(hdd_ctx_ptr->hHal,
3493 hdd_adapter_ptr->sessionId,
Deepak Dhamdheref2a7d8b2016-08-19 16:17:38 -07003494 true,
3495 hdd_is_okc_mode_enabled(hdd_ctx_ptr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05303496 qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE);
3497 qdf_mem_copy(local_pmk, data, data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003498 sme_roam_set_psk_pmk(WLAN_HDD_GET_HAL_CTX(hdd_adapter_ptr),
3499 hdd_adapter_ptr->sessionId, local_pmk, data_len);
3500 return 0;
3501}
3502
3503/**
3504 * wlan_hdd_cfg80211_keymgmt_set_key() - Store the Keys in the driver session
3505 * @wiphy: pointer to wireless wiphy structure.
3506 * @wdev: pointer to wireless_dev structure.
3507 * @data: Pointer to the Key data
3508 * @data_len:Length of the data passed
3509 *
3510 * This is called when wlan driver needs to save the keys received via
3511 * vendor specific command.
3512 *
3513 * Return: Return the Success or Failure code.
3514 */
3515static int wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy,
3516 struct wireless_dev *wdev,
3517 const void *data, int data_len)
3518{
3519 int ret;
3520
3521 cds_ssr_protect(__func__);
3522 ret = __wlan_hdd_cfg80211_keymgmt_set_key(wiphy, wdev, data, data_len);
3523 cds_ssr_unprotect(__func__);
3524
3525 return ret;
3526}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003527#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003528
3529static const struct nla_policy qca_wlan_vendor_get_wifi_info_policy[
3530 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1] = {
3531 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION] = {.type = NLA_U8 },
3532 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION] = {.type = NLA_U8 },
Ryan Hsu7ac88852016-04-28 10:20:34 -07003533 [QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX] = {.type = NLA_U32 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003534};
3535
3536/**
3537 * __wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3538 * @wiphy: pointer to wireless wiphy structure.
3539 * @wdev: pointer to wireless_dev structure.
3540 * @data: Pointer to the data to be passed via vendor interface
3541 * @data_len:Length of the data to be passed
3542 *
3543 * This is called when wlan driver needs to send wifi driver related info
3544 * (driver/fw version) to the user space application upon request.
3545 *
3546 * Return: Return the Success or Failure code.
3547 */
3548static int
3549__wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3550 struct wireless_dev *wdev,
3551 const void *data, int data_len)
3552{
3553 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3554 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
Ryan Hsu7ac88852016-04-28 10:20:34 -07003555 tSirVersionString driver_version;
3556 tSirVersionString firmware_version;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003557 uint32_t major_spid = 0, minor_spid = 0, siid = 0, crmid = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003558 int status;
Ryan Hsu7ac88852016-04-28 10:20:34 -07003559 struct sk_buff *reply_skb;
3560 uint32_t skb_len = 0, count = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003561
Jeff Johnson1f61b612016-02-12 16:28:33 -08003562 ENTER_DEV(wdev->netdev);
3563
Anurag Chouhan6d760662016-02-20 16:05:43 +05303564 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003565 hdd_err("Command not allowed in FTM mode");
3566 return -EPERM;
3567 }
3568
3569 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303570 if (status)
3571 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003572
3573 if (nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, data,
3574 data_len, qca_wlan_vendor_get_wifi_info_policy)) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003575 hdd_err("WIFI_INFO_GET NL CMD parsing failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003576 return -EINVAL;
3577 }
3578
3579 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003580 hdd_err("Rcvd req for Driver version");
3581 strlcpy(driver_version, QWLAN_VERSIONSTR,
3582 sizeof(driver_version));
3583 skb_len += strlen(driver_version) + 1;
3584 count++;
3585 }
3586
3587 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
3588 hdd_info("Rcvd req for FW version");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003589 hdd_get_fw_version(hdd_ctx, &major_spid, &minor_spid, &siid,
3590 &crmid);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003591 snprintf(firmware_version, sizeof(firmware_version),
3592 "%d:%d:%d:%d", major_spid, minor_spid, siid, crmid);
3593 skb_len += strlen(firmware_version) + 1;
3594 count++;
3595 }
3596
3597 if (count == 0) {
3598 hdd_err("unknown attribute in get_wifi_info request");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003599 return -EINVAL;
3600 }
3601
Ryan Hsu7ac88852016-04-28 10:20:34 -07003602 skb_len += (NLA_HDRLEN * count) + NLMSG_HDRLEN;
3603 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
3604
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003605 if (!reply_skb) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003606 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003607 return -ENOMEM;
3608 }
3609
Ryan Hsu7ac88852016-04-28 10:20:34 -07003610 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
3611 if (nla_put_string(reply_skb,
3612 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION,
3613 driver_version))
3614 goto error_nla_fail;
3615 }
3616
Hanumanth Reddy Pothula1046ccc2016-10-14 14:33:44 +05303617 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
Ryan Hsu7ac88852016-04-28 10:20:34 -07003618 if (nla_put_string(reply_skb,
3619 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION,
3620 firmware_version))
3621 goto error_nla_fail;
3622 }
3623
3624 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX]) {
3625 if (nla_put_u32(reply_skb,
3626 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX,
3627 hdd_ctx->radio_index))
3628 goto error_nla_fail;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003629 }
3630
3631 return cfg80211_vendor_cmd_reply(reply_skb);
Ryan Hsu7ac88852016-04-28 10:20:34 -07003632
3633error_nla_fail:
3634 hdd_err("nla put fail");
3635 kfree_skb(reply_skb);
3636 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003637}
3638
3639/**
3640 * wlan_hdd_cfg80211_get_wifi_info() - Get the wifi driver related info
3641 * @wiphy: pointer to wireless wiphy structure.
3642 * @wdev: pointer to wireless_dev structure.
3643 * @data: Pointer to the data to be passed via vendor interface
3644 * @data_len:Length of the data to be passed
3645 *
3646 * This is called when wlan driver needs to send wifi driver related info
3647 * (driver/fw version) to the user space application upon request.
3648 *
3649 * Return: Return the Success or Failure code.
3650 */
3651static int
3652wlan_hdd_cfg80211_get_wifi_info(struct wiphy *wiphy,
3653 struct wireless_dev *wdev,
3654 const void *data, int data_len)
3655{
3656 int ret;
3657
3658 cds_ssr_protect(__func__);
3659 ret = __wlan_hdd_cfg80211_get_wifi_info(wiphy, wdev, data, data_len);
3660 cds_ssr_unprotect(__func__);
3661
3662 return ret;
3663}
3664
3665/**
3666 * __wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3667 * @wiphy: pointer to wireless wiphy structure.
3668 * @wdev: pointer to wireless_dev structure.
3669 * @data: Pointer to the data to be passed via vendor interface
3670 * @data_len:Length of the data to be passed
3671 *
3672 * This is called by userspace to know the supported logger features
3673 *
3674 * Return: Return the Success or Failure code.
3675 */
3676static int
3677__wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3678 struct wireless_dev *wdev,
3679 const void *data, int data_len)
3680{
3681 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3682 int status;
3683 uint32_t features;
3684 struct sk_buff *reply_skb = NULL;
3685
Jeff Johnson1f61b612016-02-12 16:28:33 -08003686 ENTER_DEV(wdev->netdev);
3687
Anurag Chouhan6d760662016-02-20 16:05:43 +05303688 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003689 hdd_err("Command not allowed in FTM mode");
3690 return -EPERM;
3691 }
3692
3693 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303694 if (status)
3695 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003696
3697 features = 0;
3698
3699 if (hdd_is_memdump_supported())
3700 features |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
3701 features |= WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED;
3702 features |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
3703 features |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
3704
3705 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
3706 sizeof(uint32_t) + NLA_HDRLEN + NLMSG_HDRLEN);
3707 if (!reply_skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003708 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003709 return -ENOMEM;
3710 }
3711
Jeff Johnson020db452016-06-29 14:37:26 -07003712 hdd_notice("Supported logger features: 0x%0x", features);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003713 if (nla_put_u32(reply_skb, QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED,
3714 features)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003715 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003716 kfree_skb(reply_skb);
3717 return -EINVAL;
3718 }
3719
3720 return cfg80211_vendor_cmd_reply(reply_skb);
3721}
3722
3723/**
3724 * wlan_hdd_cfg80211_get_logger_supp_feature() - Get the wifi logger features
3725 * @wiphy: pointer to wireless wiphy structure.
3726 * @wdev: pointer to wireless_dev structure.
3727 * @data: Pointer to the data to be passed via vendor interface
3728 * @data_len:Length of the data to be passed
3729 *
3730 * This is called by userspace to know the supported logger features
3731 *
3732 * Return: Return the Success or Failure code.
3733 */
3734static int
3735wlan_hdd_cfg80211_get_logger_supp_feature(struct wiphy *wiphy,
3736 struct wireless_dev *wdev,
3737 const void *data, int data_len)
3738{
3739 int ret;
3740
3741 cds_ssr_protect(__func__);
3742 ret = __wlan_hdd_cfg80211_get_logger_supp_feature(wiphy, wdev,
3743 data, data_len);
3744 cds_ssr_unprotect(__func__);
3745
3746 return ret;
3747}
3748
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003749#ifdef WLAN_FEATURE_ROAM_OFFLOAD
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003750/**
3751 * wlan_hdd_send_roam_auth_event() - Send the roamed and authorized event
3752 * @hdd_ctx_ptr: pointer to HDD Context.
3753 * @bssid: pointer to bssid of roamed AP.
3754 * @req_rsn_ie: Pointer to request RSN IE
3755 * @req_rsn_len: Length of the request RSN IE
3756 * @rsp_rsn_ie: Pointer to response RSN IE
3757 * @rsp_rsn_len: Length of the response RSN IE
3758 * @roam_info_ptr: Pointer to the roaming related information
3759 *
3760 * This is called when wlan driver needs to send the roaming and
3761 * authorization information after roaming.
3762 *
3763 * The information that would be sent is the request RSN IE, response
3764 * RSN IE and BSSID of the newly roamed AP.
3765 *
3766 * If the Authorized status is authenticated, then additional parameters
3767 * like PTK's KCK and KEK and Replay Counter would also be passed to the
3768 * supplicant.
3769 *
3770 * The supplicant upon receiving this event would ignore the legacy
3771 * cfg80211_roamed call and use the entire information from this event.
3772 * The cfg80211_roamed should still co-exist since the kernel will
3773 * make use of the parameters even if the supplicant ignores it.
3774 *
3775 * Return: Return the Success or Failure code.
3776 */
3777int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid,
3778 uint8_t *req_rsn_ie, uint32_t req_rsn_len, uint8_t *rsp_rsn_ie,
3779 uint32_t rsp_rsn_len, tCsrRoamInfo *roam_info_ptr)
3780{
3781 struct sk_buff *skb = NULL;
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003782 eCsrAuthType auth_type;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003783 ENTER();
3784
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303785 if (wlan_hdd_validate_context(hdd_ctx_ptr))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003786 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003787
Varun Reddy Yeturud351a6c2016-03-16 14:01:00 -07003788 if (!roaming_offload_enabled(hdd_ctx_ptr) ||
Prashanth Bhattabfc25292015-11-05 11:16:21 -08003789 !roam_info_ptr->roamSynchInProgress)
3790 return 0;
3791
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003792 skb = cfg80211_vendor_event_alloc(hdd_ctx_ptr->wiphy,
3793 NULL,
3794 ETH_ALEN + req_rsn_len + rsp_rsn_len +
3795 sizeof(uint8_t) + SIR_REPLAY_CTR_LEN +
3796 SIR_KCK_KEY_LEN + SIR_KCK_KEY_LEN +
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003797 sizeof(uint8_t) + (8 * NLMSG_HDRLEN),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003798 QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
3799 GFP_KERNEL);
3800
3801 if (!skb) {
Jeff Johnson020db452016-06-29 14:37:26 -07003802 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003803 return -EINVAL;
3804 }
3805
3806 if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
3807 ETH_ALEN, bssid) ||
3808 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
3809 req_rsn_len, req_rsn_ie) ||
3810 nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
3811 rsp_rsn_len, rsp_rsn_ie)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003812 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003813 goto nla_put_failure;
3814 }
Jeff Johnson020db452016-06-29 14:37:26 -07003815 hdd_debug("Auth Status = %d", roam_info_ptr->synchAuthStatus);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003816 if (roam_info_ptr->synchAuthStatus ==
3817 CSR_ROAM_AUTH_STATUS_AUTHENTICATED) {
Jeff Johnson020db452016-06-29 14:37:26 -07003818 hdd_debug("Include Auth Params TLV's");
Naveen Rawat14298b92015-11-25 16:27:41 -08003819 if (nla_put_u8(skb,
3820 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) {
3821 hdd_err("nla put fail");
3822 goto nla_put_failure;
3823 }
Varun Reddy Yeturu16e8f012016-02-03 17:21:09 -08003824 auth_type = roam_info_ptr->u.pConnectedProfile->AuthType;
3825 /* if FT or CCKM connection: dont send replay counter */
3826 if (auth_type != eCSR_AUTH_TYPE_FT_RSN &&
3827 auth_type != eCSR_AUTH_TYPE_FT_RSN_PSK &&
3828 auth_type != eCSR_AUTH_TYPE_CCKM_WPA &&
3829 auth_type != eCSR_AUTH_TYPE_CCKM_RSN &&
3830 nla_put(skb,
3831 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
3832 SIR_REPLAY_CTR_LEN,
3833 roam_info_ptr->replay_ctr)) {
3834 hdd_err("non FT/non CCKM connection.");
Naveen Rawat14298b92015-11-25 16:27:41 -08003835 hdd_err("failed to send replay counter.");
3836 goto nla_put_failure;
3837 }
3838 if (nla_put(skb,
3839 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
3840 SIR_KCK_KEY_LEN, roam_info_ptr->kck) ||
3841 nla_put(skb,
3842 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
3843 SIR_KEK_KEY_LEN, roam_info_ptr->kek)) {
3844 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003845 goto nla_put_failure;
3846 }
3847 } else {
Jeff Johnson020db452016-06-29 14:37:26 -07003848 hdd_debug("No Auth Params TLV's");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003849 if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
3850 false)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003851 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003852 goto nla_put_failure;
3853 }
3854 }
3855
Jeff Johnson020db452016-06-29 14:37:26 -07003856 hdd_debug("Subnet Change Status = %d",
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003857 roam_info_ptr->subnet_change_status);
3858
3859 /*
3860 * Add subnet change status if subnet has changed
3861 * 0 = unchanged
3862 * 1 = changed
3863 * 2 = unknown
3864 */
3865 if (roam_info_ptr->subnet_change_status) {
3866 if (nla_put_u8(skb,
3867 QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
3868 roam_info_ptr->subnet_change_status)) {
Jeff Johnson020db452016-06-29 14:37:26 -07003869 hdd_err("nla put fail");
Ravi Joshi277ae9b2015-11-13 11:30:43 -08003870 goto nla_put_failure;
3871 }
3872 }
3873
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003874 cfg80211_vendor_event(skb, GFP_KERNEL);
3875 return 0;
3876
3877nla_put_failure:
3878 kfree_skb(skb);
3879 return -EINVAL;
3880}
Varun Reddy Yeturubbbbe232016-02-29 14:01:57 -08003881#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003882
3883static const struct nla_policy
3884wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
3885
3886 [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 },
3887 [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 },
3888 [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 },
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303889 [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 },
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303890 [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] = {.type = NLA_U8 },
3891 [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION] = {.type = NLA_U8 },
Zhang Qiana3bcbe02016-08-12 16:20:36 +08003892 [QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY] = {.type = NLA_U8 },
3893 [QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY] = {.type = NLA_U8 },
3894 [QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY] = {.type = NLA_U8 },
3895 [QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY] = {.type = NLA_U8 },
3896 [QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY] = {.type = NLA_U8 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003897};
3898
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003899/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303900 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
3901 *
3902 * @adapter: Pointer to HDD adapter
3903 * @ie_data: Pointer to Scan IEs buffer
3904 * @ie_len: Length of Scan IEs
3905 *
3906 * Return: 0 on success; error number otherwise
3907 */
3908static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
3909 uint8_t *ie_data, uint8_t ie_len)
3910{
3911 hdd_scaninfo_t *scan_info = NULL;
3912 scan_info = &adapter->scan_info;
3913
3914 if (scan_info->default_scan_ies) {
3915 qdf_mem_free(scan_info->default_scan_ies);
3916 scan_info->default_scan_ies = NULL;
3917 }
3918
3919 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
3920 if (!scan_info->default_scan_ies)
3921 return -ENOMEM;
3922
3923 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
3924 scan_info->default_scan_ies_len = ie_len;
3925 return 0;
3926}
3927
3928/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003929 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3930 * vendor command
3931 *
3932 * @wiphy: wiphy device pointer
3933 * @wdev: wireless device pointer
3934 * @data: Vendor command data buffer
3935 * @data_len: Buffer length
3936 *
3937 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3938 *
3939 * Return: Error code.
3940 */
3941static int
3942__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3943 struct wireless_dev *wdev,
3944 const void *data,
3945 int data_len)
3946{
3947 struct net_device *dev = wdev->netdev;
3948 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3949 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3950 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
3951 int ret_val = 0;
3952 u32 modulated_dtim;
3953 u16 stats_avg_factor;
3954 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303955 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07003956 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07003957 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303958 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05303959 int attr_len;
3960 int access_policy = 0;
3961 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
3962 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05303963 uint16_t scan_ie_len = 0;
3964 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303965 struct sir_set_tx_rx_aggregation_size request;
3966 QDF_STATUS qdf_status;
Zhang Qiana3bcbe02016-08-12 16:20:36 +08003967 uint8_t retry, delay;
3968 int param_id;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05303969
Jeff Johnson1f61b612016-02-12 16:28:33 -08003970 ENTER_DEV(dev);
3971
Anurag Chouhan6d760662016-02-20 16:05:43 +05303972 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003973 hdd_err("Command not allowed in FTM mode");
3974 return -EPERM;
3975 }
3976
3977 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303978 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003979 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003980
3981 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
3982 data, data_len,
3983 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07003984 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003985 return -EINVAL;
3986 }
3987
Krunal Sonie3531942016-04-12 17:43:53 -07003988 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
3989 ftm_capab = nla_get_u32(tb[
3990 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
3991 hdd_ctx->config->fine_time_meas_cap =
3992 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
3993 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05303994 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07003995 hdd_ctx->config->fine_time_meas_cap);
3996 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
3997 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
3998 hdd_ctx->config->fine_time_meas_cap);
3999 }
4000
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004001 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
4002 modulated_dtim = nla_get_u32(
4003 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
4004
4005 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
4006 adapter->sessionId,
4007 modulated_dtim);
4008
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304009 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004010 ret_val = -EPERM;
4011 }
4012
Kapil Gupta6213c012016-09-02 19:39:09 +05304013 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4014 qpower = nla_get_u8(
4015 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4016 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4017 ret_val = -EINVAL;
4018 }
4019
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004020 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4021 stats_avg_factor = nla_get_u16(
4022 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4023 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4024 adapter->sessionId,
4025 stats_avg_factor);
4026
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304027 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004028 ret_val = -EPERM;
4029 }
4030
4031
4032 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4033 guard_time = nla_get_u32(
4034 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4035 status = sme_configure_guard_time(hdd_ctx->hHal,
4036 adapter->sessionId,
4037 guard_time);
4038
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304039 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004040 ret_val = -EPERM;
4041 }
4042
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304043 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4044 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4045 attr_len = nla_len(
4046 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4047 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4048 hdd_info("Invalid value. attr_len %d",
4049 attr_len);
4050 return -EINVAL;
4051 }
4052
4053 nla_memcpy(&vendor_ie,
4054 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4055 attr_len);
4056 vendor_ie_present = true;
4057 hdd_info("Access policy vendor ie present.attr_len %d",
4058 attr_len);
4059 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4060 &vendor_ie[0], attr_len);
4061 }
4062
4063 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4064 access_policy = (int) nla_get_u32(
4065 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4066 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4067 (access_policy >
4068 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4069 hdd_info("Invalid value. access_policy %d",
4070 access_policy);
4071 return -EINVAL;
4072 }
4073 access_policy_present = true;
4074 hdd_info("Access policy present. access_policy %d",
4075 access_policy);
4076 }
4077
Zhang Qiana3bcbe02016-08-12 16:20:36 +08004078 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]) {
4079 retry = nla_get_u8(tb[
4080 QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY]);
4081 retry = retry > CFG_NON_AGG_RETRY_MAX ?
4082 CFG_NON_AGG_RETRY_MAX : retry;
4083 param_id = WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH;
4084 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4085 retry, PDEV_CMD);
4086 }
4087
4088 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]) {
4089 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY]);
4090 retry = retry > CFG_AGG_RETRY_MAX ?
4091 CFG_AGG_RETRY_MAX : retry;
4092
4093 /* Value less than CFG_AGG_RETRY_MIN has side effect to t-put */
4094 retry = ((retry > 0) && (retry < CFG_AGG_RETRY_MIN)) ?
4095 CFG_AGG_RETRY_MIN : retry;
4096 param_id = WMI_PDEV_PARAM_AGG_SW_RETRY_TH;
4097 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4098 retry, PDEV_CMD);
4099 }
4100
4101 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]) {
4102 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY]);
4103 retry = retry > CFG_MGMT_RETRY_MAX ?
4104 CFG_MGMT_RETRY_MAX : retry;
4105 param_id = WMI_PDEV_PARAM_MGMT_RETRY_LIMIT;
4106 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4107 retry, PDEV_CMD);
4108 }
4109
4110 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]) {
4111 retry = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY]);
4112 retry = retry > CFG_CTRL_RETRY_MAX ?
4113 CFG_CTRL_RETRY_MAX : retry;
4114 param_id = WMI_PDEV_PARAM_CTRL_RETRY_LIMIT;
4115 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4116 retry, PDEV_CMD);
4117 }
4118
4119 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]) {
4120 delay = nla_get_u8(tb[
4121 QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY]);
4122 delay = delay > CFG_PROPAGATION_DELAY_MAX ?
4123 CFG_PROPAGATION_DELAY_MAX : delay;
4124 param_id = WMI_PDEV_PARAM_PROPAGATION_DELAY;
4125 ret_val = wma_cli_set_command(adapter->sessionId, param_id,
4126 delay, PDEV_CMD);
4127 }
4128
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304129 if (vendor_ie_present && access_policy_present) {
4130 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4131 access_policy =
4132 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304133 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304134 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304135 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304136
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304137 hdd_info("calling sme_update_access_policy_vendor_ie");
4138 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4139 adapter->sessionId, &vendor_ie[0],
4140 access_policy);
4141 if (QDF_STATUS_SUCCESS != status) {
4142 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304143 return -EINVAL;
4144 }
4145 }
4146
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304147 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4148 set_value = nla_get_u8(
4149 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4150 hdd_info("set_value: %d", set_value);
4151 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4152 }
4153
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304154 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4155 scan_ie_len = nla_len(
4156 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4157 hdd_info("Received default scan IE of len %d session %d device mode %d",
4158 scan_ie_len, adapter->sessionId,
4159 adapter->device_mode);
4160 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4161 scan_ie = (uint8_t *) nla_data(tb
4162 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304163
4164 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4165 scan_ie_len))
4166 hdd_err("Failed to save default scan IEs");
4167
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304168 if (adapter->device_mode == QDF_STA_MODE) {
4169 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4170 adapter->sessionId, scan_ie,
4171 scan_ie_len);
4172 if (QDF_STATUS_SUCCESS != status)
4173 ret_val = -EPERM;
4174 }
4175 } else
4176 ret_val = -EPERM;
4177 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304178
4179 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4180 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4181 /* if one is specified, both must be specified */
4182 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4183 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4184 hdd_err("Both TX and RX MPDU Aggregation required");
4185 return -EINVAL;
4186 }
4187
4188 request.tx_aggregation_size = nla_get_u8(
4189 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4190 request.rx_aggregation_size = nla_get_u8(
4191 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4192 request.vdev_id = adapter->sessionId;
4193
4194 if (request.tx_aggregation_size >=
4195 CFG_TX_AGGREGATION_SIZE_MIN &&
4196 request.tx_aggregation_size <=
4197 CFG_TX_AGGREGATION_SIZE_MAX &&
4198 request.rx_aggregation_size >=
4199 CFG_RX_AGGREGATION_SIZE_MIN &&
4200 request.rx_aggregation_size <=
4201 CFG_RX_AGGREGATION_SIZE_MAX) {
4202 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4203 if (qdf_status != QDF_STATUS_SUCCESS) {
4204 hdd_err("failed to set aggr sizes err %d",
4205 qdf_status);
4206 ret_val = -EPERM;
4207 }
4208 } else {
4209 hdd_err("TX %d RX %d MPDU aggr size not in range",
4210 request.tx_aggregation_size,
4211 request.rx_aggregation_size);
4212 ret_val = -EINVAL;
4213 }
4214 }
4215
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304216 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4217 uint8_t ignore_assoc_disallowed;
4218
4219 ignore_assoc_disallowed
4220 = nla_get_u8(tb[
4221 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4222 hdd_info("Set ignore_assoc_disallowed value - %d",
4223 ignore_assoc_disallowed);
4224 if ((ignore_assoc_disallowed <
4225 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4226 (ignore_assoc_disallowed >
4227 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4228 return -EPERM;
4229
4230 sme_update_session_param(hdd_ctx->hHal,
4231 adapter->sessionId,
4232 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4233 ignore_assoc_disallowed);
4234 }
4235
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004236 return ret_val;
4237}
4238
4239/**
4240 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4241 * vendor command
4242 *
4243 * @wiphy: wiphy device pointer
4244 * @wdev: wireless device pointer
4245 * @data: Vendor command data buffer
4246 * @data_len: Buffer length
4247 *
4248 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4249 *
4250 * Return: EOK or other error codes.
4251 */
4252static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4253 struct wireless_dev *wdev,
4254 const void *data,
4255 int data_len)
4256{
4257 int ret;
4258
4259 cds_ssr_protect(__func__);
4260 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4261 data, data_len);
4262 cds_ssr_unprotect(__func__);
4263
4264 return ret;
4265}
4266
4267static const struct
4268nla_policy
4269qca_wlan_vendor_wifi_logger_start_policy
4270[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4271 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4272 = {.type = NLA_U32 },
4273 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4274 = {.type = NLA_U32 },
4275 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4276 = {.type = NLA_U32 },
4277};
4278
4279/**
4280 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4281 * or disable the collection of packet statistics from the firmware
4282 * @wiphy: WIPHY structure pointer
4283 * @wdev: Wireless device structure pointer
4284 * @data: Pointer to the data received
4285 * @data_len: Length of the data received
4286 *
4287 * This function enables or disables the collection of packet statistics from
4288 * the firmware
4289 *
4290 * Return: 0 on success and errno on failure
4291 */
4292static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4293 struct wireless_dev *wdev,
4294 const void *data,
4295 int data_len)
4296{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304297 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004298 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4299 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4300 struct sir_wifi_start_log start_log;
4301
Jeff Johnson1f61b612016-02-12 16:28:33 -08004302 ENTER_DEV(wdev->netdev);
4303
Anurag Chouhan6d760662016-02-20 16:05:43 +05304304 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004305 hdd_err("Command not allowed in FTM mode");
4306 return -EPERM;
4307 }
4308
4309 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304310 if (status)
4311 return status;
4312
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004313
4314 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4315 data, data_len,
4316 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004317 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004318 return -EINVAL;
4319 }
4320
4321 /* Parse and fetch ring id */
4322 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004323 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004324 return -EINVAL;
4325 }
4326 start_log.ring_id = nla_get_u32(
4327 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004328 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004329
4330 /* Parse and fetch verbose level */
4331 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004332 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004333 return -EINVAL;
4334 }
4335 start_log.verbose_level = nla_get_u32(
4336 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004337 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004338
4339 /* Parse and fetch flag */
4340 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004341 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004342 return -EINVAL;
4343 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304344 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004345 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304346 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004347
4348 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4349
4350 if (start_log.ring_id == RING_ID_WAKELOCK) {
4351 /* Start/stop wakelock events */
4352 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4353 cds_set_wakelock_logging(true);
4354 else
4355 cds_set_wakelock_logging(false);
4356 return 0;
4357 }
4358
4359 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304360 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004361 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004362 status);
4363 return -EINVAL;
4364 }
4365 return 0;
4366}
4367
4368/**
4369 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4370 * or disable the collection of packet statistics from the firmware
4371 * @wiphy: WIPHY structure pointer
4372 * @wdev: Wireless device structure pointer
4373 * @data: Pointer to the data received
4374 * @data_len: Length of the data received
4375 *
4376 * This function is used to enable or disable the collection of packet
4377 * statistics from the firmware
4378 *
4379 * Return: 0 on success and errno on failure
4380 */
4381static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4382 struct wireless_dev *wdev,
4383 const void *data,
4384 int data_len)
4385{
4386 int ret = 0;
4387
4388 cds_ssr_protect(__func__);
4389 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4390 wdev, data, data_len);
4391 cds_ssr_unprotect(__func__);
4392
4393 return ret;
4394}
4395
4396static const struct
4397nla_policy
4398qca_wlan_vendor_wifi_logger_get_ring_data_policy
4399[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4400 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4401 = {.type = NLA_U32 },
4402};
4403
4404/**
4405 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4406 * @wiphy: WIPHY structure pointer
4407 * @wdev: Wireless device structure pointer
4408 * @data: Pointer to the data received
4409 * @data_len: Length of the data received
4410 *
4411 * This function is used to flush or retrieve the per packet statistics from
4412 * the driver
4413 *
4414 * Return: 0 on success and errno on failure
4415 */
4416static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4417 struct wireless_dev *wdev,
4418 const void *data,
4419 int data_len)
4420{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304421 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004422 uint32_t ring_id;
4423 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4424 struct nlattr *tb
4425 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4426
Jeff Johnson1f61b612016-02-12 16:28:33 -08004427 ENTER_DEV(wdev->netdev);
4428
Anurag Chouhan6d760662016-02-20 16:05:43 +05304429 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004430 hdd_err("Command not allowed in FTM mode");
4431 return -EPERM;
4432 }
4433
4434 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304435 if (status)
4436 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004437
4438 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
4439 data, data_len,
4440 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004441 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004442 return -EINVAL;
4443 }
4444
4445 /* Parse and fetch ring id */
4446 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004447 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004448 return -EINVAL;
4449 }
4450
4451 ring_id = nla_get_u32(
4452 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
4453
4454 if (ring_id == RING_ID_PER_PACKET_STATS) {
4455 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07004456 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05304457 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
4458 /*
4459 * As part of DRIVER ring ID, flush both driver and fw logs.
4460 * For other Ring ID's driver doesn't have any rings to flush
4461 */
4462 hdd_notice("Bug report triggered by framework");
4463
4464 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
4465 WLAN_LOG_INDICATOR_FRAMEWORK,
4466 WLAN_LOG_REASON_CODE_UNUSED,
4467 true, false);
4468 if (QDF_STATUS_SUCCESS != status) {
4469 hdd_err("Failed to trigger bug report");
4470 return -EINVAL;
4471 }
4472 } else {
4473 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
4474 WLAN_LOG_INDICATOR_FRAMEWORK,
4475 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004476 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004477 return 0;
4478}
4479
4480/**
4481 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
4482 * @wiphy: WIPHY structure pointer
4483 * @wdev: Wireless device structure pointer
4484 * @data: Pointer to the data received
4485 * @data_len: Length of the data received
4486 *
4487 * This function is used to flush or retrieve the per packet statistics from
4488 * the driver
4489 *
4490 * Return: 0 on success and errno on failure
4491 */
4492static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4493 struct wireless_dev *wdev,
4494 const void *data,
4495 int data_len)
4496{
4497 int ret = 0;
4498
4499 cds_ssr_protect(__func__);
4500 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
4501 wdev, data, data_len);
4502 cds_ssr_unprotect(__func__);
4503
4504 return ret;
4505}
4506
4507#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4508/**
4509 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
4510 * @hdd_ctx: HDD context
4511 * @request_id: [input] request id
4512 * @pattern_id: [output] pattern id
4513 *
4514 * This function loops through request id to pattern id array
4515 * if the slot is available, store the request id and return pattern id
4516 * if entry exists, return the pattern id
4517 *
4518 * Return: 0 on success and errno on failure
4519 */
4520static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4521 uint32_t request_id,
4522 uint8_t *pattern_id)
4523{
4524 uint32_t i;
4525
4526 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4527 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4528 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
4529 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
4530 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4531 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4532 return 0;
4533 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
4534 request_id) {
4535 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4536 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4537 return 0;
4538 }
4539 }
4540 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4541 return -EINVAL;
4542}
4543
4544/**
4545 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
4546 * @hdd_ctx: HDD context
4547 * @request_id: [input] request id
4548 * @pattern_id: [output] pattern id
4549 *
4550 * This function loops through request id to pattern id array
4551 * reset request id to 0 (slot available again) and
4552 * return pattern id
4553 *
4554 * Return: 0 on success and errno on failure
4555 */
4556static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4557 uint32_t request_id,
4558 uint8_t *pattern_id)
4559{
4560 uint32_t i;
4561
4562 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4563 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4564 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
4565 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4566 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4567 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4568 return 0;
4569 }
4570 }
4571 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4572 return -EINVAL;
4573}
4574
4575
4576/*
4577 * define short names for the global vendor params
4578 * used by __wlan_hdd_cfg80211_offloaded_packets()
4579 */
4580#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
4581#define PARAM_REQUEST_ID \
4582 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
4583#define PARAM_CONTROL \
4584 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
4585#define PARAM_IP_PACKET \
4586 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
4587#define PARAM_SRC_MAC_ADDR \
4588 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
4589#define PARAM_DST_MAC_ADDR \
4590 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
4591#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
4592
4593/**
4594 * wlan_hdd_add_tx_ptrn() - add tx pattern
4595 * @adapter: adapter pointer
4596 * @hdd_ctx: hdd context
4597 * @tb: nl attributes
4598 *
4599 * This function reads the NL attributes and forms a AddTxPtrn message
4600 * posts it to SME.
4601 *
4602 */
4603static int
4604wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4605 struct nlattr **tb)
4606{
4607 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304608 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004609 uint32_t request_id, ret, len;
4610 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304611 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004612 uint16_t eth_type = htons(ETH_P_IP);
4613
4614 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004615 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004616 return -ENOTSUPP;
4617 }
4618
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304619 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004620 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004621 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004622 return -ENOMEM;
4623 }
4624
4625 /* Parse and fetch request Id */
4626 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004627 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004628 goto fail;
4629 }
4630
4631 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4632 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004633 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004634 return -EINVAL;
4635 }
Jeff Johnson77848112016-06-29 14:52:06 -07004636 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004637
4638 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004639 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004640 goto fail;
4641 }
4642 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07004643 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004644 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07004645 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004646 goto fail;
4647 }
4648
4649 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004650 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004651 goto fail;
4652 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08004653 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05304654 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004655 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004656 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004657
Anurag Chouhanc5548422016-02-24 18:33:27 +05304658 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004659 &adapter->macAddressCurrent)) {
4660 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004661 goto fail;
4662 }
4663
4664 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004665 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004666 goto fail;
4667 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05304668 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004669 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004670 MAC_ADDR_ARRAY(dst_addr.bytes));
4671
4672 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004673 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004674 goto fail;
4675 }
4676 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07004677 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004678
4679 if (add_req->ucPtrnSize < 0 ||
4680 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
4681 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004682 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004683 add_req->ucPtrnSize);
4684 goto fail;
4685 }
4686
4687 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304688 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05304689 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304690 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304691 QDF_MAC_ADDR_SIZE);
4692 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304693 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004694 len += 2;
4695
4696 /*
4697 * This is the IP packet, add 14 bytes Ethernet (802.3) header
4698 * ------------------------------------------------------------
4699 * | 14 bytes Ethernet (802.3) header | IP header and payload |
4700 * ------------------------------------------------------------
4701 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304702 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004703 nla_data(tb[PARAM_IP_PACKET]),
4704 add_req->ucPtrnSize);
4705 add_req->ucPtrnSize += len;
4706
4707 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4708 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004709 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004710 goto fail;
4711 }
4712 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004713 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004714
4715 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304716 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004717 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004718 goto fail;
4719 }
4720
4721 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304722 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004723 return 0;
4724
4725fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304726 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004727 return -EINVAL;
4728}
4729
4730/**
4731 * wlan_hdd_del_tx_ptrn() - delete tx pattern
4732 * @adapter: adapter pointer
4733 * @hdd_ctx: hdd context
4734 * @tb: nl attributes
4735 *
4736 * This function reads the NL attributes and forms a DelTxPtrn message
4737 * posts it to SME.
4738 *
4739 */
4740static int
4741wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4742 struct nlattr **tb)
4743{
4744 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304745 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004746 uint32_t request_id, ret;
4747 uint8_t pattern_id = 0;
4748
4749 /* Parse and fetch request Id */
4750 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004751 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004752 return -EINVAL;
4753 }
4754 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4755 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004756 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004757 return -EINVAL;
4758 }
4759
4760 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4761 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004762 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004763 return -EINVAL;
4764 }
4765
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304766 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004767 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004768 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004769 return -ENOMEM;
4770 }
4771
Anurag Chouhanc5548422016-02-24 18:33:27 +05304772 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004773 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004774 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004775 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004776 request_id, del_req->ucPtrnId);
4777
4778 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304779 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004780 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004781 goto fail;
4782 }
4783
4784 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304785 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004786 return 0;
4787
4788fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304789 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004790 return -EINVAL;
4791}
4792
4793
4794/**
4795 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
4796 * @wiphy: Pointer to wireless phy
4797 * @wdev: Pointer to wireless device
4798 * @data: Pointer to data
4799 * @data_len: Data length
4800 *
4801 * Return: 0 on success, negative errno on failure
4802 */
4803static int
4804__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4805 struct wireless_dev *wdev,
4806 const void *data,
4807 int data_len)
4808{
4809 struct net_device *dev = wdev->netdev;
4810 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4811 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4812 struct nlattr *tb[PARAM_MAX + 1];
4813 uint8_t control;
4814 int ret;
4815 static const struct nla_policy policy[PARAM_MAX + 1] = {
4816 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4817 [PARAM_CONTROL] = { .type = NLA_U32 },
4818 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304819 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004820 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304821 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004822 [PARAM_PERIOD] = { .type = NLA_U32 },
4823 };
4824
Jeff Johnson1f61b612016-02-12 16:28:33 -08004825 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004826
Anurag Chouhan6d760662016-02-20 16:05:43 +05304827 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004828 hdd_err("Command not allowed in FTM mode");
4829 return -EPERM;
4830 }
4831
4832 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304833 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004834 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004835
4836 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004837 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004838 return -ENOTSUPP;
4839 }
4840
4841 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004842 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004843 return -EINVAL;
4844 }
4845
4846 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004847 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004848 return -EINVAL;
4849 }
4850 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07004851 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004852
4853 if (control == WLAN_START_OFFLOADED_PACKETS)
4854 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
4855 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
4856 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
4857 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004858 hdd_err("Invalid control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004859 return -EINVAL;
4860 }
4861}
4862
4863/*
4864 * done with short names for the global vendor params
4865 * used by __wlan_hdd_cfg80211_offloaded_packets()
4866 */
4867#undef PARAM_MAX
4868#undef PARAM_REQUEST_ID
4869#undef PARAM_CONTROL
4870#undef PARAM_IP_PACKET
4871#undef PARAM_SRC_MAC_ADDR
4872#undef PARAM_DST_MAC_ADDR
4873#undef PARAM_PERIOD
4874
4875/**
4876 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
4877 * @wiphy: wiphy structure pointer
4878 * @wdev: Wireless device structure pointer
4879 * @data: Pointer to the data received
4880 * @data_len: Length of @data
4881 *
4882 * Return: 0 on success; errno on failure
4883 */
4884static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4885 struct wireless_dev *wdev,
4886 const void *data,
4887 int data_len)
4888{
4889 int ret = 0;
4890
4891 cds_ssr_protect(__func__);
4892 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
4893 wdev, data, data_len);
4894 cds_ssr_unprotect(__func__);
4895
4896 return ret;
4897}
4898#endif
4899
4900/*
4901 * define short names for the global vendor params
4902 * used by __wlan_hdd_cfg80211_monitor_rssi()
4903 */
4904#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
4905#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
4906#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
4907#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
4908#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
4909
4910/**
4911 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
4912 * @wiphy: Pointer to wireless phy
4913 * @wdev: Pointer to wireless device
4914 * @data: Pointer to data
4915 * @data_len: Data length
4916 *
4917 * Return: 0 on success, negative errno on failure
4918 */
4919static int
4920__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
4921 struct wireless_dev *wdev,
4922 const void *data,
4923 int data_len)
4924{
4925 struct net_device *dev = wdev->netdev;
4926 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4927 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4928 struct nlattr *tb[PARAM_MAX + 1];
4929 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304930 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004931 int ret;
4932 uint32_t control;
4933 static const struct nla_policy policy[PARAM_MAX + 1] = {
4934 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4935 [PARAM_CONTROL] = { .type = NLA_U32 },
4936 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
4937 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
4938 };
4939
Jeff Johnson1f61b612016-02-12 16:28:33 -08004940 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004941
4942 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304943 if (ret)
4944 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004945
4946 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004947 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004948 return -ENOTSUPP;
4949 }
4950
4951 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004952 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004953 return -EINVAL;
4954 }
4955
4956 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004957 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004958 return -EINVAL;
4959 }
4960
4961 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004962 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004963 return -EINVAL;
4964 }
4965
4966 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4967 req.session_id = adapter->sessionId;
4968 control = nla_get_u32(tb[PARAM_CONTROL]);
4969
4970 if (control == QCA_WLAN_RSSI_MONITORING_START) {
4971 req.control = true;
4972 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004973 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004974 return -EINVAL;
4975 }
4976
4977 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004978 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004979 return -EINVAL;
4980 }
4981
4982 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
4983 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
4984
4985 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004986 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004987 req.min_rssi, req.max_rssi);
4988 return -EINVAL;
4989 }
Jeff Johnson77848112016-06-29 14:52:06 -07004990 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004991 req.min_rssi, req.max_rssi);
4992
4993 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
4994 req.control = false;
4995 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004996 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004997 return -EINVAL;
4998 }
Jeff Johnson77848112016-06-29 14:52:06 -07004999 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005000 req.request_id, req.session_id, req.control);
5001
5002 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305003 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005004 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005005 return -EINVAL;
5006 }
5007
5008 return 0;
5009}
5010
5011/*
5012 * done with short names for the global vendor params
5013 * used by __wlan_hdd_cfg80211_monitor_rssi()
5014 */
5015#undef PARAM_MAX
5016#undef PARAM_CONTROL
5017#undef PARAM_REQUEST_ID
5018#undef PARAM_MAX_RSSI
5019#undef PARAM_MIN_RSSI
5020
5021/**
5022 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
5023 * @wiphy: wiphy structure pointer
5024 * @wdev: Wireless device structure pointer
5025 * @data: Pointer to the data received
5026 * @data_len: Length of @data
5027 *
5028 * Return: 0 on success; errno on failure
5029 */
5030static int
5031wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
5032 const void *data, int data_len)
5033{
5034 int ret;
5035
5036 cds_ssr_protect(__func__);
5037 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
5038 cds_ssr_unprotect(__func__);
5039
5040 return ret;
5041}
5042
5043/**
5044 * hdd_rssi_threshold_breached() - rssi breached NL event
5045 * @hddctx: HDD context
5046 * @data: rssi breached event data
5047 *
5048 * This function reads the rssi breached event %data and fill in the skb with
5049 * NL attributes and send up the NL event.
5050 *
5051 * Return: none
5052 */
5053void hdd_rssi_threshold_breached(void *hddctx,
5054 struct rssi_breach_event *data)
5055{
5056 hdd_context_t *hdd_ctx = hddctx;
5057 struct sk_buff *skb;
5058
5059 ENTER();
5060
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305061 if (wlan_hdd_validate_context(hdd_ctx))
5062 return;
5063 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005064 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005065 return;
5066 }
5067
5068 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5069 NULL,
5070 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5071 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5072 GFP_KERNEL);
5073
5074 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005075 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005076 return;
5077 }
5078
Jeff Johnson77848112016-06-29 14:52:06 -07005079 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005080 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005081 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005082 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5083
5084 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5085 data->request_id) ||
5086 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5087 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5088 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5089 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005090 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005091 goto fail;
5092 }
5093
5094 cfg80211_vendor_event(skb, GFP_KERNEL);
5095 return;
5096
5097fail:
5098 kfree_skb(skb);
5099 return;
5100}
5101
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305102static const struct nla_policy
5103ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5104 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5105};
5106
5107/**
5108 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5109 * @wiphy: Pointer to wireless phy
5110 * @wdev: Pointer to wireless device
5111 * @data: Pointer to data
5112 * @data_len: Length of @data
5113 *
5114 * Return: 0 on success, negative errno on failure
5115 */
5116static int
5117__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5118 struct wireless_dev *wdev,
5119 const void *data, int data_len)
5120{
5121 int status;
5122 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5123 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005124 struct net_device *dev = wdev->netdev;
5125 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305126
5127 ENTER_DEV(wdev->netdev);
5128
5129 status = wlan_hdd_validate_context(pHddCtx);
5130 if (0 != status)
5131 return status;
5132 if (!pHddCtx->config->fhostNSOffload) {
5133 hdd_err("ND Offload not supported");
5134 return -EINVAL;
5135 }
5136
5137 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5138 (struct nlattr *)data,
5139 data_len, ns_offload_set_policy)) {
5140 hdd_err("nla_parse failed");
5141 return -EINVAL;
5142 }
5143
5144 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5145 hdd_err("ND Offload flag attribute not present");
5146 return -EINVAL;
5147 }
5148
5149 pHddCtx->ns_offload_enable =
5150 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5151
Dustin Brownd8279d22016-09-07 14:52:57 -07005152 /* update ns offload in case it is already enabled/disabled */
5153 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
5154
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305155 return 0;
5156}
5157
5158/**
5159 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5160 * @wiphy: pointer to wireless wiphy structure.
5161 * @wdev: pointer to wireless_dev structure.
5162 * @data: Pointer to the data to be passed via vendor interface
5163 * @data_len:Length of the data to be passed
5164 *
5165 * Return: Return the Success or Failure code.
5166 */
5167static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5168 struct wireless_dev *wdev,
5169 const void *data, int data_len)
5170{
5171 int ret;
5172
5173 cds_ssr_protect(__func__);
5174 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5175 cds_ssr_unprotect(__func__);
5176
5177 return ret;
5178}
5179
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005180/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5181 * @wiphy: Pointer to wireless phy
5182 * @wdev: Pointer to wireless device
5183 * @data: Pointer to data
5184 * @data_len: Data length
5185 *
5186 * This function return the preferred frequency list generated by the policy
5187 * manager.
5188 *
5189 * Return: success or failure code
5190 */
5191static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5192 struct wireless_dev
5193 *wdev, const void *data,
5194 int data_len)
5195{
5196 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5197 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305198 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305199 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005200 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305201 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005202 enum cds_con_mode intf_mode;
5203 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5204 struct sk_buff *reply_skb;
5205
Jeff Johnson1f61b612016-02-12 16:28:33 -08005206 ENTER_DEV(wdev->netdev);
5207
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005208 ret = wlan_hdd_validate_context(hdd_ctx);
5209 if (ret)
5210 return -EINVAL;
5211
5212 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5213 data, data_len, NULL)) {
5214 hdd_err("Invalid ATTR");
5215 return -EINVAL;
5216 }
5217
5218 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5219 hdd_err("attr interface type failed");
5220 return -EINVAL;
5221 }
5222
5223 intf_mode = nla_get_u32(tb
5224 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5225
5226 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5227 hdd_err("Invalid interface type");
5228 return -EINVAL;
5229 }
5230
5231 hdd_debug("Userspace requested pref freq list");
5232
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305233 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5234 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305235 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005236 hdd_err("Get pcl failed");
5237 return -EINVAL;
5238 }
5239
5240 /* convert channel number to frequency */
5241 for (i = 0; i < pcl_len; i++) {
5242 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5243 freq_list[i] =
5244 ieee80211_channel_to_frequency(pcl[i],
5245 IEEE80211_BAND_2GHZ);
5246 else
5247 freq_list[i] =
5248 ieee80211_channel_to_frequency(pcl[i],
5249 IEEE80211_BAND_5GHZ);
5250 }
5251
5252 /* send the freq_list back to supplicant */
5253 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5254 sizeof(u32) *
5255 pcl_len +
5256 NLMSG_HDRLEN);
5257
5258 if (!reply_skb) {
5259 hdd_err("Allocate reply_skb failed");
5260 return -EINVAL;
5261 }
5262
5263 if (nla_put_u32(reply_skb,
5264 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5265 intf_mode) ||
5266 nla_put(reply_skb,
5267 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5268 sizeof(uint32_t) * pcl_len,
5269 freq_list)) {
5270 hdd_err("nla put fail");
5271 kfree_skb(reply_skb);
5272 return -EINVAL;
5273 }
5274
5275 return cfg80211_vendor_cmd_reply(reply_skb);
5276}
5277
5278/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5279 * @wiphy: Pointer to wireless phy
5280 * @wdev: Pointer to wireless device
5281 * @data: Pointer to data
5282 * @data_len: Data length
5283 *
5284 * This function return the preferred frequency list generated by the policy
5285 * manager.
5286 *
5287 * Return: success or failure code
5288 */
5289static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5290 struct wireless_dev
5291 *wdev, const void *data,
5292 int data_len)
5293{
5294 int ret = 0;
5295
5296 cds_ssr_protect(__func__);
5297 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5298 data, data_len);
5299 cds_ssr_unprotect(__func__);
5300
5301 return ret;
5302}
5303
5304/**
5305 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5306 * @wiphy: Pointer to wireless phy
5307 * @wdev: Pointer to wireless device
5308 * @data: Pointer to data
5309 * @data_len: Data length
5310 *
5311 * Return: 0 on success, negative errno on failure
5312 */
5313static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5314 struct wireless_dev *wdev,
5315 const void *data,
5316 int data_len)
5317{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305318 struct net_device *ndev = wdev->netdev;
5319 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005320 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5321 int ret = 0;
5322 enum cds_con_mode intf_mode;
5323 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5324 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005325
Jeff Johnson1f61b612016-02-12 16:28:33 -08005326 ENTER_DEV(ndev);
5327
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005328 ret = wlan_hdd_validate_context(hdd_ctx);
5329 if (ret)
5330 return ret;
5331
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005332 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5333 data, data_len, NULL)) {
5334 hdd_err("Invalid ATTR");
5335 return -EINVAL;
5336 }
5337
5338 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5339 hdd_err("attr interface type failed");
5340 return -EINVAL;
5341 }
5342
5343 intf_mode = nla_get_u32(tb
5344 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5345
5346 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5347 hdd_err("Invalid interface type");
5348 return -EINVAL;
5349 }
5350
5351 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5352 hdd_err("attr probable freq failed");
5353 return -EINVAL;
5354 }
5355
5356 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5357 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5358
5359 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005360 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005361 channel_hint, HW_MODE_20_MHZ)) {
5362 hdd_err("Set channel hint failed due to concurrency check");
5363 return -EINVAL;
5364 }
5365
Krunal Soni09e55032016-06-07 10:06:55 -07005366 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5367 hdd_warn("Remain On Channel Pending");
5368
Krunal Soni3091bcc2016-06-23 12:28:21 -07005369 ret = qdf_reset_connection_update();
5370 if (!QDF_IS_STATUS_SUCCESS(ret))
5371 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005372
Krunal Soni3091bcc2016-06-23 12:28:21 -07005373 ret = cds_current_connections_update(adapter->sessionId,
5374 channel_hint,
5375 SIR_UPDATE_REASON_SET_OPER_CHAN);
5376 if (QDF_STATUS_E_FAILURE == ret) {
5377 /* return in the failure case */
5378 hdd_err("ERROR: connections update failed!!");
5379 return -EINVAL;
5380 }
5381
5382 if (QDF_STATUS_SUCCESS == ret) {
5383 /*
5384 * Success is the only case for which we expect hw mode
5385 * change to take place, hence we need to wait.
5386 * For any other return value it should be a pass
5387 * through
5388 */
5389 ret = qdf_wait_for_connection_update();
5390 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5391 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005392 return -EINVAL;
5393 }
5394
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005395 }
5396
5397 return 0;
5398}
5399
5400/**
5401 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5402 * @wiphy: Pointer to wireless phy
5403 * @wdev: Pointer to wireless device
5404 * @data: Pointer to data
5405 * @data_len: Data length
5406 *
5407 * Return: 0 on success, negative errno on failure
5408 */
5409static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5410 struct wireless_dev *wdev,
5411 const void *data,
5412 int data_len)
5413{
5414 int ret = 0;
5415
5416 cds_ssr_protect(__func__);
5417 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5418 data, data_len);
5419 cds_ssr_unprotect(__func__);
5420
5421 return ret;
5422}
5423
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305424static const struct
5425nla_policy
5426qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5427 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5428};
5429
5430/**
5431 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
5432 * @wiphy: WIPHY structure pointer
5433 * @wdev: Wireless device structure pointer
5434 * @data: Pointer to the data received
5435 * @data_len: Length of the data received
5436 *
5437 * This function is used to get link properties like nss, rate flags and
5438 * operating frequency for the active connection with the given peer.
5439 *
5440 * Return: 0 on success and errno on failure
5441 */
5442static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5443 struct wireless_dev *wdev,
5444 const void *data,
5445 int data_len)
5446{
5447 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5448 struct net_device *dev = wdev->netdev;
5449 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5450 hdd_station_ctx_t *hdd_sta_ctx;
5451 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05305452 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305453 uint32_t sta_id;
5454 struct sk_buff *reply_skb;
5455 uint32_t rate_flags = 0;
5456 uint8_t nss;
5457 uint8_t final_rate_flags = 0;
5458 uint32_t freq;
5459
Jeff Johnson1f61b612016-02-12 16:28:33 -08005460 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305461
Anurag Chouhan6d760662016-02-20 16:05:43 +05305462 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305463 hdd_err("Command not allowed in FTM mode");
5464 return -EPERM;
5465 }
5466
5467 if (0 != wlan_hdd_validate_context(hdd_ctx))
5468 return -EINVAL;
5469
5470 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
5471 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005472 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305473 return -EINVAL;
5474 }
5475
5476 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005477 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305478 adapter->device_mode);
5479 return -EINVAL;
5480 }
5481
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305482 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05305483 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005484 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305485 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
5486
Krunal Sonib4326f22016-03-10 13:05:51 -08005487 if (adapter->device_mode == QDF_STA_MODE ||
5488 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305489 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
5490 if ((hdd_sta_ctx->conn_info.connState !=
5491 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305492 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305493 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005494 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305495 MAC_ADDR_ARRAY(peer_mac));
5496 return -EINVAL;
5497 }
5498
5499 nss = hdd_sta_ctx->conn_info.nss;
5500 freq = cds_chan_to_freq(
5501 hdd_sta_ctx->conn_info.operationChannel);
5502 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08005503 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
5504 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305505
5506 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
5507 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05305508 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305509 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305510 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305511 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305512 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305513 break;
5514 }
5515
5516 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07005517 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305518 MAC_ADDR_ARRAY(peer_mac));
5519 return -EINVAL;
5520 }
5521
5522 nss = adapter->aStaInfo[sta_id].nss;
5523 freq = cds_chan_to_freq(
5524 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
5525 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
5526 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07005527 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305528 MAC_ADDR_ARRAY(peer_mac));
5529 return -EINVAL;
5530 }
5531
5532 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
5533 if (rate_flags & eHAL_TX_RATE_VHT80) {
5534 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005535#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305536 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005537#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305538 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
5539 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005540#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305541 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005542#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305543 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
5544 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
5545 } else if (rate_flags &
5546 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
5547 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005548#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305549 if (rate_flags & eHAL_TX_RATE_HT40)
5550 final_rate_flags |=
5551 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005552#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305553 }
5554
5555 if (rate_flags & eHAL_TX_RATE_SGI) {
5556 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
5557 final_rate_flags |= RATE_INFO_FLAGS_MCS;
5558 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
5559 }
5560 }
5561
5562 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5563 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
5564
5565 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005566 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305567 return -EINVAL;
5568 }
5569
5570 if (nla_put_u8(reply_skb,
5571 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
5572 nss) ||
5573 nla_put_u8(reply_skb,
5574 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
5575 final_rate_flags) ||
5576 nla_put_u32(reply_skb,
5577 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
5578 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005579 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305580 kfree_skb(reply_skb);
5581 return -EINVAL;
5582 }
5583
5584 return cfg80211_vendor_cmd_reply(reply_skb);
5585}
5586
5587/**
5588 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
5589 * properties.
5590 * @wiphy: WIPHY structure pointer
5591 * @wdev: Wireless device structure pointer
5592 * @data: Pointer to the data received
5593 * @data_len: Length of the data received
5594 *
5595 * This function is used to get link properties like nss, rate flags and
5596 * operating frequency for the active connection with the given peer.
5597 *
5598 * Return: 0 on success and errno on failure
5599 */
5600static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5601 struct wireless_dev *wdev,
5602 const void *data,
5603 int data_len)
5604{
5605 int ret = 0;
5606
5607 cds_ssr_protect(__func__);
5608 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
5609 wdev, data, data_len);
5610 cds_ssr_unprotect(__func__);
5611
5612 return ret;
5613}
5614
Peng Xu278d0122015-09-24 16:34:17 -07005615static const struct
5616nla_policy
5617qca_wlan_vendor_ota_test_policy
5618[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
5619 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
5620};
5621
5622/**
5623 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
5624 * @wiphy: Pointer to wireless phy
5625 * @wdev: Pointer to wireless device
5626 * @data: Pointer to data
5627 * @data_len: Data length
5628 *
5629 * Return: 0 on success, negative errno on failure
5630 */
5631static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5632 struct wireless_dev *wdev,
5633 const void *data,
5634 int data_len)
5635{
5636 struct net_device *dev = wdev->netdev;
5637 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5638 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
5639 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5640 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
5641 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305642 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07005643 uint32_t current_roam_state;
5644
Jeff Johnson1f61b612016-02-12 16:28:33 -08005645 ENTER_DEV(dev);
5646
Anurag Chouhan6d760662016-02-20 16:05:43 +05305647 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07005648 hdd_err("Command not allowed in FTM mode");
5649 return -EPERM;
5650 }
5651
5652 if (0 != wlan_hdd_validate_context(hdd_ctx))
5653 return -EINVAL;
5654
5655 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
5656 data, data_len,
5657 qca_wlan_vendor_ota_test_policy)) {
5658 hdd_err("invalid attr");
5659 return -EINVAL;
5660 }
5661
5662 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
5663 hdd_err("attr ota test failed");
5664 return -EINVAL;
5665 }
5666
5667 ota_enable = nla_get_u8(
5668 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
5669
5670 hdd_info(" OTA test enable = %d", ota_enable);
5671 if (ota_enable != 1) {
5672 hdd_err("Invalid value, only enable test mode is supported!");
5673 return -EINVAL;
5674 }
5675
5676 current_roam_state =
5677 sme_get_current_roam_state(hal, adapter->sessionId);
5678 status = sme_stop_roaming(hal, adapter->sessionId,
5679 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305680 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005681 hdd_err("Enable/Disable roaming failed");
5682 return -EINVAL;
5683 }
5684
5685 status = sme_ps_enable_disable(hal, adapter->sessionId,
5686 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305687 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005688 hdd_err("Enable/Disable power save failed");
5689 /* restore previous roaming setting */
5690 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
5691 current_roam_state == eCSR_ROAMING_STATE_JOINED)
5692 status = sme_start_roaming(hal, adapter->sessionId,
5693 eCsrHddIssued);
5694 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
5695 current_roam_state == eCSR_ROAMING_STATE_IDLE)
5696 status = sme_stop_roaming(hal, adapter->sessionId,
5697 eCsrHddIssued);
5698
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305699 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07005700 hdd_err("Restoring roaming state failed");
5701
5702 return -EINVAL;
5703 }
5704
5705
5706 return 0;
5707}
5708
5709/**
5710 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
5711 * @wiphy: Pointer to wireless phy
5712 * @wdev: Pointer to wireless device
5713 * @data: Pointer to data
5714 * @data_len: Data length
5715 *
5716 * Return: 0 on success, negative errno on failure
5717 */
5718static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5719 struct wireless_dev *wdev,
5720 const void *data,
5721 int data_len)
5722{
5723 int ret = 0;
5724
5725 cds_ssr_protect(__func__);
5726 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
5727 cds_ssr_unprotect(__func__);
5728
5729 return ret;
5730}
5731
Peng Xu4d67c8f2015-10-16 16:02:26 -07005732/**
5733 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5734 * @wiphy: Pointer to wireless phy
5735 * @wdev: Pointer to wireless device
5736 * @data: Pointer to data
5737 * @data_len: Data length
5738 *
5739 * Return: 0 on success, negative errno on failure
5740 */
5741static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5742 struct wireless_dev *wdev,
5743 const void *data,
5744 int data_len)
5745{
5746 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5747 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005748 hdd_adapter_t *adapter;
5749 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005750 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
5751 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005752 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005753
Jeff Johnson1f61b612016-02-12 16:28:33 -08005754 ENTER_DEV(dev);
5755
Peng Xu4d67c8f2015-10-16 16:02:26 -07005756 ret = wlan_hdd_validate_context(hdd_ctx);
5757 if (ret)
5758 return ret;
5759
5760 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5761
5762 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
5763 data, data_len, NULL)) {
5764 hdd_err("Invalid ATTR");
5765 return -EINVAL;
5766 }
5767
5768 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
5769 hdd_err("attr tx power scale failed");
5770 return -EINVAL;
5771 }
5772
5773 scale_value = nla_get_u8(tb
5774 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
5775
5776 if (scale_value > MAX_TXPOWER_SCALE) {
5777 hdd_err("Invalid tx power scale level");
5778 return -EINVAL;
5779 }
5780
Peng Xu62c8c432016-05-09 15:23:02 -07005781 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005782
Peng Xu62c8c432016-05-09 15:23:02 -07005783 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005784 hdd_err("Set tx power scale failed");
5785 return -EINVAL;
5786 }
5787
5788 return 0;
5789}
5790
5791/**
5792 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5793 * @wiphy: Pointer to wireless phy
5794 * @wdev: Pointer to wireless device
5795 * @data: Pointer to data
5796 * @data_len: Data length
5797 *
5798 * Return: 0 on success, negative errno on failure
5799 */
5800static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5801 struct wireless_dev *wdev,
5802 const void *data,
5803 int data_len)
5804{
Peng Xu62c8c432016-05-09 15:23:02 -07005805 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005806
5807 cds_ssr_protect(__func__);
5808 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
5809 data, data_len);
5810 cds_ssr_unprotect(__func__);
5811
5812 return ret;
5813}
5814
5815/**
5816 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5817 * @wiphy: Pointer to wireless phy
5818 * @wdev: Pointer to wireless device
5819 * @data: Pointer to data
5820 * @data_len: Data length
5821 *
5822 * Return: 0 on success, negative errno on failure
5823 */
5824static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5825 struct wireless_dev *wdev,
5826 const void *data,
5827 int data_len)
5828{
5829 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5830 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005831 hdd_adapter_t *adapter;
5832 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005833 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
5834 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005835 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005836
Jeff Johnson1f61b612016-02-12 16:28:33 -08005837 ENTER_DEV(dev);
5838
Peng Xu4d67c8f2015-10-16 16:02:26 -07005839 ret = wlan_hdd_validate_context(hdd_ctx);
5840 if (ret)
5841 return ret;
5842
5843 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5844
5845 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
5846 data, data_len, NULL)) {
5847 hdd_err("Invalid ATTR");
5848 return -EINVAL;
5849 }
5850
5851 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
5852 hdd_err("attr tx power decrease db value failed");
5853 return -EINVAL;
5854 }
5855
5856 scale_value = nla_get_u8(tb
5857 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
5858
Peng Xu62c8c432016-05-09 15:23:02 -07005859 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
5860 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005861
Peng Xu62c8c432016-05-09 15:23:02 -07005862 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005863 hdd_err("Set tx power decrease db failed");
5864 return -EINVAL;
5865 }
5866
5867 return 0;
5868}
5869
5870/**
5871 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5872 * @wiphy: Pointer to wireless phy
5873 * @wdev: Pointer to wireless device
5874 * @data: Pointer to data
5875 * @data_len: Data length
5876 *
5877 * Return: 0 on success, negative errno on failure
5878 */
5879static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5880 struct wireless_dev *wdev,
5881 const void *data,
5882 int data_len)
5883{
Peng Xu62c8c432016-05-09 15:23:02 -07005884 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005885
5886 cds_ssr_protect(__func__);
5887 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
5888 data, data_len);
5889 cds_ssr_unprotect(__func__);
5890
5891 return ret;
5892}
Peng Xu8fdaa492016-06-22 10:20:47 -07005893
5894/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05305895 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
5896 * @wiphy: Pointer to wireless phy
5897 * @wdev: Pointer to wireless device
5898 * @data: Pointer to data
5899 * @data_len: Data length
5900 *
5901 * Processes the conditional channel switch request and invokes the helper
5902 * APIs to process the channel switch request.
5903 *
5904 * Return: 0 on success, negative errno on failure
5905 */
5906static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
5907 struct wireless_dev *wdev,
5908 const void *data,
5909 int data_len)
5910{
5911 int ret;
5912 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5913 struct net_device *dev = wdev->netdev;
5914 hdd_adapter_t *adapter;
5915 struct nlattr
5916 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
5917 uint32_t freq_len, i;
5918 uint32_t *freq;
5919 uint8_t chans[QDF_MAX_NUM_CHAN];
5920
5921 ENTER_DEV(dev);
5922
5923 ret = wlan_hdd_validate_context(hdd_ctx);
5924 if (ret)
5925 return ret;
5926
5927 if (!hdd_ctx->config->enableDFSMasterCap) {
5928 hdd_err("DFS master capability is not present in the driver");
5929 return -EINVAL;
5930 }
5931
5932 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5933 hdd_err("Command not allowed in FTM mode");
5934 return -EPERM;
5935 }
5936
5937 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5938 if (adapter->device_mode != QDF_SAP_MODE) {
5939 hdd_err("Invalid device mode %d", adapter->device_mode);
5940 return -EINVAL;
5941 }
5942
5943 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
5944 data, data_len, NULL)) {
5945 hdd_err("Invalid ATTR");
5946 return -EINVAL;
5947 }
5948
5949 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
5950 hdd_err("Frequency list is missing");
5951 return -EINVAL;
5952 }
5953
5954 freq_len = nla_len(
5955 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
5956 sizeof(uint32_t);
5957
5958 if (freq_len > QDF_MAX_NUM_CHAN) {
5959 hdd_err("insufficient space to hold channels");
5960 return -ENOMEM;
5961 }
5962
5963 hdd_debug("freq_len=%d", freq_len);
5964
5965 freq = nla_data(
5966 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
5967
5968
5969 for (i = 0; i < freq_len; i++) {
5970 if (freq[i] == 0)
5971 chans[i] = 0;
5972 else
5973 chans[i] = ieee80211_frequency_to_channel(freq[i]);
5974
5975 hdd_debug("freq[%d]=%d", i, freq[i]);
5976 }
5977
5978 /*
5979 * The input frequency list from user space is designed to be a
5980 * priority based frequency list. This is only to accommodate any
5981 * future request. But, current requirement is only to perform CAC
5982 * on a single channel. So, the first entry from the list is picked.
5983 *
5984 * If channel is zero, any channel in the available outdoor regulatory
5985 * domain will be selected.
5986 */
5987 ret = wlan_hdd_request_pre_cac(chans[0]);
5988 if (ret) {
5989 hdd_err("pre cac request failed with reason:%d", ret);
5990 return ret;
5991 }
5992
5993 return 0;
5994}
5995
5996/**
Peng Xu8fdaa492016-06-22 10:20:47 -07005997 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
5998 * @wiphy: Pointer to wireless phy
5999 * @wdev: Pointer to wireless device
6000 * @data: Pointer to data
6001 * @data_len: Data length
6002 *
6003 * This function is to process the p2p listen offload start vendor
6004 * command. It parses the input parameters and invoke WMA API to
6005 * send the command to firmware.
6006 *
6007 * Return: 0 on success, negative errno on failure
6008 */
6009static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6010 struct wireless_dev *wdev,
6011 const void *data,
6012 int data_len)
6013{
6014 int ret;
6015 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6016 struct net_device *dev = wdev->netdev;
6017 hdd_adapter_t *adapter;
6018 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
6019 struct sir_p2p_lo_start params;
6020 QDF_STATUS status;
6021
6022 ENTER_DEV(dev);
6023
6024 ret = wlan_hdd_validate_context(hdd_ctx);
6025 if (ret)
6026 return ret;
6027
6028 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6029 hdd_err("Command not allowed in FTM mode");
6030 return -EPERM;
6031 }
6032
6033 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6034 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6035 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6036 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6037 hdd_err("Invalid device mode %d", adapter->device_mode);
6038 return -EINVAL;
6039 }
6040
6041 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
6042 data, data_len, NULL)) {
6043 hdd_err("Invalid ATTR");
6044 return -EINVAL;
6045 }
6046
6047 memset(&params, 0, sizeof(params));
6048
6049 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
6050 params.ctl_flags = 1; /* set to default value */
6051 else
6052 params.ctl_flags = nla_get_u32(tb
6053 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
6054
6055 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
6056 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
6057 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6058 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6059 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6060 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6061 hdd_err("Attribute parsing failed");
6062 return -EINVAL;
6063 }
6064
6065 params.vdev_id = adapter->sessionId;
6066 params.freq = nla_get_u32(tb
6067 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6068 if ((params.freq != 2412) && (params.freq != 2437) &&
6069 (params.freq != 2462)) {
6070 hdd_err("Invalid listening channel: %d", params.freq);
6071 return -EINVAL;
6072 }
6073
6074 params.period = nla_get_u32(tb
6075 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6076 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6077 hdd_err("Invalid period: %d", params.period);
6078 return -EINVAL;
6079 }
6080
6081 params.interval = nla_get_u32(tb
6082 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6083 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6084 hdd_err("Invalid interval: %d", params.interval);
6085 return -EINVAL;
6086 }
6087
6088 params.count = nla_get_u32(tb
6089 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
6090 if (!((params.count > 0) && (params.count < UINT_MAX))) {
6091 hdd_err("Invalid count: %d", params.count);
6092 return -EINVAL;
6093 }
6094
6095 params.device_types = nla_data(tb
6096 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6097 if (params.device_types == NULL) {
6098 hdd_err("Invalid device types");
6099 return -EINVAL;
6100 }
6101
6102 params.dev_types_len = nla_len(tb
6103 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6104 if (params.dev_types_len < 8) {
6105 hdd_err("Invalid device type length: %d", params.dev_types_len);
6106 return -EINVAL;
6107 }
6108
6109 params.probe_resp_tmplt = nla_data(tb
6110 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6111 if (params.probe_resp_tmplt == NULL) {
6112 hdd_err("Invalid probe response template");
6113 return -EINVAL;
6114 }
6115
6116 params.probe_resp_len = nla_len(tb
6117 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6118 if (params.probe_resp_len == 0) {
6119 hdd_err("Invalid probe resp template length: %d",
6120 params.probe_resp_len);
6121 return -EINVAL;
6122 }
6123
6124 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6125 params.freq, params.period, params.interval, params.count);
6126
6127 status = wma_p2p_lo_start(&params);
6128
6129 if (!QDF_IS_STATUS_SUCCESS(status)) {
6130 hdd_err("P2P LO start failed");
6131 return -EINVAL;
6132 }
6133
6134 return 0;
6135}
6136
6137
6138/**
6139 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6140 * @wiphy: Pointer to wireless phy
6141 * @wdev: Pointer to wireless device
6142 * @data: Pointer to data
6143 * @data_len: Data length
6144 *
6145 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6146 * to process p2p listen offload start vendor command.
6147 *
6148 * Return: 0 on success, negative errno on failure
6149 */
6150static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6151 struct wireless_dev *wdev,
6152 const void *data,
6153 int data_len)
6154{
6155 int ret = 0;
6156
6157 cds_ssr_protect(__func__);
6158 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6159 data, data_len);
6160 cds_ssr_unprotect(__func__);
6161
6162 return ret;
6163}
6164
6165/**
6166 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6167 * @wiphy: Pointer to wireless phy
6168 * @wdev: Pointer to wireless device
6169 * @data: Pointer to data
6170 * @data_len: Data length
6171 *
6172 * This function is to process the p2p listen offload stop vendor
6173 * command. It invokes WMA API to send command to firmware.
6174 *
6175 * Return: 0 on success, negative errno on failure
6176 */
6177static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6178 struct wireless_dev *wdev,
6179 const void *data,
6180 int data_len)
6181{
6182 QDF_STATUS status;
6183 hdd_adapter_t *adapter;
6184 struct net_device *dev = wdev->netdev;
6185
6186 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6187 hdd_err("Command not allowed in FTM mode");
6188 return -EPERM;
6189 }
6190
6191 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6192 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6193 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6194 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6195 hdd_err("Invalid device mode");
6196 return -EINVAL;
6197 }
6198
6199 status = wma_p2p_lo_stop(adapter->sessionId);
6200
6201 if (!QDF_IS_STATUS_SUCCESS(status)) {
6202 hdd_err("P2P LO stop failed");
6203 return -EINVAL;
6204 }
6205
6206 return 0;
6207}
6208
6209/**
6210 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6211 * @wiphy: Pointer to wireless phy
6212 * @wdev: Pointer to wireless device
6213 * @data: Pointer to data
6214 * @data_len: Data length
6215 *
6216 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6217 * to process p2p listen offload stop vendor command.
6218 *
6219 * Return: 0 on success, negative errno on failure
6220 */
6221static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6222 struct wireless_dev *wdev,
6223 const void *data,
6224 int data_len)
6225{
6226 int ret = 0;
6227
6228 cds_ssr_protect(__func__);
6229 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6230 data, data_len);
6231 cds_ssr_unprotect(__func__);
6232
6233 return ret;
6234}
6235
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306236/**
6237 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6238 * @wiphy: Pointer to wireless phy
6239 * @wdev: Pointer to wireless device
6240 * @data: Pointer to data
6241 * @data_len: Data length
6242 *
6243 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6244 * to process the conditional channel switch request.
6245 *
6246 * Return: 0 on success, negative errno on failure
6247 */
6248static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6249 struct wireless_dev *wdev,
6250 const void *data,
6251 int data_len)
6252{
6253 int ret;
6254
6255 cds_ssr_protect(__func__);
6256 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6257 data, data_len);
6258 cds_ssr_unprotect(__func__);
6259
6260 return ret;
6261}
6262
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306263/*
6264 * define short names for the global vendor params
6265 * used by __wlan_hdd_cfg80211_bpf_offload()
6266 */
6267#define BPF_INVALID \
6268 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6269#define BPF_SET_RESET \
6270 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6271#define BPF_VERSION \
6272 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6273#define BPF_FILTER_ID \
6274 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6275#define BPF_PACKET_SIZE \
6276 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6277#define BPF_CURRENT_OFFSET \
6278 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6279#define BPF_PROGRAM \
6280 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6281#define BPF_MAX \
6282 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006283
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306284static const struct nla_policy
6285wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6286 [BPF_SET_RESET] = {.type = NLA_U32},
6287 [BPF_VERSION] = {.type = NLA_U32},
6288 [BPF_FILTER_ID] = {.type = NLA_U32},
6289 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6290 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6291 [BPF_PROGRAM] = {.type = NLA_U8},
6292};
6293
6294/**
6295 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
6296 * @hdd_context: hdd_context
6297 * @bpf_get_offload: struct for get offload
6298 *
6299 * This function receives the response/data from the lower layer and
6300 * checks to see if the thread is still waiting then post the results to
6301 * upper layer, if the request has timed out then ignore.
6302 *
6303 * Return: None
6304 */
6305void hdd_get_bpf_offload_cb(void *hdd_context,
6306 struct sir_bpf_get_offload *data)
6307{
6308 hdd_context_t *hdd_ctx = hdd_context;
6309 struct hdd_bpf_context *context;
6310
6311 ENTER();
6312
6313 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006314 hdd_err("HDD context is invalid or data(%p) is null",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306315 data);
6316 return;
6317 }
6318
6319 spin_lock(&hdd_context_lock);
6320
6321 context = &bpf_context;
6322 /* The caller presumably timed out so there is nothing we can do */
6323 if (context->magic != BPF_CONTEXT_MAGIC) {
6324 spin_unlock(&hdd_context_lock);
6325 return;
6326 }
6327
6328 /* context is valid so caller is still waiting */
6329 /* paranoia: invalidate the magic */
6330 context->magic = 0;
6331
6332 context->capability_response = *data;
6333 complete(&context->completion);
6334
6335 spin_unlock(&hdd_context_lock);
6336
6337 return;
6338}
6339
6340/**
6341 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6342 * @hdd_context: hdd_context
6343 * @bpf_get_offload: struct for get offload
6344 *
6345 * Return: 0 on success, error number otherwise.
6346 */
6347static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6348 struct sir_bpf_get_offload *bpf_get_offload)
6349{
6350 struct sk_buff *skb;
6351 uint32_t nl_buf_len;
6352
6353 ENTER();
6354
6355 nl_buf_len = NLMSG_HDRLEN;
6356 nl_buf_len +=
6357 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6358 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6359
6360 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6361 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006362 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306363 return -ENOMEM;
6364 }
6365
Jeff Johnson77848112016-06-29 14:52:06 -07006366 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306367 bpf_get_offload->bpf_version,
6368 bpf_get_offload->max_bytes_for_bpf_inst);
6369
6370 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6371 bpf_get_offload->max_bytes_for_bpf_inst) ||
6372 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006373 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306374 goto nla_put_failure;
6375 }
6376
6377 cfg80211_vendor_cmd_reply(skb);
6378 EXIT();
6379 return 0;
6380
6381nla_put_failure:
6382 kfree_skb(skb);
6383 return -EINVAL;
6384}
6385
6386/**
6387 * hdd_get_bpf_offload - Get BPF offload Capabilities
6388 * @hdd_ctx: Hdd context
6389 *
6390 * Return: 0 on success, errno on failure
6391 */
6392static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6393{
6394 unsigned long rc;
6395 struct hdd_bpf_context *context;
6396 QDF_STATUS status;
6397 int ret;
6398
6399 ENTER();
6400
6401 spin_lock(&hdd_context_lock);
6402 context = &bpf_context;
6403 context->magic = BPF_CONTEXT_MAGIC;
6404 INIT_COMPLETION(context->completion);
6405 spin_unlock(&hdd_context_lock);
6406
6407 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal);
6408 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006409 hdd_err("Unable to retrieve BPF caps");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306410 return -EINVAL;
6411 }
6412 /* request was sent -- wait for the response */
6413 rc = wait_for_completion_timeout(&context->completion,
6414 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
6415 if (!rc) {
Jeff Johnson77848112016-06-29 14:52:06 -07006416 hdd_err("Target response timed out");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306417 spin_lock(&hdd_context_lock);
6418 context->magic = 0;
6419 spin_unlock(&hdd_context_lock);
6420
6421 return -ETIMEDOUT;
6422 }
6423 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
6424 &bpf_context.capability_response);
6425 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006426 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306427
6428 EXIT();
6429 return ret;
6430}
6431
6432/**
6433 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
6434 * @hdd_ctx: Hdd context
6435 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306436 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306437 *
6438 * Return: 0 on success; errno on failure
6439 */
6440static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
6441 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306442 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306443{
6444 struct sir_bpf_set_offload *bpf_set_offload;
6445 QDF_STATUS status;
6446 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05306447 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306448
6449 ENTER();
6450
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306451 if (adapter->device_mode == QDF_STA_MODE ||
6452 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
6453 if (!hdd_conn_is_connected(
6454 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
6455 hdd_err("Not in Connected state!");
6456 return -ENOTSUPP;
6457 }
6458 }
6459
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306460 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
6461 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07006462 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306463 return -ENOMEM;
6464 }
6465 qdf_mem_zero(bpf_set_offload, sizeof(*bpf_set_offload));
6466
6467 /* Parse and fetch bpf packet size */
6468 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006469 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306470 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306471 goto fail;
6472 }
6473 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
6474
6475 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07006476 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306477 goto post_sme;
6478 }
6479
6480 /* Parse and fetch bpf program */
6481 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006482 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306483 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306484 goto fail;
6485 }
6486
6487 prog_len = nla_len(tb[BPF_PROGRAM]);
6488 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05306489
6490 if (bpf_set_offload->program == NULL) {
6491 hdd_err("qdf_mem_malloc failed for bpf offload program");
6492 ret = -ENOMEM;
6493 goto fail;
6494 }
6495
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306496 bpf_set_offload->current_length = prog_len;
6497 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306498 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306499
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05306500 hdd_info("BPF set instructions");
6501 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
6502 bpf_set_offload->program, prog_len);
6503
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306504 /* Parse and fetch filter Id */
6505 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006506 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306507 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306508 goto fail;
6509 }
6510 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
6511
6512 /* Parse and fetch current offset */
6513 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006514 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306515 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306516 goto fail;
6517 }
6518 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
6519
6520post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07006521 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 +05306522 bpf_set_offload->session_id,
6523 bpf_set_offload->version,
6524 bpf_set_offload->filter_id,
6525 bpf_set_offload->total_length,
6526 bpf_set_offload->current_length,
6527 bpf_set_offload->current_offset);
6528
6529 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
6530 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006531 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05306532 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306533 goto fail;
6534 }
6535 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306536
6537fail:
6538 if (bpf_set_offload->current_length)
6539 qdf_mem_free(bpf_set_offload->program);
6540 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05306541 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306542}
6543
6544/**
6545 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
6546 * @wiphy: wiphy structure pointer
6547 * @wdev: Wireless device structure pointer
6548 * @data: Pointer to the data received
6549 * @data_len: Length of @data
6550 *
6551 * Return: 0 on success; errno on failure
6552 */
6553static int
6554__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6555 struct wireless_dev *wdev,
6556 const void *data, int data_len)
6557{
6558 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6559 struct net_device *dev = wdev->netdev;
6560 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6561 struct nlattr *tb[BPF_MAX + 1];
6562 int ret_val, packet_filter_subcmd;
6563
6564 ENTER();
6565
6566 ret_val = wlan_hdd_validate_context(hdd_ctx);
6567 if (ret_val)
6568 return ret_val;
6569
6570 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07006571 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306572 return -EINVAL;
6573 }
6574
6575 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07006576 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306577 return -ENOTSUPP;
6578 }
6579
6580 if (nla_parse(tb, BPF_MAX, data, data_len,
6581 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006582 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306583 return -EINVAL;
6584 }
6585
6586 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006587 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306588 return -EINVAL;
6589 }
6590
6591 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
6592
6593 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
6594 return hdd_get_bpf_offload(hdd_ctx);
6595 else
6596 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306597 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306598}
6599
6600/**
6601 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
6602 * @wiphy: wiphy structure pointer
6603 * @wdev: Wireless device structure pointer
6604 * @data: Pointer to the data received
6605 * @data_len: Length of @data
6606 *
6607 * Return: 0 on success; errno on failure
6608 */
6609
6610static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6611 struct wireless_dev *wdev,
6612 const void *data, int data_len)
6613{
6614 int ret;
6615
6616 cds_ssr_protect(__func__);
6617 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
6618 cds_ssr_unprotect(__func__);
6619
6620 return ret;
6621}
6622
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306623/**
6624 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
6625 * @pre_cac_adapter: AP adapter used for pre cac
6626 * @status: Status (true or false)
6627 * @handle: Global handle
6628 *
6629 * Sets the status of pre cac i.e., whether the pre cac is active or not
6630 *
6631 * Return: Zero on success, non-zero on failure
6632 */
6633static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
6634 bool status, tHalHandle handle)
6635{
6636 QDF_STATUS ret;
6637
6638 ret = wlan_sap_set_pre_cac_status(
6639 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
6640 if (QDF_IS_STATUS_ERROR(ret))
6641 return -EINVAL;
6642
6643 return 0;
6644}
6645
6646/**
6647 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
6648 * @ap_adapter: AP adapter
6649 * @chan_before_pre_cac: Channel
6650 *
6651 * Saves the channel which the AP was beaconing on before moving to the pre
6652 * cac channel. If radar is detected on the pre cac channel, this saved
6653 * channel will be used for AP operations.
6654 *
6655 * Return: Zero on success, non-zero on failure
6656 */
6657static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
6658 uint8_t chan_before_pre_cac)
6659{
6660 QDF_STATUS ret;
6661
6662 ret = wlan_sap_set_chan_before_pre_cac(
6663 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
6664 if (QDF_IS_STATUS_ERROR(ret))
6665 return -EINVAL;
6666
6667 return 0;
6668}
6669
6670/**
6671 * wlan_hdd_sap_get_nol() - Get SAPs NOL
6672 * @ap_adapter: AP adapter
6673 * @nol: Non-occupancy list
6674 * @nol_len: Length of NOL
6675 *
6676 * Get the NOL for SAP
6677 *
6678 * Return: Zero on success, non-zero on failure
6679 */
6680static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
6681 uint32_t *nol_len)
6682{
6683 QDF_STATUS ret;
6684
6685 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
6686 nol, nol_len);
6687 if (QDF_IS_STATUS_ERROR(ret))
6688 return -EINVAL;
6689
6690 return 0;
6691}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306692
6693/**
6694 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
6695 * @hdd_ctx: HDD context
6696 * @ap_adapter: AP adapter
6697 * @channel: Channel requested by userspace
6698 * @pre_cac_chan: Pointer to the pre CAC channel
6699 *
6700 * Validates the channel provided by userspace. If user provided channel 0,
6701 * a valid outdoor channel must be selected from the regulatory channel.
6702 *
6703 * Return: Zero on success and non zero value on error
6704 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07006705static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
6706 hdd_adapter_t *ap_adapter,
6707 uint8_t channel,
6708 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306709{
6710 uint32_t i, j;
6711 QDF_STATUS status;
6712 int ret;
6713 uint8_t nol[QDF_MAX_NUM_CHAN];
6714 uint32_t nol_len = 0, weight_len = 0;
6715 bool found;
6716 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6717 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
6718 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
6719
6720 if (0 == channel) {
6721 /* Channel is not obtained from PCL because PCL may not have
6722 * the entire channel list. For example: if SAP is up on
6723 * channel 6 and PCL is queried for the next SAP interface,
6724 * if SCC is preferred, the PCL will contain only the channel
6725 * 6. But, we are in need of a DFS channel. So, going with the
6726 * first channel from the valid channel list.
6727 */
6728 status = cds_get_valid_chans(channel_list, &len);
6729 if (QDF_IS_STATUS_ERROR(status)) {
6730 hdd_err("Failed to get channel list");
6731 return -EINVAL;
6732 }
6733 cds_update_with_safe_channel_list(channel_list, &len,
6734 pcl_weights, weight_len);
6735 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
6736 for (i = 0; i < len; i++) {
6737 found = false;
6738 for (j = 0; j < nol_len; j++) {
6739 if (channel_list[i] == nol[j]) {
6740 found = true;
6741 break;
6742 }
6743 }
6744 if (found)
6745 continue;
6746 if (CDS_IS_DFS_CH(channel_list[i])) {
6747 *pre_cac_chan = channel_list[i];
6748 break;
6749 }
6750 }
6751 if (*pre_cac_chan == 0) {
6752 hdd_err("unable to find outdoor channel");
6753 return -EINVAL;
6754 }
6755 } else {
6756 /* Only when driver selects a channel, check is done for
6757 * unnsafe and NOL channels. When user provides a fixed channel
6758 * the user is expected to take care of this.
6759 */
6760 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
6761 !CDS_IS_DFS_CH(channel)) {
6762 hdd_err("Invalid channel for pre cac:%d", channel);
6763 return -EINVAL;
6764 } else {
6765 *pre_cac_chan = channel;
6766 }
6767 }
6768 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
6769 return 0;
6770}
6771
6772/**
6773 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
6774 * @channel: Channel option provided by userspace
6775 *
6776 * Sets the driver to the required hardware mode and start an adapater for
6777 * pre CAC which will mimic an AP.
6778 *
6779 * Return: Zero on success, non-zero value on error
6780 */
6781int wlan_hdd_request_pre_cac(uint8_t channel)
6782{
6783 uint8_t pre_cac_chan = 0;
6784 hdd_context_t *hdd_ctx;
6785 int ret;
6786 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
6787 hdd_ap_ctx_t *hdd_ap_ctx;
6788 QDF_STATUS status;
6789 struct wiphy *wiphy;
6790 struct net_device *dev;
6791 struct cfg80211_chan_def chandef;
6792 enum nl80211_channel_type channel_type;
6793 uint32_t freq;
6794 struct ieee80211_channel *chan;
6795 tHalHandle handle;
6796 bool val;
6797
6798 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
6799 if (0 != wlan_hdd_validate_context(hdd_ctx))
6800 return -EINVAL;
6801
6802 if (cds_get_connection_count() > 1) {
6803 hdd_err("pre cac not allowed in concurrency");
6804 return -EINVAL;
6805 }
6806
6807 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
6808 if (!ap_adapter) {
6809 hdd_err("unable to get SAP adapter");
6810 return -EINVAL;
6811 }
6812
6813 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
6814 if (!handle) {
6815 hdd_err("Invalid handle");
6816 return -EINVAL;
6817 }
6818
6819 val = wlan_sap_is_pre_cac_active(handle);
6820 if (val) {
6821 hdd_err("pre cac is already in progress");
6822 return -EINVAL;
6823 }
6824
6825 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6826 if (!hdd_ap_ctx) {
6827 hdd_err("SAP context is NULL");
6828 return -EINVAL;
6829 }
6830
6831 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
6832 hdd_err("SAP is already on DFS channel:%d",
6833 hdd_ap_ctx->operatingChannel);
6834 return -EINVAL;
6835 }
6836
6837 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
6838 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
6839 hdd_ap_ctx->operatingChannel);
6840 return -EINVAL;
6841 }
6842
6843 hdd_info("channel:%d", channel);
6844
6845 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
6846 &pre_cac_chan);
6847 if (ret != 0)
6848 return ret;
6849
6850 /* Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
6851 * connection update should result in DBS mode
6852 */
6853 status = cds_update_and_wait_for_connection_update(
6854 ap_adapter->sessionId,
6855 pre_cac_chan,
6856 SIR_UPDATE_REASON_PRE_CAC);
6857 if (QDF_IS_STATUS_ERROR(status)) {
6858 hdd_err("error in moving to DBS mode");
6859 return -EINVAL;
6860 }
6861
6862 hdd_debug("starting pre cac SAP adapter");
6863
6864 /* Starting a SAP adapter:
6865 * Instead of opening an adapter, we could just do a SME open session
6866 * for AP type. But, start BSS would still need an adapter.
6867 * So, this option is not taken.
6868 *
6869 * hdd open adapter is going to register this precac interface with
6870 * user space. This interface though exposed to user space will be in
6871 * DOWN state. Consideration was done to avoid this registration to the
6872 * user space. But, as part of SAP operations multiple events are sent
6873 * to user space. Some of these events received from unregistered
6874 * interface was causing crashes. So, retaining the registration.
6875 *
6876 * So, this interface would remain registered and will remain in DOWN
6877 * state for the CAC duration. We will add notes in the feature
6878 * announcement to not use this temporary interface for any activity
6879 * from user space.
6880 */
6881 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
6882 wlan_hdd_get_intf_addr(hdd_ctx),
6883 NET_NAME_UNKNOWN, true);
6884 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306885 hdd_err("error opening the pre cac adapter");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306886 return -EINVAL;
6887 }
6888
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306889 /*
6890 * This interface is internally created by the driver. So, no interface
6891 * up comes for this interface from user space and hence starting
6892 * the adapter internally.
6893 */
6894 if (hdd_start_adapter(pre_cac_adapter)) {
6895 hdd_err("error starting the pre cac adapter");
6896 goto close_pre_cac_adapter;
6897 }
6898
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306899 hdd_debug("preparing for start ap/bss on the pre cac adapter");
6900
6901 wiphy = hdd_ctx->wiphy;
6902 dev = pre_cac_adapter->dev;
6903
6904 /* Since this is only a dummy interface lets us use the IEs from the
6905 * other active SAP interface. In regular scenarios, these IEs would
6906 * come from the user space entity
6907 */
6908 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
6909 sizeof(*ap_adapter->sessionCtx.ap.beacon));
6910 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
6911 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306912 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306913 }
6914 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
6915 ap_adapter->sessionCtx.ap.beacon,
6916 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
6917 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
6918 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
6919 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
6920 ap_adapter->sessionCtx.ap.sapConfig.authType;
6921
6922 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
6923 * to operate on the same bandwidth as that of the 2.4GHz operations.
6924 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
6925 */
6926 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
6927 case CH_WIDTH_20MHZ:
6928 channel_type = NL80211_CHAN_HT20;
6929 break;
6930 case CH_WIDTH_40MHZ:
6931 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
6932 ap_adapter->sessionCtx.ap.sapConfig.channel)
6933 channel_type = NL80211_CHAN_HT40PLUS;
6934 else
6935 channel_type = NL80211_CHAN_HT40MINUS;
6936 break;
6937 default:
6938 channel_type = NL80211_CHAN_NO_HT;
6939 break;
6940 }
6941
6942 freq = cds_chan_to_freq(pre_cac_chan);
6943 chan = __ieee80211_get_channel(wiphy, freq);
6944 if (!chan) {
6945 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306946 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306947 }
6948
6949 cfg80211_chandef_create(&chandef, chan, channel_type);
6950
6951 hdd_debug("orig width:%d channel_type:%d freq:%d",
6952 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
6953 channel_type, freq);
6954
6955 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
6956 if (0 != ret) {
6957 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306958 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306959 }
6960
6961 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
6962 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
6963 eHIDDEN_SSID_NOT_IN_USE, false);
6964 if (QDF_IS_STATUS_ERROR(status)) {
6965 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306966 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306967 }
6968
6969 /*
6970 * The pre cac status is set here. But, it would not be reset explicitly
6971 * anywhere, since after the pre cac success/failure, the pre cac
6972 * adapter itself would be removed.
6973 */
6974 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
6975 if (0 != ret) {
6976 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306977 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306978 }
6979
6980 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
6981 hdd_ap_ctx->operatingChannel);
6982 if (0 != ret) {
6983 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306984 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306985 }
6986
6987 ap_adapter->pre_cac_chan = pre_cac_chan;
6988
6989 return 0;
6990
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306991stop_close_pre_cac_adapter:
6992 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306993 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
6994 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306995close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306996 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
6997 return -EINVAL;
6998}
6999
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307000/**
7001 * hdd_init_bpf_completion() - Initialize the completion event for bpf
7002 *
7003 * Return: None
7004 */
7005void hdd_init_bpf_completion(void)
7006{
7007 init_completion(&bpf_context.completion);
7008}
7009
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307010static const struct nla_policy
7011wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
7012 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
7013};
7014
Agrawal Ashish65634612016-08-18 13:24:32 +05307015static const struct nla_policy
7016wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
7017 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
7018 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
7019};
7020
7021/**
7022 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
7023 * @wiphy: Pointer to wireless phy
7024 * @wdev: Pointer to wireless device
7025 * @data: Pointer to data
7026 * @data_len: Length of @data
7027 *
7028 * This function parses the incoming NL vendor command data attributes and
7029 * updates the SAP context about channel_hint and DFS mode.
7030 * If channel_hint is set, SAP will choose that channel
7031 * as operating channel.
7032 *
7033 * If DFS mode is enabled, driver will include DFS channels
7034 * in ACS else driver will skip DFS channels.
7035 *
7036 * Return: 0 on success, negative errno on failure
7037 */
7038static int
7039__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7040 struct wireless_dev *wdev,
7041 const void *data, int data_len)
7042{
7043 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7044 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
7045 int ret;
7046 struct acs_dfs_policy *acs_policy;
7047 int mode = DFS_MODE_NONE;
7048 int channel_hint = 0;
7049
7050 ENTER_DEV(wdev->netdev);
7051
7052 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7053 hdd_err("Command not allowed in FTM mode");
7054 return -EINVAL;
7055 }
7056
7057 ret = wlan_hdd_validate_context(hdd_ctx);
7058 if (0 != ret)
7059 return ret;
7060
7061 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7062 data, data_len,
7063 wlan_hdd_set_acs_dfs_config_policy)) {
7064 hdd_err("invalid attr");
7065 return -EINVAL;
7066 }
7067
7068 acs_policy = &hdd_ctx->acs_policy;
7069 /*
7070 * SCM sends this attribute to restrict SAP from choosing
7071 * DFS channels from ACS.
7072 */
7073 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7074 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7075
7076 if (!IS_DFS_MODE_VALID(mode)) {
7077 hdd_err("attr acs dfs mode is not valid");
7078 return -EINVAL;
7079 }
7080 acs_policy->acs_dfs_mode = mode;
7081
7082 /*
7083 * SCM sends this attribute to provide an active channel,
7084 * to skip redundant ACS between drivers, and save driver start up time
7085 */
7086 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7087 channel_hint = nla_get_u8(
7088 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7089
7090 if (!IS_CHANNEL_VALID(channel_hint)) {
7091 hdd_err("acs channel is not valid");
7092 return -EINVAL;
7093 }
7094 acs_policy->acs_channel = channel_hint;
7095
7096 return 0;
7097}
7098
7099/**
7100 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7101 * @wiphy: wiphy structure pointer
7102 * @wdev: Wireless device structure pointer
7103 * @data: Pointer to the data received
7104 * @data_len: Length of @data
7105 *
7106 * This function parses the incoming NL vendor command data attributes and
7107 * updates the SAP context about channel_hint and DFS mode.
7108 *
7109 * Return: 0 on success; errno on failure
7110 */
7111static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7112 struct wireless_dev *wdev,
7113 const void *data, int data_len)
7114{
7115 int ret;
7116
7117 cds_ssr_protect(__func__);
7118 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7119 cds_ssr_unprotect(__func__);
7120
7121 return ret;
7122}
7123
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307124/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307125 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7126 * @mode : cfg80211 dfs mode
7127 *
7128 * Return: return csr sta roam dfs mode else return NONE
7129 */
7130static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7131 enum dfs_mode mode)
7132{
7133 switch (mode) {
7134 case DFS_MODE_ENABLE:
7135 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7136 break;
7137 case DFS_MODE_DISABLE:
7138 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7139 break;
7140 case DFS_MODE_DEPRIORITIZE:
7141 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7142 break;
7143 default:
7144 hdd_err("STA Roam policy dfs mode is NONE");
7145 return CSR_STA_ROAM_POLICY_NONE;
7146 }
7147}
7148
7149static const struct nla_policy
7150wlan_hdd_set_sta_roam_config_policy[
7151QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7152 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7153 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7154};
7155
7156/**
7157 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7158 * for station connection or roaming.
7159 * @wiphy: Pointer to wireless phy
7160 * @wdev: Pointer to wireless device
7161 * @data: Pointer to data
7162 * @data_len: Length of @data
7163 *
7164 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7165 * channels needs to be skipped in scanning or not.
7166 * If dfs_mode is disabled, driver will not scan DFS channels.
7167 * If skip_unsafe_channels is set, driver will skip unsafe channels
7168 * in Scanning.
7169 *
7170 * Return: 0 on success, negative errno on failure
7171 */
7172static int
7173__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7174 struct wireless_dev *wdev,
7175 const void *data, int data_len)
7176{
7177 struct net_device *dev = wdev->netdev;
7178 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7179 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7180 struct nlattr *tb[
7181 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7182 int ret;
7183 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7184 enum dfs_mode mode = DFS_MODE_NONE;
7185 bool skip_unsafe_channels = false;
7186 QDF_STATUS status;
7187
7188 ENTER_DEV(dev);
7189
7190 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7191 hdd_err("Command not allowed in FTM mode");
7192 return -EINVAL;
7193 }
7194
7195 ret = wlan_hdd_validate_context(hdd_ctx);
7196 if (0 != ret)
7197 return ret;
7198 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7199 data, data_len,
7200 wlan_hdd_set_sta_roam_config_policy)) {
7201 hdd_err("invalid attr");
7202 return -EINVAL;
7203 }
7204 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7205 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7206 if (!IS_DFS_MODE_VALID(mode)) {
7207 hdd_err("attr sta roam dfs mode policy is not valid");
7208 return -EINVAL;
7209 }
7210
7211 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7212
7213 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7214 skip_unsafe_channels = nla_get_u8(
7215 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
7216
7217 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
7218 skip_unsafe_channels, adapter->sessionId);
7219
7220 if (!QDF_IS_STATUS_SUCCESS(status)) {
7221 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7222 return -EINVAL;
7223 }
7224 return 0;
7225}
7226
7227/**
7228 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7229 * connection and roaming for station.
7230 * @wiphy: wiphy structure pointer
7231 * @wdev: Wireless device structure pointer
7232 * @data: Pointer to the data received
7233 * @data_len: Length of @data
7234 *
7235 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7236 * channels needs to be skipped in scanning or not.
7237 * If dfs_mode is disabled, driver will not scan DFS channels.
7238 * If skip_unsafe_channels is set, driver will skip unsafe channels
7239 * in Scanning.
7240 * Return: 0 on success; errno on failure
7241 */
7242static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7243 struct wireless_dev *wdev,
7244 const void *data, int data_len)
7245{
7246 int ret;
7247
7248 cds_ssr_protect(__func__);
7249 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7250 cds_ssr_unprotect(__func__);
7251
7252 return ret;
7253}
7254
Agrawal Ashish467dde42016-09-08 18:44:22 +05307255#ifdef FEATURE_WLAN_CH_AVOID
7256/**
7257 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7258 * is on unsafe channel.
7259 * @wiphy: wiphy structure pointer
7260 * @wdev: Wireless device structure pointer
7261 * @data: Pointer to the data received
7262 * @data_len: Length of @data
7263 *
7264 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7265 * on any of unsafe channels.
7266 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7267 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7268 *
7269 * Return: 0 on success; errno on failure
7270 */
7271static int
7272__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7273 struct wireless_dev *wdev,
7274 const void *data, int data_len)
7275{
7276 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7277 int ret;
7278 uint16_t unsafe_channel_count;
7279 int unsafe_channel_index;
7280 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7281
7282 ENTER_DEV(wdev->netdev);
7283
7284 if (!qdf_ctx) {
7285 cds_err("qdf_ctx is NULL");
7286 return -EINVAL;
7287 }
7288
7289 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7290 hdd_err("Command not allowed in FTM mode");
7291 return -EINVAL;
7292 }
7293
7294 ret = wlan_hdd_validate_context(hdd_ctx);
7295 if (0 != ret)
7296 return ret;
7297 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7298 &(hdd_ctx->unsafe_channel_count),
7299 sizeof(hdd_ctx->unsafe_channel_list));
7300
7301 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7302 (uint16_t)NUM_CHANNELS);
7303 for (unsafe_channel_index = 0;
7304 unsafe_channel_index < unsafe_channel_count;
7305 unsafe_channel_index++) {
7306 hdd_info("Channel %d is not safe",
7307 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7308 }
7309 hdd_unsafe_channel_restart_sap(hdd_ctx);
7310 return 0;
7311}
7312
7313/**
7314 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7315 * is on unsafe channel.
7316 * @wiphy: wiphy structure pointer
7317 * @wdev: Wireless device structure pointer
7318 * @data: Pointer to the data received
7319 * @data_len: Length of @data
7320 *
7321 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7322 * on any of unsafe channels.
7323 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7324 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7325 *
7326 * Return: 0 on success; errno on failure
7327 */
7328static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7329 struct wireless_dev *wdev,
7330 const void *data, int data_len)
7331{
7332 int ret;
7333
7334 cds_ssr_protect(__func__);
7335 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
7336 cds_ssr_unprotect(__func__);
7337
7338 return ret;
7339}
7340
7341#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307342/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307343 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
7344 * SAP is on unsafe channel.
7345 * @wiphy: wiphy structure pointer
7346 * @wdev: Wireless device structure pointer
7347 * @data: Pointer to the data received
7348 * @data_len: Length of @data
7349 *
7350 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7351 * driver.
7352 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7353 * will initiate restart of sap.
7354 *
7355 * Return: 0 on success; errno on failure
7356 */
7357static int
7358__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7359 struct wireless_dev *wdev,
7360 const void *data, int data_len)
7361{
7362 struct net_device *ndev = wdev->netdev;
7363 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7364 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7365 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
7366 uint8_t config_channel = 0;
7367 hdd_ap_ctx_t *ap_ctx;
7368 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307369 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307370
7371 ENTER();
7372
7373 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007374 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307375 return -EINVAL;
7376 }
7377
7378 ret = wlan_hdd_validate_context(hdd_ctx);
7379 if (0 != ret)
7380 return -EINVAL;
7381
7382 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
7383 data, data_len,
7384 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007385 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307386 return -EINVAL;
7387 }
7388
7389 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
7390 if (!test_bit(SOFTAP_BSS_STARTED,
7391 &hostapd_adapter->event_flags)) {
7392 hdd_err("SAP is not started yet. Restart sap will be invalid");
7393 return -EINVAL;
7394 }
7395
7396 config_channel =
7397 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
7398
7399 if (!((IS_24G_CH(config_channel)) ||
7400 (IS_5G_CH(config_channel)))) {
7401 hdd_err("Channel %d is not valid to restart SAP",
7402 config_channel);
7403 return -ENOTSUPP;
7404 }
7405
7406 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
7407 ap_ctx->sapConfig.channel = config_channel;
7408 ap_ctx->sapConfig.ch_params.ch_width =
7409 ap_ctx->sapConfig.ch_width_orig;
7410
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07007411 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307412 ap_ctx->sapConfig.sec_ch,
7413 &ap_ctx->sapConfig.ch_params);
7414
7415 cds_restart_sap(hostapd_adapter);
7416 }
7417
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307418 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
7419 uint32_t freq_len, i;
7420 uint32_t *freq;
7421 uint8_t chans[QDF_MAX_NUM_CHAN];
7422
7423 hdd_debug("setting mandatory freq/chan list");
7424
7425 freq_len = nla_len(
7426 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
7427 sizeof(uint32_t);
7428
7429 if (freq_len > QDF_MAX_NUM_CHAN) {
7430 hdd_err("insufficient space to hold channels");
7431 return -ENOMEM;
7432 }
7433
7434 freq = nla_data(
7435 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
7436
7437 hdd_debug("freq_len=%d", freq_len);
7438
7439 for (i = 0; i < freq_len; i++) {
7440 chans[i] = ieee80211_frequency_to_channel(freq[i]);
7441 hdd_debug("freq[%d]=%d", i, freq[i]);
7442 }
7443
7444 status = cds_set_sap_mandatory_channels(chans, freq_len);
7445 if (QDF_IS_STATUS_ERROR(status))
7446 return -EINVAL;
7447 }
7448
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307449 return 0;
7450}
7451
7452/**
7453 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
7454 * @wiphy: wiphy structure pointer
7455 * @wdev: Wireless device structure pointer
7456 * @data: Pointer to the data received
7457 * @data_len: Length of @data
7458 *
7459 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7460 * driver.
7461 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7462 * will initiate restart of sap.
7463 *
7464 * Return: 0 on success; errno on failure
7465 */
7466static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7467 struct wireless_dev *wdev,
7468 const void *data, int data_len)
7469{
7470 int ret;
7471
7472 cds_ssr_protect(__func__);
7473 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
7474 wdev, data, data_len);
7475 cds_ssr_unprotect(__func__);
7476
7477 return ret;
7478}
7479
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307480#undef BPF_INVALID
7481#undef BPF_SET_RESET
7482#undef BPF_VERSION
7483#undef BPF_ID
7484#undef BPF_PACKET_SIZE
7485#undef BPF_CURRENT_OFFSET
7486#undef BPF_PROGRAM
7487#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307488
7489/**
7490 * define short names for the global vendor params
7491 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
7492 */
7493#define PARAM_TOTAL_CMD_EVENT_WAKE \
7494 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
7495#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
7496 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
7497#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
7498 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
7499#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
7500 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
7501#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
7502 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
7503#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
7504 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
7505#define PARAM_TOTAL_RX_DATA_WAKE \
7506 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
7507#define PARAM_RX_UNICAST_CNT \
7508 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
7509#define PARAM_RX_MULTICAST_CNT \
7510 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
7511#define PARAM_RX_BROADCAST_CNT \
7512 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
7513#define PARAM_ICMP_PKT \
7514 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
7515#define PARAM_ICMP6_PKT \
7516 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
7517#define PARAM_ICMP6_RA \
7518 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
7519#define PARAM_ICMP6_NA \
7520 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
7521#define PARAM_ICMP6_NS \
7522 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
7523#define PARAM_ICMP4_RX_MULTICAST_CNT \
7524 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
7525#define PARAM_ICMP6_RX_MULTICAST_CNT \
7526 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
7527#define PARAM_OTHER_RX_MULTICAST_CNT \
7528 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
7529
7530
7531/**
7532 * hdd_send_wakelock_stats() - API to send wakelock stats
7533 * @ctx: context to be passed to callback
7534 * @data: data passed to callback
7535 *
7536 * This function is used to send wake lock stats to HAL layer
7537 *
7538 * Return: 0 on success, error number otherwise.
7539 */
7540static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
7541 const struct sir_wake_lock_stats *data)
7542{
7543 struct sk_buff *skb;
7544 uint32_t nl_buf_len;
7545 uint32_t total_rx_data_wake, rx_multicast_cnt;
7546 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307547 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307548
7549 ENTER();
7550
7551 nl_buf_len = NLMSG_HDRLEN;
7552 nl_buf_len +=
7553 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
7554 (NLMSG_HDRLEN + sizeof(uint32_t));
7555
7556 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7557
7558 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007559 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307560 return -ENOMEM;
7561 }
7562
Jeff Johnson64943bd2016-08-23 13:14:06 -07007563 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307564 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007565 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307566 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007567 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307568 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007569 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307570 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007571 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307572 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007573 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307574 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007575 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307576 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007577 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
7578 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307579 data->wow_icmpv6_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307580
7581 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307582 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307583
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307584 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307585 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307586
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307587 rx_multicast_cnt =
7588 data->wow_ipv4_mcast_wake_up_count +
7589 ipv6_rx_multicast_addr_cnt;
7590
7591 total_rx_data_wake =
7592 data->wow_ucast_wake_up_count +
7593 data->wow_bcast_wake_up_count +
7594 rx_multicast_cnt;
7595
7596 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
7597 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
7598 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
7599 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
7600 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
7601 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
7602 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
7603 total_rx_data_wake) ||
7604 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
7605 data->wow_ucast_wake_up_count) ||
7606 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
7607 rx_multicast_cnt) ||
7608 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
7609 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307610 nla_put_u32(skb, PARAM_ICMP_PKT,
7611 data->wow_icmpv4_count) ||
7612 nla_put_u32(skb, PARAM_ICMP6_PKT,
7613 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307614 nla_put_u32(skb, PARAM_ICMP6_RA,
7615 data->wow_ipv6_mcast_ra_stats) ||
7616 nla_put_u32(skb, PARAM_ICMP6_NA,
7617 data->wow_ipv6_mcast_na_stats) ||
7618 nla_put_u32(skb, PARAM_ICMP6_NS,
7619 data->wow_ipv6_mcast_ns_stats) ||
7620 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
7621 data->wow_ipv4_mcast_wake_up_count) ||
7622 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
7623 ipv6_rx_multicast_addr_cnt) ||
7624 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007625 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307626 goto nla_put_failure;
7627 }
7628
7629 cfg80211_vendor_cmd_reply(skb);
7630
7631 EXIT();
7632 return 0;
7633
7634nla_put_failure:
7635 kfree_skb(skb);
7636 return -EINVAL;
7637}
7638
7639/**
7640 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7641 * @wiphy: wiphy pointer
7642 * @wdev: pointer to struct wireless_dev
7643 * @data: pointer to incoming NL vendor data
7644 * @data_len: length of @data
7645 *
7646 * This function parses the incoming NL vendor command data attributes and
7647 * invokes the SME Api and blocks on a completion variable.
7648 * WMA copies required data and invokes callback
7649 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7650 *
7651 * Return: 0 on success; error number otherwise.
7652 */
7653static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7654 struct wireless_dev *wdev,
7655 const void *data,
7656 int data_len)
7657{
7658 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7659 int status, ret;
7660 struct sir_wake_lock_stats wake_lock_stats;
7661 QDF_STATUS qdf_status;
7662
7663 ENTER();
7664
7665 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007666 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307667 return -EINVAL;
7668 }
7669
7670 status = wlan_hdd_validate_context(hdd_ctx);
7671 if (0 != status)
7672 return -EINVAL;
7673
7674 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
7675 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007676 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307677 return -EINVAL;
7678 }
7679
7680 ret = hdd_send_wakelock_stats(hdd_ctx,
7681 &wake_lock_stats);
7682 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07007683 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307684
7685 EXIT();
7686 return ret;
7687}
7688
7689/**
7690 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7691 * @wiphy: wiphy pointer
7692 * @wdev: pointer to struct wireless_dev
7693 * @data: pointer to incoming NL vendor data
7694 * @data_len: length of @data
7695 *
7696 * This function parses the incoming NL vendor command data attributes and
7697 * invokes the SME Api and blocks on a completion variable.
7698 * WMA copies required data and invokes callback
7699 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7700 *
7701 * Return: 0 on success; error number otherwise.
7702 */
7703static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7704 struct wireless_dev *wdev,
7705 const void *data, int data_len)
7706{
7707 int ret;
7708
7709 cds_ssr_protect(__func__);
7710 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
7711 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07007712 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307713
7714 return ret;
7715}
7716
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307717/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05307718 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
7719 * @wiphy: wiphy structure pointer
7720 * @wdev: Wireless device structure pointer
7721 * @data: Pointer to the data received
7722 * @data_len: Length of @data
7723 *
7724 * This function reads wmi max bus size and fill in the skb with
7725 * NL attributes and send up the NL event.
7726 * Return: 0 on success; errno on failure
7727 */
7728static int
7729__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7730 struct wireless_dev *wdev,
7731 const void *data, int data_len)
7732{
7733 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7734 int ret_val;
7735 struct sk_buff *skb;
7736 uint32_t nl_buf_len;
7737
7738 ENTER();
7739
7740 ret_val = wlan_hdd_validate_context(hdd_ctx);
7741 if (ret_val)
7742 return ret_val;
7743
7744 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7745 hdd_err("Command not allowed in FTM mode");
7746 return -EINVAL;
7747 }
7748
7749 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
7750
7751 nl_buf_len = NLMSG_HDRLEN;
7752 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
7753
7754 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7755 if (!skb) {
7756 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
7757 return -ENOMEM;
7758 }
7759
7760 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
7761 hdd_ctx->wmi_max_len)) {
7762 hdd_err("nla put failure");
7763 goto nla_put_failure;
7764 }
7765
7766 cfg80211_vendor_cmd_reply(skb);
7767
7768 EXIT();
7769
7770 return 0;
7771
7772nla_put_failure:
7773 kfree_skb(skb);
7774 return -EINVAL;
7775}
7776
7777/**
7778 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
7779 * @wiphy: wiphy structure pointer
7780 * @wdev: Wireless device structure pointer
7781 * @data: Pointer to the data received
7782 * @data_len: Length of @data
7783 *
7784 * Return: 0 on success; errno on failure
7785 */
7786static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7787 struct wireless_dev *wdev,
7788 const void *data, int data_len)
7789{
7790 int ret;
7791
7792 cds_ssr_protect(__func__);
7793 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
7794 cds_ssr_unprotect(__func__);
7795
7796 return ret;
7797}
7798
7799/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307800 *__wlan_hdd_cfg80211_setband() - set band
7801 * @wiphy: Pointer to wireless phy
7802 * @wdev: Pointer to wireless device
7803 * @data: Pointer to data
7804 * @data_len: Length of @data
7805 *
7806 * Return: 0 on success, negative errno on failure
7807 */
7808static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7809 struct wireless_dev *wdev,
7810 const void *data, int data_len)
7811{
7812 struct net_device *dev = wdev->netdev;
7813 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7814 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7815 int ret;
7816 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
7817 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
7818
7819 ENTER();
7820
7821 ret = wlan_hdd_validate_context(hdd_ctx);
7822 if (ret)
7823 return ret;
7824
7825 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
7826 hdd_err(FL("Invalid ATTR"));
7827 return -EINVAL;
7828 }
7829
7830 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
7831 hdd_err(FL("attr SETBAND_VALUE failed"));
7832 return -EINVAL;
7833 }
7834
7835 ret = hdd_set_band(dev,
7836 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
7837
7838 EXIT();
7839 return ret;
7840}
7841
7842/**
7843 * wlan_hdd_cfg80211_setband() - Wrapper to setband
7844 * @wiphy: wiphy structure pointer
7845 * @wdev: Wireless device structure pointer
7846 * @data: Pointer to the data received
7847 * @data_len: Length of @data
7848 *
7849 * Return: 0 on success; errno on failure
7850 */
7851static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7852 struct wireless_dev *wdev,
7853 const void *data, int data_len)
7854{
7855 int ret;
7856
7857 cds_ssr_protect(__func__);
7858 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
7859 cds_ssr_unprotect(__func__);
7860
7861 return ret;
7862}
7863
Mukul Sharma69c44cd2016-09-12 18:33:57 +05307864static const struct
7865nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
7866 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
7867 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
7868 .len = QDF_MAC_ADDR_SIZE},
7869};
7870
7871/**
7872 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7873 * @wiphy: Pointer to wireless phy
7874 * @wdev: Pointer to wireless device
7875 * @data: Pointer to data
7876 * @data_len: Length of @data
7877 *
7878 * This function is used to enable/disable roaming using vendor commands
7879 *
7880 * Return: 0 on success, negative errno on failure
7881 */
7882static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7883 struct wireless_dev *wdev,
7884 const void *data, int data_len)
7885{
7886 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7887 struct net_device *dev = wdev->netdev;
7888 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7889 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7890 uint32_t is_fast_roam_enabled;
7891 int ret;
7892
7893 ENTER_DEV(dev);
7894
7895 ret = wlan_hdd_validate_context(hdd_ctx);
7896 if (0 != ret)
7897 return ret;
7898
7899 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7900 hdd_err("Command not allowed in FTM mode");
7901 return -EINVAL;
7902 }
7903
7904 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
7905 qca_wlan_vendor_attr);
7906 if (ret) {
7907 hdd_err("Invalid ATTR");
7908 return -EINVAL;
7909 }
7910
7911 /* Parse and fetch Enable flag */
7912 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
7913 hdd_err("attr enable failed");
7914 return -EINVAL;
7915 }
7916
7917 is_fast_roam_enabled = nla_get_u32(
7918 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
7919 hdd_notice("isFastRoamEnabled %d", is_fast_roam_enabled);
7920
7921 /* Update roaming */
7922 ret = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
7923 is_fast_roam_enabled);
7924 if (ret)
7925 hdd_err("sme_config_fast_roaming failed");
7926 EXIT();
7927 return ret;
7928}
7929
7930/**
7931 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7932 * @wiphy: Pointer to wireless phy
7933 * @wdev: Pointer to wireless device
7934 * @data: Pointer to data
7935 * @data_len: Length of @data
7936 *
7937 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
7938 *
7939 * Return: 0 on success, negative errno on failure
7940 */
7941static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7942 struct wireless_dev *wdev,
7943 const void *data, int data_len)
7944{
7945 int ret;
7946
7947 cds_ssr_protect(__func__);
7948 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
7949 cds_ssr_unprotect(__func__);
7950
7951 return ret;
7952}
7953
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007954const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
7955 {
7956 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7957 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
7958 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05307959 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007960 .doit = is_driver_dfs_capable
7961 },
7962
7963#ifdef WLAN_FEATURE_NAN
7964 {
7965 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7966 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
7967 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7968 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7969 .doit = wlan_hdd_cfg80211_nan_request
7970 },
7971#endif
7972
7973#ifdef WLAN_FEATURE_STATS_EXT
7974 {
7975 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7976 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
7977 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7978 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7979 .doit = wlan_hdd_cfg80211_stats_ext_request
7980 },
7981#endif
7982#ifdef FEATURE_WLAN_EXTSCAN
7983 {
7984 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7985 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
7986 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7987 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7988 .doit = wlan_hdd_cfg80211_extscan_start
7989 },
7990 {
7991 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7992 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
7993 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7994 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7995 .doit = wlan_hdd_cfg80211_extscan_stop
7996 },
7997 {
7998 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7999 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
8000 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8001 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
8002 },
8003 {
8004 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8005 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
8006 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8007 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8008 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
8009 },
8010 {
8011 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8012 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
8013 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8014 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8015 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
8016 },
8017 {
8018 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8019 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
8020 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8021 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8022 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
8023 },
8024 {
8025 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8026 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
8027 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8028 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8029 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
8030 },
8031 {
8032 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8033 .info.subcmd =
8034 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
8035 .flags =
8036 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8037 WIPHY_VENDOR_CMD_NEED_RUNNING,
8038 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
8039 },
8040 {
8041 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8042 .info.subcmd =
8043 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
8044 .flags =
8045 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
8046 WIPHY_VENDOR_CMD_NEED_RUNNING,
8047 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
8048 },
8049 {
8050 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8051 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
8052 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8053 WIPHY_VENDOR_CMD_NEED_NETDEV |
8054 WIPHY_VENDOR_CMD_NEED_RUNNING,
8055 .doit = wlan_hdd_cfg80211_set_epno_list
8056 },
8057#endif /* FEATURE_WLAN_EXTSCAN */
8058
8059#ifdef WLAN_FEATURE_LINK_LAYER_STATS
8060 {
8061 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8062 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
8063 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8064 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8065 .doit = wlan_hdd_cfg80211_ll_stats_clear
8066 },
8067
8068 {
8069 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8070 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
8071 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8072 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8073 .doit = wlan_hdd_cfg80211_ll_stats_set
8074 },
8075
8076 {
8077 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8078 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
8079 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8080 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8081 .doit = wlan_hdd_cfg80211_ll_stats_get
8082 },
8083#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
8084#ifdef FEATURE_WLAN_TDLS
8085 {
8086 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8087 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
8088 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8089 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8090 .doit = wlan_hdd_cfg80211_exttdls_enable
8091 },
8092 {
8093 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8094 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
8095 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8096 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8097 .doit = wlan_hdd_cfg80211_exttdls_disable
8098 },
8099 {
8100 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8101 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
8102 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8103 .doit = wlan_hdd_cfg80211_exttdls_get_status
8104 },
8105#endif
8106 {
8107 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8108 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
8109 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8110 .doit = wlan_hdd_cfg80211_get_supported_features
8111 },
8112 {
8113 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8114 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
8115 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8116 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
8117 },
8118 {
8119 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8120 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
8121 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05308122 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008123 },
8124 {
8125 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8126 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
8127 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8128 WIPHY_VENDOR_CMD_NEED_NETDEV,
8129 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
8130 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07008131 {
8132 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8133 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
8134 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8135 WIPHY_VENDOR_CMD_NEED_NETDEV,
8136 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
8137 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008138 {
8139 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05308140 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
8141 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8142 WIPHY_VENDOR_CMD_NEED_NETDEV |
8143 WIPHY_VENDOR_CMD_NEED_RUNNING,
8144 .doit = hdd_cfg80211_get_station_cmd
8145 },
8146 {
8147 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008148 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
8149 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8150 WIPHY_VENDOR_CMD_NEED_NETDEV |
8151 WIPHY_VENDOR_CMD_NEED_RUNNING,
8152 .doit = wlan_hdd_cfg80211_do_acs
8153 },
8154
8155 {
8156 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8157 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
8158 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8159 WIPHY_VENDOR_CMD_NEED_NETDEV,
8160 .doit = wlan_hdd_cfg80211_get_features
8161 },
8162#ifdef WLAN_FEATURE_ROAM_OFFLOAD
8163 {
8164 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8165 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
8166 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8167 WIPHY_VENDOR_CMD_NEED_NETDEV |
8168 WIPHY_VENDOR_CMD_NEED_RUNNING,
8169 .doit = wlan_hdd_cfg80211_keymgmt_set_key
8170 },
8171#endif
8172#ifdef FEATURE_WLAN_EXTSCAN
8173 {
8174 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8175 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
8176 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8177 WIPHY_VENDOR_CMD_NEED_NETDEV |
8178 WIPHY_VENDOR_CMD_NEED_RUNNING,
8179 .doit = wlan_hdd_cfg80211_set_passpoint_list
8180 },
8181 {
8182 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8183 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
8184 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8185 WIPHY_VENDOR_CMD_NEED_NETDEV |
8186 WIPHY_VENDOR_CMD_NEED_RUNNING,
8187 .doit = wlan_hdd_cfg80211_reset_passpoint_list
8188 },
8189 {
8190 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8191 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
8192 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8193 WIPHY_VENDOR_CMD_NEED_NETDEV |
8194 WIPHY_VENDOR_CMD_NEED_RUNNING,
8195 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
8196 },
8197 {
8198 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8199 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
8200 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8201 WIPHY_VENDOR_CMD_NEED_NETDEV |
8202 WIPHY_VENDOR_CMD_NEED_RUNNING,
8203 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
8204 },
8205#endif /* FEATURE_WLAN_EXTSCAN */
8206 {
8207 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8208 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
8209 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8210 WIPHY_VENDOR_CMD_NEED_NETDEV,
8211 .doit = wlan_hdd_cfg80211_get_wifi_info
8212 },
8213 {
8214 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8215 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
8216 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8217 WIPHY_VENDOR_CMD_NEED_NETDEV |
8218 WIPHY_VENDOR_CMD_NEED_RUNNING,
8219 .doit = wlan_hdd_cfg80211_wifi_configuration_set
8220 },
8221 {
8222 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8223 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
8224 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8225 WIPHY_VENDOR_CMD_NEED_NETDEV,
8226 .doit = wlan_hdd_cfg80211_set_ext_roam_params
8227 },
8228 {
8229 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8230 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
8231 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8232 WIPHY_VENDOR_CMD_NEED_NETDEV,
8233 .doit = wlan_hdd_cfg80211_wifi_logger_start
8234 },
8235 {
8236 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8237 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
8238 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8239 WIPHY_VENDOR_CMD_NEED_NETDEV,
8240 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
8241 },
8242 {
8243 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8244 .info.subcmd =
8245 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
8246 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8247 WIPHY_VENDOR_CMD_NEED_NETDEV |
8248 WIPHY_VENDOR_CMD_NEED_RUNNING,
8249 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
8250 },
8251 {
8252 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8253 .info.subcmd =
8254 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
8255 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8256 WIPHY_VENDOR_CMD_NEED_NETDEV |
8257 WIPHY_VENDOR_CMD_NEED_RUNNING,
8258 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
8259 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07008260#ifdef WLAN_FEATURE_TSF
8261 {
8262 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8263 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
8264 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8265 WIPHY_VENDOR_CMD_NEED_NETDEV |
8266 WIPHY_VENDOR_CMD_NEED_RUNNING,
8267 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
8268 },
8269#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008270#ifdef FEATURE_WLAN_TDLS
8271 {
8272 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8273 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
8274 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8275 WIPHY_VENDOR_CMD_NEED_NETDEV |
8276 WIPHY_VENDOR_CMD_NEED_RUNNING,
8277 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
8278 },
8279#endif
8280#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
8281 {
8282 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8283 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
8284 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8285 WIPHY_VENDOR_CMD_NEED_NETDEV |
8286 WIPHY_VENDOR_CMD_NEED_RUNNING,
8287 .doit = wlan_hdd_cfg80211_offloaded_packets
8288 },
8289#endif
8290 {
8291 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8292 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
8293 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8294 WIPHY_VENDOR_CMD_NEED_NETDEV |
8295 WIPHY_VENDOR_CMD_NEED_RUNNING,
8296 .doit = wlan_hdd_cfg80211_monitor_rssi
8297 },
8298 {
8299 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308300 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
8301 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8302 WIPHY_VENDOR_CMD_NEED_NETDEV |
8303 WIPHY_VENDOR_CMD_NEED_RUNNING,
8304 .doit = wlan_hdd_cfg80211_set_ns_offload
8305 },
8306 {
8307 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008308 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
8309 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8310 WIPHY_VENDOR_CMD_NEED_NETDEV |
8311 WIPHY_VENDOR_CMD_NEED_RUNNING,
8312 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
8313 },
8314#ifdef WLAN_FEATURE_MEMDUMP
8315 {
8316 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8317 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
8318 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8319 WIPHY_VENDOR_CMD_NEED_NETDEV |
8320 WIPHY_VENDOR_CMD_NEED_RUNNING,
8321 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
8322 },
8323#endif /* WLAN_FEATURE_MEMDUMP */
8324 {
8325 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8326 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
8327 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8328 WIPHY_VENDOR_CMD_NEED_NETDEV |
8329 WIPHY_VENDOR_CMD_NEED_RUNNING,
8330 .doit = wlan_hdd_cfg80211_vendor_scan
8331 },
8332
8333 /* OCB commands */
8334 {
8335 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8336 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
8337 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8338 WIPHY_VENDOR_CMD_NEED_NETDEV |
8339 WIPHY_VENDOR_CMD_NEED_RUNNING,
8340 .doit = wlan_hdd_cfg80211_ocb_set_config
8341 },
8342 {
8343 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8344 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
8345 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8346 WIPHY_VENDOR_CMD_NEED_NETDEV |
8347 WIPHY_VENDOR_CMD_NEED_RUNNING,
8348 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
8349 },
8350 {
8351 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8352 .info.subcmd =
8353 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
8354 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8355 WIPHY_VENDOR_CMD_NEED_NETDEV |
8356 WIPHY_VENDOR_CMD_NEED_RUNNING,
8357 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
8358 },
8359 {
8360 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8361 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
8362 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8363 WIPHY_VENDOR_CMD_NEED_NETDEV |
8364 WIPHY_VENDOR_CMD_NEED_RUNNING,
8365 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
8366 },
8367 {
8368 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8369 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
8370 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8371 WIPHY_VENDOR_CMD_NEED_NETDEV |
8372 WIPHY_VENDOR_CMD_NEED_RUNNING,
8373 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
8374 },
8375 {
8376 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8377 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
8378 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8379 WIPHY_VENDOR_CMD_NEED_NETDEV |
8380 WIPHY_VENDOR_CMD_NEED_RUNNING,
8381 .doit = wlan_hdd_cfg80211_dcc_get_stats
8382 },
8383 {
8384 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8385 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
8386 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8387 WIPHY_VENDOR_CMD_NEED_NETDEV |
8388 WIPHY_VENDOR_CMD_NEED_RUNNING,
8389 .doit = wlan_hdd_cfg80211_dcc_clear_stats
8390 },
8391 {
8392 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8393 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
8394 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8395 WIPHY_VENDOR_CMD_NEED_NETDEV |
8396 WIPHY_VENDOR_CMD_NEED_RUNNING,
8397 .doit = wlan_hdd_cfg80211_dcc_update_ndl
8398 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308399 {
8400 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8401 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
8402 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8403 WIPHY_VENDOR_CMD_NEED_NETDEV |
8404 WIPHY_VENDOR_CMD_NEED_RUNNING,
8405 .doit = wlan_hdd_cfg80211_get_link_properties
8406 },
Peng Xu278d0122015-09-24 16:34:17 -07008407 {
Peng Xud2220962016-07-11 17:59:17 -07008408 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07008409 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
8410 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8411 WIPHY_VENDOR_CMD_NEED_NETDEV |
8412 WIPHY_VENDOR_CMD_NEED_RUNNING,
8413 .doit = wlan_hdd_cfg80211_set_ota_test
8414 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08008415#ifdef FEATURE_LFR_SUBNET_DETECTION
8416 {
8417 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8418 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
8419 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8420 WIPHY_VENDOR_CMD_NEED_NETDEV |
8421 WIPHY_VENDOR_CMD_NEED_RUNNING,
8422 .doit = wlan_hdd_cfg80211_set_gateway_params
8423 },
8424#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07008425 {
Peng Xud2220962016-07-11 17:59:17 -07008426 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07008427 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
8428 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8429 WIPHY_VENDOR_CMD_NEED_NETDEV |
8430 WIPHY_VENDOR_CMD_NEED_RUNNING,
8431 .doit = wlan_hdd_cfg80211_txpower_scale
8432 },
8433 {
8434 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8435 .info.subcmd =
8436 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
8437 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8438 WIPHY_VENDOR_CMD_NEED_NETDEV |
8439 WIPHY_VENDOR_CMD_NEED_RUNNING,
8440 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
8441 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308442 {
8443 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8444 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
8445 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8446 WIPHY_VENDOR_CMD_NEED_NETDEV |
8447 WIPHY_VENDOR_CMD_NEED_RUNNING,
8448 .doit = wlan_hdd_cfg80211_bpf_offload
8449 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308450 {
8451 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05308452 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
8453 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8454 WIPHY_VENDOR_CMD_NEED_NETDEV |
8455 WIPHY_VENDOR_CMD_NEED_RUNNING,
8456 .doit = wlan_hdd_cfg80211_acs_dfs_mode
8457 },
8458 {
8459 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308460 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
8461 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8462 WIPHY_VENDOR_CMD_NEED_NETDEV |
8463 WIPHY_VENDOR_CMD_NEED_RUNNING,
8464 .doit = wlan_hdd_cfg80211_sta_roam_policy
8465 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05308466#ifdef FEATURE_WLAN_CH_AVOID
8467 {
8468 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8469 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
8470 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8471 WIPHY_VENDOR_CMD_NEED_NETDEV |
8472 WIPHY_VENDOR_CMD_NEED_RUNNING,
8473 .doit = wlan_hdd_cfg80211_avoid_freq
8474 },
8475#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308476 {
8477 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308478 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
8479 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8480 WIPHY_VENDOR_CMD_NEED_NETDEV |
8481 WIPHY_VENDOR_CMD_NEED_RUNNING,
8482 .doit = wlan_hdd_cfg80211_sap_configuration_set
8483 },
Peng Xu8fdaa492016-06-22 10:20:47 -07008484 {
Peng Xu4225c152016-07-14 21:18:14 -07008485 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07008486 .info.subcmd =
8487 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
8488 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8489 WIPHY_VENDOR_CMD_NEED_NETDEV |
8490 WIPHY_VENDOR_CMD_NEED_RUNNING,
8491 .doit = wlan_hdd_cfg80211_p2p_lo_start
8492 },
8493 {
8494 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8495 .info.subcmd =
8496 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
8497 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8498 WIPHY_VENDOR_CMD_NEED_NETDEV |
8499 WIPHY_VENDOR_CMD_NEED_RUNNING,
8500 .doit = wlan_hdd_cfg80211_p2p_lo_stop
8501 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308502 {
8503 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8504 .info.subcmd =
8505 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
8506 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8507 WIPHY_VENDOR_CMD_NEED_NETDEV |
8508 WIPHY_VENDOR_CMD_NEED_RUNNING,
8509 .doit = wlan_hdd_cfg80211_conditional_chan_switch
8510 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07008511#ifdef WLAN_FEATURE_NAN_DATAPATH
8512 {
8513 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8514 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
8515 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8516 WIPHY_VENDOR_CMD_NEED_NETDEV |
8517 WIPHY_VENDOR_CMD_NEED_RUNNING,
8518 .doit = wlan_hdd_cfg80211_process_ndp_cmd
8519 },
8520#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308521 {
8522 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8523 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
8524 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8525 WIPHY_VENDOR_CMD_NEED_NETDEV |
8526 WIPHY_VENDOR_CMD_NEED_RUNNING,
8527 .doit = wlan_hdd_cfg80211_get_wakelock_stats
8528 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308529 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308530 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8531 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
8532 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8533 WIPHY_VENDOR_CMD_NEED_NETDEV |
8534 WIPHY_VENDOR_CMD_NEED_RUNNING,
8535 .doit = wlan_hdd_cfg80211_get_bus_size
8536 },
8537 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308538 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
8539 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8540 WIPHY_VENDOR_CMD_NEED_NETDEV |
8541 WIPHY_VENDOR_CMD_NEED_RUNNING,
8542 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308543 },
8544 {
8545 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8546 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
8547 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8548 WIPHY_VENDOR_CMD_NEED_NETDEV |
8549 WIPHY_VENDOR_CMD_NEED_RUNNING,
8550 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05308551 },
8552#ifdef WLAN_FEATURE_DISA
8553 {
8554 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8555 .info.subcmd =
8556 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
8557 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8558 WIPHY_VENDOR_CMD_NEED_NETDEV |
8559 WIPHY_VENDOR_CMD_NEED_RUNNING,
8560 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
8561 },
8562#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008563};
8564
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008565/**
8566 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
8567 * @priv_size: Size of the hdd context.
8568 *
8569 * Allocate wiphy context and hdd context.
8570 *
8571 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008572 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008573hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008574{
8575 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008576 hdd_context_t *hdd_ctx;
8577
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008578 ENTER();
8579
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008580 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
8581
8582 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008583 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008584 return NULL;
8585 }
8586
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008587 hdd_ctx = wiphy_priv(wiphy);
8588
8589 hdd_ctx->wiphy = wiphy;
8590
8591 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008592}
8593
8594/*
8595 * FUNCTION: wlan_hdd_cfg80211_update_band
8596 * This function is called from the supplicant through a
8597 * private ioctl to change the band value
8598 */
8599int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
8600{
8601 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07008602 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008603
8604 ENTER();
8605
8606 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8607
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008608 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008609 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008610
8611 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8612 struct ieee80211_supported_band *band = wiphy->bands[i];
8613
8614 channelEnabledState =
8615 cds_get_channel_state(band->channels[j].
8616 hw_value);
8617
8618 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
8619 /* 5G only */
8620#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8621 /* Enable Social channels for P2P */
8622 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8623 (band->channels[j].center_freq)
8624 && CHANNEL_STATE_ENABLE ==
8625 channelEnabledState)
8626 band->channels[j].flags &=
8627 ~IEEE80211_CHAN_DISABLED;
8628 else
8629#endif
8630 band->channels[j].flags |=
8631 IEEE80211_CHAN_DISABLED;
8632 continue;
8633 } else if (IEEE80211_BAND_5GHZ == i &&
8634 eCSR_BAND_24 == eBand) {
8635 /* 2G only */
8636 band->channels[j].flags |=
8637 IEEE80211_CHAN_DISABLED;
8638 continue;
8639 }
8640
Amar Singhal6842e8f2016-02-23 16:30:32 -08008641 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008642 band->channels[j].flags &=
8643 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008644 }
8645 }
8646 return 0;
8647}
8648
8649/*
8650 * FUNCTION: wlan_hdd_cfg80211_init
8651 * This function is called by hdd_wlan_startup()
8652 * during initialization.
8653 * This function is used to initialize and register wiphy structure.
8654 */
8655int wlan_hdd_cfg80211_init(struct device *dev,
8656 struct wiphy *wiphy, struct hdd_config *pCfg)
8657{
8658 int i, j;
8659 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8660
8661 ENTER();
8662
8663 /* Now bind the underlying wlan device with wiphy */
8664 set_wiphy_dev(wiphy, dev);
8665
8666 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
8667
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008668#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
8669 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008670 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008671#else
8672 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008673 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008674#endif
8675
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008676 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
8677 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
8678 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
8679#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
8680 | WIPHY_FLAG_4ADDR_STATION
8681#endif
8682 | WIPHY_FLAG_OFFCHAN_TX;
8683
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008684#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
8685 wiphy->wowlan = &wowlan_support_cfg80211_init;
8686#else
8687 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
8688 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
8689 wiphy->wowlan.pattern_min_len = 1;
8690 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
8691#endif
8692
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07008693 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008694#ifdef FEATURE_WLAN_ESE
8695 || pCfg->isEseIniFeatureEnabled
8696#endif
8697 ) {
8698 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
8699 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008700#ifdef FEATURE_WLAN_TDLS
8701 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
8702 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
8703#endif
8704
8705 wiphy->features |= NL80211_FEATURE_HT_IBSS;
8706
Naveen Rawatc77e6e72016-08-05 15:19:03 -07008707#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
8708 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
8709#endif
8710
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008711#ifdef FEATURE_WLAN_SCAN_PNO
8712 if (pCfg->configPNOScanSupport) {
8713 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8714 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
8715 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
8716 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Ryan Hsub736bc52016-06-15 16:58:24 -07008717#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) || defined(WITH_BACKPORTS)
8718 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
8719#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008720 }
8721#endif /*FEATURE_WLAN_SCAN_PNO */
8722
8723#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05308724 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008725#endif
8726
8727 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
8728 driver can still register regulatory callback and
8729 it will get regulatory settings in wiphy->band[], but
8730 driver need to determine what to do with both
8731 regulatory settings */
8732
8733 wiphy->reg_notifier = hdd_reg_notifier;
8734
8735#if defined QCA_WIFI_FTM
8736}
8737#endif
8738
8739 wiphy->max_scan_ssids = MAX_SCAN_SSID;
8740
8741 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
8742
8743 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
8744
Arun Khandavallifae92942016-08-01 13:31:08 +05308745 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
8746 | BIT(NL80211_IFTYPE_ADHOC)
8747 | BIT(NL80211_IFTYPE_P2P_CLIENT)
8748 | BIT(NL80211_IFTYPE_P2P_GO)
8749 | BIT(NL80211_IFTYPE_AP)
8750 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008751
Arun Khandavallifae92942016-08-01 13:31:08 +05308752 if (pCfg->advertiseConcurrentOperation) {
8753 if (pCfg->enableMCC) {
8754 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07008755
Arun Khandavallifae92942016-08-01 13:31:08 +05308756 for (i = 0;
8757 i < ARRAY_SIZE(wlan_hdd_iface_combination);
8758 i++) {
8759 if (!pCfg->allowMCCGODiffBI)
8760 wlan_hdd_iface_combination[i].
8761 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008762 }
8763 }
8764 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +05308765 ARRAY_SIZE(wlan_hdd_iface_combination);
8766 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008767 }
8768
8769 /* Before registering we need to update the ht capabilitied based
8770 * on ini values*/
8771 if (!pCfg->ShortGI20MhzEnable) {
8772 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
8773 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008774 }
8775
8776 if (!pCfg->ShortGI40MhzEnable) {
8777 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
8778 }
8779
8780 if (!pCfg->nChannelBondingMode5GHz) {
8781 wlan_hdd_band_5_ghz.ht_cap.cap &=
8782 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
8783 }
8784
Abhishek Singhf512bf32016-05-04 16:47:46 +05308785 /*
8786 * In case of static linked driver at the time of driver unload,
8787 * module exit doesn't happens. Module cleanup helps in cleaning
8788 * of static memory.
8789 * If driver load happens statically, at the time of driver unload,
8790 * wiphy flags don't get reset because of static memory.
8791 * It's better not to store channel in static memory.
8792 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008793 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
Abhishek Singhf512bf32016-05-04 16:47:46 +05308794 wiphy->bands[IEEE80211_BAND_2GHZ]->channels =
8795 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
8796 if (wiphy->bands[IEEE80211_BAND_2GHZ]->channels == NULL) {
8797 hdd_err("Not enough memory to allocate channels");
8798 return -ENOMEM;
8799 }
8800 qdf_mem_copy(wiphy->bands[IEEE80211_BAND_2GHZ]->channels,
8801 &hdd_channels_2_4_ghz[0],
8802 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +05308803 if ((hdd_is_5g_supported(pHddCtx)) &&
8804 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
8805 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
8806 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
8807 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008808 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
Abhishek Singhf512bf32016-05-04 16:47:46 +05308809 wiphy->bands[IEEE80211_BAND_5GHZ]->channels =
8810 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
8811 if (wiphy->bands[IEEE80211_BAND_5GHZ]->channels == NULL) {
8812 hdd_err("Not enough memory to allocate channels");
8813 qdf_mem_free(wiphy->
8814 bands[IEEE80211_BAND_2GHZ]->channels);
8815 wiphy->bands[IEEE80211_BAND_2GHZ]->channels = NULL;
8816 return -ENOMEM;
8817 }
8818 qdf_mem_copy(wiphy->bands[IEEE80211_BAND_5GHZ]->channels,
8819 &hdd_channels_5_ghz[0],
8820 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008821 }
8822
8823 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8824
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008825 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008826 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008827
8828 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8829 struct ieee80211_supported_band *band = wiphy->bands[i];
8830
8831 if (IEEE80211_BAND_2GHZ == i &&
8832 eCSR_BAND_5G == pCfg->nBandCapability) {
8833 /* 5G only */
8834#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8835 /* Enable social channels for P2P */
8836 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8837 (band->channels[j].center_freq))
8838 band->channels[j].flags &=
8839 ~IEEE80211_CHAN_DISABLED;
8840 else
8841#endif
8842 band->channels[j].flags |=
8843 IEEE80211_CHAN_DISABLED;
8844 continue;
8845 } else if (IEEE80211_BAND_5GHZ == i &&
8846 eCSR_BAND_24 == pCfg->nBandCapability) {
8847 /* 2G only */
8848 band->channels[j].flags |=
8849 IEEE80211_CHAN_DISABLED;
8850 continue;
8851 }
8852 }
8853 }
8854 /*Initialise the supported cipher suite details */
8855 wiphy->cipher_suites = hdd_cipher_suites;
8856 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
8857
8858 /*signal strength in mBm (100*dBm) */
8859 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
8860 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
8861
Anurag Chouhan6d760662016-02-20 16:05:43 +05308862 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008863 wiphy->n_vendor_commands =
8864 ARRAY_SIZE(hdd_wiphy_vendor_commands);
8865 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
8866
8867 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
8868 wiphy->n_vendor_events =
8869 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
8870 }
8871
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008872 if (pCfg->enableDFSMasterCap) {
8873 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
8874 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008875
8876 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8877
8878#ifdef QCA_HT_2040_COEX
8879 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
8880#endif
8881
Abhishek Singh1bdb1572015-10-16 16:24:19 +05308882 hdd_add_channel_switch_support(&wiphy->flags);
8883
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008884 EXIT();
8885 return 0;
8886}
8887
Abhishek Singhf512bf32016-05-04 16:47:46 +05308888/**
8889 * wlan_hdd_cfg80211_deinit - Deinit cfg80211
8890 * @ wiphy: the wiphy to validate against
8891 *
8892 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308893 * memory allocated in wlan_hdd_cfg80211_init also
8894 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +05308895 *
8896 * Return: void
8897 */
8898void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
8899{
8900 int i;
8901
8902 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8903 if (NULL != wiphy->bands[i] &&
8904 (NULL != wiphy->bands[i]->channels)) {
8905 qdf_mem_free(wiphy->bands[i]->channels);
8906 wiphy->bands[i]->channels = NULL;
8907 }
8908 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308909 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +05308910}
8911
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008912/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308913 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008914 * initialization. In wlan_hdd_cfg80211_init, only the
8915 * default values will be initialized. The final initialization
8916 * of all required members can be done here.
8917 */
8918void wlan_hdd_update_wiphy(struct wiphy *wiphy, struct hdd_config *pCfg)
8919{
8920 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8921}
8922
8923/* In this function we are registering wiphy. */
8924int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
8925{
8926 ENTER();
8927 /* Register our wiphy dev with cfg80211 */
8928 if (0 > wiphy_register(wiphy)) {
8929 /* print error */
Jeff Johnson77848112016-06-29 14:52:06 -07008930 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008931 return -EIO;
8932 }
8933
8934 EXIT();
8935 return 0;
8936}
8937
8938/*
8939 HDD function to update wiphy capability based on target offload status.
8940
8941 wlan_hdd_cfg80211_init() does initialization of all wiphy related
8942 capability even before downloading firmware to the target. In discrete
8943 case, host will get know certain offload capability (say sched_scan
8944 caps) only after downloading firmware to the target and target boots up.
8945 This function is used to override setting done in wlan_hdd_cfg80211_init()
8946 based on target capability.
8947 */
8948void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
8949{
8950#ifdef FEATURE_WLAN_SCAN_PNO
8951 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8952 struct hdd_config *pCfg = pHddCtx->config;
8953
8954 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
8955 * control comes here. Here just we need to clear it if firmware doesn't
8956 * have PNO support. */
8957 if (!pCfg->PnoOffload) {
8958 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8959 wiphy->max_sched_scan_ssids = 0;
8960 wiphy->max_match_sets = 0;
8961 wiphy->max_sched_scan_ie_len = 0;
8962 }
8963#endif
8964}
8965
8966/* This function registers for all frame which supplicant is interested in */
8967void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
8968{
8969 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8970 /* Register for all P2P action, public action etc frames */
8971 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
8972
8973 ENTER();
8974
Abhishek Singh7996eb72015-12-30 17:24:02 +05308975 /* Register frame indication call back */
8976 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
8977
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +05308978 /* Register for p2p ack indication */
8979 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
8980
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008981 /* Right now we are registering these frame when driver is getting
8982 initialized. Once we will move to 2.6.37 kernel, in which we have
8983 frame register ops, we will move this code as a part of that */
8984 /* GAS Initial Request */
8985 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8986 (uint8_t *) GAS_INITIAL_REQ,
8987 GAS_INITIAL_REQ_SIZE);
8988
8989 /* GAS Initial Response */
8990 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8991 (uint8_t *) GAS_INITIAL_RSP,
8992 GAS_INITIAL_RSP_SIZE);
8993
8994 /* GAS Comeback Request */
8995 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8996 (uint8_t *) GAS_COMEBACK_REQ,
8997 GAS_COMEBACK_REQ_SIZE);
8998
8999 /* GAS Comeback Response */
9000 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9001 (uint8_t *) GAS_COMEBACK_RSP,
9002 GAS_COMEBACK_RSP_SIZE);
9003
9004 /* P2P Public Action */
9005 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9006 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9007 P2P_PUBLIC_ACTION_FRAME_SIZE);
9008
9009 /* P2P Action */
9010 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9011 (uint8_t *) P2P_ACTION_FRAME,
9012 P2P_ACTION_FRAME_SIZE);
9013
9014 /* WNM BSS Transition Request frame */
9015 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9016 (uint8_t *) WNM_BSS_ACTION_FRAME,
9017 WNM_BSS_ACTION_FRAME_SIZE);
9018
9019 /* WNM-Notification */
9020 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
9021 (uint8_t *) WNM_NOTIFICATION_FRAME,
9022 WNM_NOTIFICATION_FRAME_SIZE);
9023}
9024
9025void wlan_hdd_cfg80211_deregister_frames(hdd_adapter_t *pAdapter)
9026{
9027 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9028 /* Register for all P2P action, public action etc frames */
9029 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
9030
9031 ENTER();
9032
9033 /* Right now we are registering these frame when driver is getting
9034 initialized. Once we will move to 2.6.37 kernel, in which we have
9035 frame register ops, we will move this code as a part of that */
9036 /* GAS Initial Request */
9037
9038 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9039 (uint8_t *) GAS_INITIAL_REQ,
9040 GAS_INITIAL_REQ_SIZE);
9041
9042 /* GAS Initial Response */
9043 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9044 (uint8_t *) GAS_INITIAL_RSP,
9045 GAS_INITIAL_RSP_SIZE);
9046
9047 /* GAS Comeback Request */
9048 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9049 (uint8_t *) GAS_COMEBACK_REQ,
9050 GAS_COMEBACK_REQ_SIZE);
9051
9052 /* GAS Comeback Response */
9053 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9054 (uint8_t *) GAS_COMEBACK_RSP,
9055 GAS_COMEBACK_RSP_SIZE);
9056
9057 /* P2P Public Action */
9058 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9059 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9060 P2P_PUBLIC_ACTION_FRAME_SIZE);
9061
9062 /* P2P Action */
9063 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9064 (uint8_t *) P2P_ACTION_FRAME,
9065 P2P_ACTION_FRAME_SIZE);
9066
9067 /* WNM-Notification */
9068 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
9069 (uint8_t *) WNM_NOTIFICATION_FRAME,
9070 WNM_NOTIFICATION_FRAME_SIZE);
9071}
9072
9073#ifdef FEATURE_WLAN_WAPI
9074void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
9075 const uint8_t *mac_addr, const uint8_t *key,
9076 int key_Len)
9077{
9078 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9079 tCsrRoamSetKey setKey;
9080 bool isConnected = true;
9081 int status = 0;
9082 uint32_t roamId = 0xFF;
9083 uint8_t *pKeyPtr = NULL;
9084 int n = 0;
9085
Jeff Johnson46b40792016-06-29 14:03:14 -07009086 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009087 hdd_device_mode_to_string(pAdapter->device_mode),
9088 pAdapter->device_mode);
9089
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309090 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009091 setKey.keyId = key_index; /* Store Key ID */
9092 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
9093 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
9094 setKey.paeRole = 0; /* the PAE role */
9095 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05309096 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009097 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309098 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009099 }
9100 setKey.keyLength = key_Len;
9101 pKeyPtr = setKey.Key;
9102 memcpy(pKeyPtr, key, key_Len);
9103
Jeff Johnson46b40792016-06-29 14:03:14 -07009104 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009105 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -07009106 hdd_notice("WAPI KEY Data[%d]:%02x ",
9107 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009108
9109 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
9110 if (isConnected) {
9111 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9112 pAdapter->sessionId, &setKey, &roamId);
9113 }
9114 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -07009115 hdd_err("sme_roam_set_key returned ERROR status= %d",
9116 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009117 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
9118 }
9119}
9120#endif /* FEATURE_WLAN_WAPI */
9121
9122uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
9123 uint8_t eid)
9124{
9125 int left = length;
9126 uint8_t *ptr = (uint8_t *)ies_ptr;
9127 uint8_t elem_id, elem_len;
9128
9129 while (left >= 2) {
9130 elem_id = ptr[0];
9131 elem_len = ptr[1];
9132 left -= 2;
9133 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -07009134 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009135 eid, elem_len, left);
9136 return NULL;
9137 }
9138 if (elem_id == eid) {
9139 return ptr;
9140 }
9141
9142 left -= elem_len;
9143 ptr += (elem_len + 2);
9144 }
9145 return NULL;
9146}
9147
9148/*
9149 * FUNCTION: wlan_hdd_validate_operation_channel
9150 * called by wlan_hdd_cfg80211_start_bss() and
9151 * wlan_hdd_set_channel()
9152 * This function validates whether given channel is part of valid
9153 * channel list.
9154 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309155QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009156 int channel)
9157{
9158
9159 uint32_t num_ch = 0;
9160 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
9161 u32 indx = 0;
9162 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9163 uint8_t fValidChannel = false, count = 0;
9164 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
9165
9166 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
9167
9168 if (hdd_pConfig_ini->sapAllowAllChannel) {
9169 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -08009170 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07009171 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009172 fValidChannel = true;
9173 break;
9174 }
9175 }
9176 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -07009177 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309178 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009179 }
9180 } else {
9181 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
9182 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009183 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309184 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009185 }
9186 for (indx = 0; indx < num_ch; indx++) {
9187 if (channel == valid_ch[indx]) {
9188 break;
9189 }
9190 }
9191
9192 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -07009193 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309194 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009195 }
9196 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309197 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009198
9199}
9200
9201#ifdef DHCP_SERVER_OFFLOAD
9202static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
9203{
9204 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
9205 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
9206 uint8_t numEntries = 0;
9207 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
9208 uint8_t num;
9209 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309210 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009211 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -07009212 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009213 return;
9214 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309215 qdf_mem_zero(pDhcpSrvInfo, sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009216 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
9217 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
9218 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
9219 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
9220 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
9221 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -07009222 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009223 goto end;
9224 }
9225 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009226 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009227 goto end;
9228 }
9229 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -07009230 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009231 goto end;
9232 }
9233 for (num = 0; num < numEntries; num++) {
9234 temp = srv_ip[num];
9235 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
9236 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309237 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009238 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009239 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009240 goto end;
9241 }
Jeff Johnson77848112016-06-29 14:52:06 -07009242 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009243end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309244 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009245 return;
9246}
9247#endif /* DHCP_SERVER_OFFLOAD */
9248
9249static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9250 struct net_device *dev,
9251 struct bss_parameters *params)
9252{
9253 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9254 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9255 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309256 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009257
9258 ENTER();
9259
Anurag Chouhan6d760662016-02-20 16:05:43 +05309260 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009261 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009262 return -EINVAL;
9263 }
9264
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309265 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009266 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
9267 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -07009268 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009269 hdd_device_mode_to_string(pAdapter->device_mode),
9270 pAdapter->device_mode, params->ap_isolate);
9271
9272 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9273 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309274 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009275 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009276
Krunal Sonib4326f22016-03-10 13:05:51 -08009277 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
9278 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009279 return -EOPNOTSUPP;
9280 }
9281
9282 /* ap_isolate == -1 means that in change bss, upper layer doesn't
9283 * want to update this parameter */
9284 if (-1 != params->ap_isolate) {
9285 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
9286 !!params->ap_isolate;
9287
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309288 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009289 pAdapter->sessionId,
9290 pAdapter->sessionCtx.
9291 ap.
9292 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309293 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009294 ret = -EINVAL;
9295 }
9296 }
9297
9298 EXIT();
9299 return ret;
9300}
9301
Krunal Soni8c37e322016-02-03 16:08:37 -08009302/**
9303 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
9304 * @ndev: pointer to net device provided by supplicant
9305 * @type: type of the interface, upper layer wanted to change
9306 *
9307 * Upper layer provides the new interface mode that needs to be changed
9308 * for given net device
9309 *
9310 * Return: success or failure in terms of integer value
9311 */
9312static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009313 enum nl80211_iftype type)
9314{
Krunal Soni8c37e322016-02-03 16:08:37 -08009315 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9316 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9317 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009318 hdd_wext_state_t *wext;
9319 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309320 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009321
9322 ENTER();
9323
Krunal Soni8c37e322016-02-03 16:08:37 -08009324 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009325 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009326 return 0;
9327 }
9328
9329 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -08009330 hdd_stop_adapter(hdd_ctx, adapter, true);
9331 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009332 wdev->iftype = type;
9333 /*Check for sub-string p2p to confirm its a p2p interface */
9334 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -08009335 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009336 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009337 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -08009338 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -08009339 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009340 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -08009341 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009342 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009343 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009344 }
Krunal Soni8c37e322016-02-03 16:08:37 -08009345 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
9346 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -08009347 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
9348 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009349 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -08009350 adapter->scan_info.scanAddIE.length;
9351 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309352 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -08009353 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
9354 wext->roamProfile.phyMode =
9355 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
9356 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009357 EXIT();
9358 return status;
9359}
9360
9361static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9362 struct net_device *dev,
9363 struct bss_parameters *params)
9364{
9365 int ret;
9366
9367 cds_ssr_protect(__func__);
9368 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
9369 cds_ssr_unprotect(__func__);
9370
9371 return ret;
9372}
9373
9374/* FUNCTION: wlan_hdd_change_country_code_cd
9375 * to wait for contry code completion
9376 */
9377void *wlan_hdd_change_country_code_cb(void *pAdapter)
9378{
9379 hdd_adapter_t *call_back_pAdapter = pAdapter;
9380 complete(&call_back_pAdapter->change_country_code);
9381 return NULL;
9382}
9383
Rajeev Kumar98edb772016-01-19 12:42:19 -08009384/**
9385 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9386 * @wiphy: Pointer to the wiphy structure
9387 * @ndev: Pointer to the net device
9388 * @type: Interface type
9389 * @flags: Flags for change interface
9390 * @params: Pointer to change interface parameters
9391 *
9392 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009393 */
9394static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9395 struct net_device *ndev,
9396 enum nl80211_iftype type,
9397 u32 *flags,
9398 struct vif_params *params)
9399{
9400 struct wireless_dev *wdev;
9401 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9402 hdd_context_t *pHddCtx;
9403 tCsrRoamProfile *pRoamProfile = NULL;
9404 eCsrRoamBssType LastBSSType;
9405 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309406 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009407 int status;
9408
9409 ENTER();
9410
Anurag Chouhan6d760662016-02-20 16:05:43 +05309411 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009412 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009413 return -EINVAL;
9414 }
9415
9416 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9417 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309418 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009419 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009420
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309421 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009422 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
9423 pAdapter->sessionId, type));
9424
Jeff Johnson77848112016-06-29 14:52:06 -07009425 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009426 pAdapter->device_mode, type);
9427
Arun Khandavallifae92942016-08-01 13:31:08 +05309428 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
9429 if (status) {
9430 hdd_err("Failed to start modules");
9431 return -EINVAL;
9432 }
9433
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009434 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009435 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
9436 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009437 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009438 return -EINVAL;
9439 }
9440
9441 pConfig = pHddCtx->config;
9442 wdev = ndev->ieee80211_ptr;
9443
9444 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009445 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009446
9447 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
9448
Krunal Sonib4326f22016-03-10 13:05:51 -08009449 if ((pAdapter->device_mode == QDF_STA_MODE) ||
9450 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
9451 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
9452 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009453 hdd_wext_state_t *pWextState =
9454 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9455
9456 pRoamProfile = &pWextState->roamProfile;
9457 LastBSSType = pRoamProfile->BSSType;
9458
9459 switch (type) {
9460 case NL80211_IFTYPE_STATION:
9461 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -08009462 case NL80211_IFTYPE_ADHOC:
9463 if (type == NL80211_IFTYPE_ADHOC) {
9464 wlan_hdd_tdls_exit(pAdapter);
9465 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -07009466 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -08009467 }
9468 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
9469 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309470 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009471 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309472 if (hdd_start_adapter(pAdapter)) {
9473 hdd_err("Failed to start adapter :%d",
9474 pAdapter->device_mode);
9475 return -EINVAL;
9476 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009477 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009478 case NL80211_IFTYPE_AP:
9479 case NL80211_IFTYPE_P2P_GO:
9480 {
Jeff Johnson77848112016-06-29 14:52:06 -07009481 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009482 (type ==
9483 NL80211_IFTYPE_AP) ? "SoftAP" :
9484 "P2pGo");
9485
9486 /* Cancel any remain on channel for GO mode */
9487 if (NL80211_IFTYPE_P2P_GO == type) {
9488 wlan_hdd_cancel_existing_remain_on_channel
9489 (pAdapter);
9490 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009491
Arun Khandavallifae92942016-08-01 13:31:08 +05309492 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009493 /* De-init the adapter */
9494 hdd_deinit_adapter(pHddCtx, pAdapter, true);
9495 memset(&pAdapter->sessionCtx, 0,
9496 sizeof(pAdapter->sessionCtx));
9497 pAdapter->device_mode =
9498 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -08009499 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
9500 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009501
9502 /*
9503 * Fw will take care incase of concurrency
9504 */
9505
Krunal Sonib4326f22016-03-10 13:05:51 -08009506 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009507 && (pConfig->apRandomBssidEnabled)) {
9508 /* To meet Android requirements create a randomized
9509 MAC address of the form 02:1A:11:Fx:xx:xx */
9510 get_random_bytes(&ndev->dev_addr[3], 3);
9511 ndev->dev_addr[0] = 0x02;
9512 ndev->dev_addr[1] = 0x1A;
9513 ndev->dev_addr[2] = 0x11;
9514 ndev->dev_addr[3] |= 0xF0;
9515 memcpy(pAdapter->macAddressCurrent.
9516 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309517 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009518 pr_info("wlan: Generated HotSpot BSSID "
9519 MAC_ADDRESS_STR "\n",
9520 MAC_ADDR_ARRAY(ndev->dev_addr));
9521 }
9522
9523 hdd_set_ap_ops(pAdapter->dev);
9524
Arun Khandavallifae92942016-08-01 13:31:08 +05309525 if (hdd_start_adapter(pAdapter)) {
9526 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009527 return -EINVAL;
9528 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009529 /* Interface type changed update in wiphy structure */
9530 if (wdev) {
9531 wdev->iftype = type;
9532 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009533 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009534 return -EINVAL;
9535 }
9536 goto done;
9537 }
9538
9539 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009540 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009541 type);
9542 return -EOPNOTSUPP;
9543 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009544 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9545 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009546 switch (type) {
9547 case NL80211_IFTYPE_STATION:
9548 case NL80211_IFTYPE_P2P_CLIENT:
9549 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -08009550 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
9551 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309552 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009553 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309554 if (hdd_start_adapter(pAdapter)) {
9555 hdd_err("Failed to start adapter :%d",
9556 pAdapter->device_mode);
9557 return -EINVAL;
9558 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009559 goto done;
9560
9561 case NL80211_IFTYPE_AP:
9562 case NL80211_IFTYPE_P2P_GO:
9563 wdev->iftype = type;
9564 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009565 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009566 goto done;
9567
9568 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009569 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009570 type);
9571 return -EOPNOTSUPP;
9572 }
9573 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009574 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009575 pAdapter->device_mode);
9576 return -EOPNOTSUPP;
9577 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009578done:
9579 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009580 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009581
Jeff Johnson2ae6f712016-09-23 15:08:48 -07009582 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009583
9584 EXIT();
9585 return 0;
9586}
9587
Rajeev Kumar98edb772016-01-19 12:42:19 -08009588/**
9589 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9590 * @wiphy: Pointer to the wiphy structure
9591 * @ndev: Pointer to the net device
9592 * @type: Interface type
9593 * @flags: Flags for change interface
9594 * @params: Pointer to change interface parameters
9595 *
9596 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009597 */
9598static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9599 struct net_device *ndev,
9600 enum nl80211_iftype type,
9601 u32 *flags,
9602 struct vif_params *params)
9603{
9604 int ret;
9605
9606 cds_ssr_protect(__func__);
9607 ret =
9608 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
9609 cds_ssr_unprotect(__func__);
9610
9611 return ret;
9612}
9613
9614#ifdef FEATURE_WLAN_TDLS
9615static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
9616 int index, uint8_t match)
9617{
9618 int i;
9619 for (i = 0; i < index; i++) {
9620 if (arr[i] == match)
9621 return true;
9622 }
9623 return false;
9624}
9625#endif
9626
9627/**
9628 * __wlan_hdd_change_station() - change station
9629 * @wiphy: Pointer to the wiphy structure
9630 * @dev: Pointer to the net device.
9631 * @mac: bssid
9632 * @params: Pointer to station parameters
9633 *
9634 * Return: 0 for success, error number on failure.
9635 */
9636#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9637static int __wlan_hdd_change_station(struct wiphy *wiphy,
9638 struct net_device *dev,
9639 const uint8_t *mac,
9640 struct station_parameters *params)
9641#else
9642static int __wlan_hdd_change_station(struct wiphy *wiphy,
9643 struct net_device *dev,
9644 uint8_t *mac,
9645 struct station_parameters *params)
9646#endif
9647{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309648 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009649 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9650 hdd_context_t *pHddCtx;
9651 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +05309652 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009653#ifdef FEATURE_WLAN_TDLS
9654 tCsrStaParams StaParams = { 0 };
9655 uint8_t isBufSta = 0;
9656 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +05309657 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009658#endif
9659 int ret;
9660
9661 ENTER();
9662
Anurag Chouhan6d760662016-02-20 16:05:43 +05309663 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009664 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009665 return -EINVAL;
9666 }
9667
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309668 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009669 TRACE_CODE_HDD_CHANGE_STATION,
9670 pAdapter->sessionId, params->listen_interval));
9671
9672 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9673 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309674 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009675 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009676
9677 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9678
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309679 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009680
Krunal Sonib4326f22016-03-10 13:05:51 -08009681 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9682 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009683 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
9684 status =
9685 hdd_softap_change_sta_state(pAdapter,
9686 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -08009687 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009688
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309689 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009690 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009691 return -EINVAL;
9692 }
9693 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009694 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
9695 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009696#ifdef FEATURE_WLAN_TDLS
9697 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -07009698
9699 if (cds_is_sub_20_mhz_enabled()) {
9700 hdd_err("TDLS not allowed with sub 20 MHz");
9701 return -EINVAL;
9702 }
9703
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009704 StaParams.capability = params->capability;
9705 StaParams.uapsd_queues = params->uapsd_queues;
9706 StaParams.max_sp = params->max_sp;
9707
9708 /* Convert (first channel , number of channels) tuple to
9709 * the total list of channels. This goes with the assumption
9710 * that if the first channel is < 14, then the next channels
9711 * are an incremental of 1 else an incremental of 4 till the number
9712 * of channels.
9713 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009714 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009715 if (0 != params->supported_channels_len) {
9716 int i = 0, j = 0, k = 0, no_of_channels = 0;
9717 int num_unique_channels;
9718 int next;
9719 for (i = 0;
9720 i < params->supported_channels_len
9721 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
9722 int wifi_chan_index;
9723 if (!wlan_hdd_is_duplicate_channel
9724 (StaParams.supported_channels, j,
9725 params->supported_channels[i])) {
9726 StaParams.
9727 supported_channels[j] =
9728 params->
9729 supported_channels[i];
9730 } else {
9731 continue;
9732 }
9733 wifi_chan_index =
9734 ((StaParams.supported_channels[j] <=
9735 HDD_CHANNEL_14) ? 1 : 4);
9736 no_of_channels =
9737 params->supported_channels[i + 1];
9738
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009739 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 -08009740 StaParams.
9741 supported_channels[j],
9742 wifi_chan_index,
9743 no_of_channels);
9744 for (k = 1; k <= no_of_channels &&
9745 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
9746 k++) {
9747 next =
9748 StaParams.
9749 supported_channels[j] +
9750 wifi_chan_index;
9751 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
9752 StaParams.
9753 supported_channels[j
9754 +
9755 1]
9756 = next;
9757 } else {
9758 continue;
9759 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009760 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009761 j + 1,
9762 StaParams.
9763 supported_channels[j +
9764 1]);
9765 j += 1;
9766 }
9767 }
9768 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009769 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009770 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009771 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009772 StaParams.
9773 supported_channels[i]);
9774 }
9775 if (MAX_CHANNEL < num_unique_channels)
9776 num_unique_channels = MAX_CHANNEL;
9777 StaParams.supported_channels_len =
9778 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009779 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009780 StaParams.supported_channels_len);
9781 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309782 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009783 params->supported_oper_classes,
9784 params->supported_oper_classes_len);
9785 StaParams.supported_oper_classes_len =
9786 params->supported_oper_classes_len;
9787
9788 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309789 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009790 params->ext_capab,
9791 sizeof(StaParams.extn_capability));
9792
9793 if (NULL != params->ht_capa) {
9794 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309795 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009796 sizeof(tSirHTCap));
9797 }
9798
9799 StaParams.supported_rates_len =
9800 params->supported_rates_len;
9801
9802 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
9803 * The supported_rates array , for all the structures propogating till Add Sta
9804 * to the firmware has to be modified , if the supplicant (ieee80211) is
9805 * modified to send more rates.
9806 */
9807
9808 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
9809 */
9810 if (StaParams.supported_rates_len >
9811 SIR_MAC_MAX_SUPP_RATES)
9812 StaParams.supported_rates_len =
9813 SIR_MAC_MAX_SUPP_RATES;
9814
9815 if (0 != StaParams.supported_rates_len) {
9816 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309817 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009818 params->supported_rates,
9819 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009820 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009821 StaParams.supported_rates_len);
9822 for (i = 0; i < StaParams.supported_rates_len;
9823 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009824 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009825 StaParams.supported_rates[i]);
9826 }
9827
9828 if (NULL != params->vht_capa) {
9829 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309830 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009831 params->vht_capa,
9832 sizeof(tSirVHTCap));
9833 }
9834
9835 if (0 != params->ext_capab_len) {
9836 /*Define A Macro : TODO Sunil */
9837 if ((1 << 4) & StaParams.extn_capability[3]) {
9838 isBufSta = 1;
9839 }
9840 /* TDLS Channel Switching Support */
9841 if ((1 << 6) & StaParams.extn_capability[3]) {
9842 isOffChannelSupported = 1;
9843 }
9844 }
9845
Nitesh Shah99934ac2016-09-05 15:54:08 +05309846 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +05309847 (params->ht_capa || params->vht_capa ||
9848 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +05309849 is_qos_wmm_sta = true;
9850
9851 hdd_notice("%s: TDLS Peer is QOS capable"
9852 " is_qos_wmm_sta= %d HTcapPresent = %d",
9853 __func__, is_qos_wmm_sta,
9854 StaParams.htcap_present);
9855
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009856 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +05309857 &StaParams,
9858 isBufSta,
9859 isOffChannelSupported,
9860 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309861 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009862 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009863 return -EINVAL;
9864 }
9865
9866 status =
9867 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
9868 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309869 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009870 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009871 return -EINVAL;
9872 }
9873 }
9874#endif
9875 }
9876 EXIT();
9877 return ret;
9878}
9879
9880/**
9881 * wlan_hdd_change_station() - cfg80211 change station handler function
9882 * @wiphy: Pointer to the wiphy structure
9883 * @dev: Pointer to the net device.
9884 * @mac: bssid
9885 * @params: Pointer to station parameters
9886 *
9887 * This is the cfg80211 change station handler function which invokes
9888 * the internal function @__wlan_hdd_change_station with
9889 * SSR protection.
9890 *
9891 * Return: 0 for success, error number on failure.
9892 */
9893#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
9894static int wlan_hdd_change_station(struct wiphy *wiphy,
9895 struct net_device *dev,
9896 const u8 *mac,
9897 struct station_parameters *params)
9898#else
9899static int wlan_hdd_change_station(struct wiphy *wiphy,
9900 struct net_device *dev,
9901 u8 *mac,
9902 struct station_parameters *params)
9903#endif
9904{
9905 int ret;
9906
9907 cds_ssr_protect(__func__);
9908 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
9909 cds_ssr_unprotect(__func__);
9910
9911 return ret;
9912}
9913
9914/*
9915 * FUNCTION: __wlan_hdd_cfg80211_add_key
9916 * This function is used to initialize the key information
9917 */
9918static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
9919 struct net_device *ndev,
9920 u8 key_index, bool pairwise,
9921 const u8 *mac_addr,
9922 struct key_params *params)
9923{
9924 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9925 tCsrRoamSetKey setKey;
9926 int status;
9927 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009928 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309929 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009930 hdd_context_t *pHddCtx;
9931 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
9932
9933 ENTER();
9934
Anurag Chouhan6d760662016-02-20 16:05:43 +05309935 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009936 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009937 return -EINVAL;
9938 }
9939
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309940 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009941 TRACE_CODE_HDD_CFG80211_ADD_KEY,
9942 pAdapter->sessionId, params->key_len));
9943 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9944 status = wlan_hdd_validate_context(pHddCtx);
9945
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309946 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009947 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009948
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009949 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009950 hdd_device_mode_to_string(pAdapter->device_mode),
9951 pAdapter->device_mode);
9952
9953 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009954 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009955
9956 return -EINVAL;
9957 }
9958
9959 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009960 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009961
9962 return -EINVAL;
9963 }
9964
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009965 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009966
9967 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309968 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009969 setKey.keyId = key_index;
9970 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309971 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009972
9973 switch (params->cipher) {
9974 case WLAN_CIPHER_SUITE_WEP40:
9975 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
9976 break;
9977
9978 case WLAN_CIPHER_SUITE_WEP104:
9979 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
9980 break;
9981
9982 case WLAN_CIPHER_SUITE_TKIP:
9983 {
9984 u8 *pKey = &setKey.Key[0];
9985 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
9986
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309987 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009988
9989 /*Supplicant sends the 32bytes key in this order
9990
9991 |--------------|----------|----------|
9992 | Tk1 |TX-MIC | RX Mic |
9993 |||--------------|----------|----------|
9994 <---16bytes---><--8bytes--><--8bytes-->
9995
9996 */
9997 /*Sme expects the 32 bytes key to be in the below order
9998
9999 |--------------|----------|----------|
10000 | Tk1 |RX-MIC | TX Mic |
10001 |||--------------|----------|----------|
10002 <---16bytes---><--8bytes--><--8bytes-->
10003 */
10004 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010005 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010006
10007 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010008 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010009
10010 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010011 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010012
10013 break;
10014 }
10015
10016 case WLAN_CIPHER_SUITE_CCMP:
10017 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
10018 break;
10019
10020#ifdef FEATURE_WLAN_WAPI
10021 case WLAN_CIPHER_SUITE_SMS4:
10022 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010023 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010024 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
10025 mac_addr, params->key,
10026 params->key_len);
10027 return 0;
10028 }
10029#endif
10030
10031#ifdef FEATURE_WLAN_ESE
10032 case WLAN_CIPHER_SUITE_KRK:
10033 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
10034 break;
10035#ifdef WLAN_FEATURE_ROAM_OFFLOAD
10036 case WLAN_CIPHER_SUITE_BTK:
10037 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
10038 break;
10039#endif
10040#endif
10041
10042#ifdef WLAN_FEATURE_11W
10043 case WLAN_CIPHER_SUITE_AES_CMAC:
10044 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
10045 break;
10046#endif
10047
10048 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010049 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010050 return -EOPNOTSUPP;
10051 }
10052
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010053 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010054
10055 if (!pairwise) {
10056 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010057 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010058 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010059 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010060 } else {
10061 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010062 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010063 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010064 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010065 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010066 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010067 /* if a key is already installed, block all subsequent ones */
10068 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010069 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010070 return 0;
10071 }
10072
10073 setKey.keyDirection = eSIR_TX_RX;
10074 /*Set the group key */
10075 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10076 pAdapter->sessionId, &setKey, &roamId);
10077
10078 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010079 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010080 return -EINVAL;
10081 }
10082 /*Save the keys here and call sme_roam_set_key for setting
10083 the PTK after peer joins the IBSS network */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010084 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010085 &setKey, sizeof(tCsrRoamSetKey));
10086
10087 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
10088 return status;
10089 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010090 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10091 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010092 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10093 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070010094 status = wlansap_set_key_sta(
10095 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010096 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010097 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010098 __LINE__, status);
10099 }
10100 }
10101
10102 /* Save the key in ap ctx for use on START_BASS and restart */
10103 if (pairwise ||
10104 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
10105 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010106 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010107 sizeof(tCsrRoamSetKey));
10108 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010109 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010110 sizeof(tCsrRoamSetKey));
10111
Krunal Sonib4326f22016-03-10 13:05:51 -080010112 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
10113 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010114 hdd_wext_state_t *pWextState =
10115 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10116 hdd_station_ctx_t *pHddStaCtx =
10117 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10118
10119 if (!pairwise) {
10120 /* set group key */
10121 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010122 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010123 __func__, __LINE__);
10124 hdd_perform_roam_set_key_complete(pAdapter);
10125 }
10126 }
10127
10128 pWextState->roamProfile.Keys.KeyLength[key_index] =
10129 (u8) params->key_len;
10130
10131 pWextState->roamProfile.Keys.defaultIndex = key_index;
10132
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010133 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010134 KeyMaterial[key_index][0], params->key,
10135 params->key_len);
10136
10137 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10138
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010139 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010140 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10141 setKey.keyDirection);
10142
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010143 /* The supplicant may attempt to set the PTK once pre-authentication
10144 is done. Save the key in the UMAC and include it in the ADD BSS
10145 request */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010146 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010147 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010148 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010149 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010150 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010151 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010152 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010153 return -EINVAL;
10154 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010155
10156 /* issue set key request to SME */
10157 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10158 pAdapter->sessionId, &setKey, &roamId);
10159
10160 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010161 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010162 pHddStaCtx->roam_info.roamingState =
10163 HDD_ROAM_STATE_NONE;
10164 return -EINVAL;
10165 }
10166
10167 /* in case of IBSS as there was no information available about WEP keys during
10168 * IBSS join, group key intialized with NULL key, so re-initialize group key
10169 * with correct value*/
10170 if ((eCSR_BSS_TYPE_START_IBSS ==
10171 pWextState->roamProfile.BSSType)
10172 &&
10173 !((IW_AUTH_KEY_MGMT_802_1X ==
10174 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
10175 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
10176 pHddStaCtx->conn_info.authType)
10177 )
10178 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
10179 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
10180 )
10181 ) {
10182 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010183 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010184
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010185 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010186 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10187 setKey.keyDirection);
10188
10189 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10190 pAdapter->sessionId, &setKey,
10191 &roamId);
10192
10193 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010194 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010195 pHddStaCtx->roam_info.roamingState =
10196 HDD_ROAM_STATE_NONE;
10197 return -EINVAL;
10198 }
10199 }
10200 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010201 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010202 return 0;
10203}
10204
10205static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10206 struct net_device *ndev,
10207 u8 key_index, bool pairwise,
10208 const u8 *mac_addr,
10209 struct key_params *params)
10210{
10211 int ret;
10212 cds_ssr_protect(__func__);
10213 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
10214 mac_addr, params);
10215 cds_ssr_unprotect(__func__);
10216
10217 return ret;
10218}
10219
10220/*
10221 * FUNCTION: __wlan_hdd_cfg80211_get_key
10222 * This function is used to get the key information
10223 */
10224static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10225 struct net_device *ndev,
10226 u8 key_index, bool pairwise,
10227 const u8 *mac_addr, void *cookie,
10228 void (*callback)(void *cookie,
10229 struct key_params *)
10230 )
10231{
10232 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10233 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10234 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
10235 struct key_params params;
10236
10237 ENTER();
10238
Anurag Chouhan6d760662016-02-20 16:05:43 +053010239 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010240 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010241 return -EINVAL;
10242 }
10243
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010244 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010245 hdd_device_mode_to_string(pAdapter->device_mode),
10246 pAdapter->device_mode);
10247
10248 memset(&params, 0, sizeof(params));
10249
10250 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010251 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010252 key_index);
10253 return -EINVAL;
10254 }
10255
10256 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
10257 case eCSR_ENCRYPT_TYPE_NONE:
10258 params.cipher = IW_AUTH_CIPHER_NONE;
10259 break;
10260
10261 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
10262 case eCSR_ENCRYPT_TYPE_WEP40:
10263 params.cipher = WLAN_CIPHER_SUITE_WEP40;
10264 break;
10265
10266 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
10267 case eCSR_ENCRYPT_TYPE_WEP104:
10268 params.cipher = WLAN_CIPHER_SUITE_WEP104;
10269 break;
10270
10271 case eCSR_ENCRYPT_TYPE_TKIP:
10272 params.cipher = WLAN_CIPHER_SUITE_TKIP;
10273 break;
10274
10275 case eCSR_ENCRYPT_TYPE_AES:
10276 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
10277 break;
10278
10279 default:
10280 params.cipher = IW_AUTH_CIPHER_NONE;
10281 break;
10282 }
10283
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010284 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010285 TRACE_CODE_HDD_CFG80211_GET_KEY,
10286 pAdapter->sessionId, params.cipher));
10287
10288 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
10289 params.seq_len = 0;
10290 params.seq = NULL;
10291 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
10292 callback(cookie, &params);
10293
10294 EXIT();
10295 return 0;
10296}
10297
10298static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10299 struct net_device *ndev,
10300 u8 key_index, bool pairwise,
10301 const u8 *mac_addr, void *cookie,
10302 void (*callback)(void *cookie,
10303 struct key_params *)
10304 )
10305{
10306 int ret;
10307
10308 cds_ssr_protect(__func__);
10309 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
10310 mac_addr, cookie, callback);
10311 cds_ssr_unprotect(__func__);
10312
10313 return ret;
10314}
10315
10316/**
10317 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
10318 * @wiphy: wiphy interface context
10319 * @ndev: pointer to net device
10320 * @key_index: Key index used in 802.11 frames
10321 * @unicast: true if it is unicast key
10322 * @multicast: true if it is multicast key
10323 *
10324 * This function is required for cfg80211_ops API.
10325 * It is used to delete the key information
10326 * Underlying hardware implementation does not have API to delete the
10327 * encryption key. It is automatically deleted when the peer is
10328 * removed. Hence this function currently does nothing.
10329 * Future implementation may interprete delete key operation to
10330 * replacing the key with a random junk value, effectively making it
10331 * useless.
10332 *
10333 * Return: status code, always 0.
10334 */
10335
10336static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10337 struct net_device *ndev,
10338 u8 key_index,
10339 bool pairwise, const u8 *mac_addr)
10340{
10341 EXIT();
10342 return 0;
10343}
10344
10345/**
10346 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
10347 * @wiphy: Pointer to wiphy structure.
10348 * @dev: Pointer to net_device structure.
10349 * @key_index: key index
10350 * @pairwise: pairwise
10351 * @mac_addr: mac address
10352 *
10353 * This is the cfg80211 delete key handler function which invokes
10354 * the internal function @__wlan_hdd_cfg80211_del_key with
10355 * SSR protection.
10356 *
10357 * Return: 0 for success, error number on failure.
10358 */
10359static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10360 struct net_device *dev,
10361 u8 key_index,
10362 bool pairwise, const u8 *mac_addr)
10363{
10364 int ret;
10365
10366 cds_ssr_protect(__func__);
10367 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
10368 pairwise, mac_addr);
10369 cds_ssr_unprotect(__func__);
10370
10371 return ret;
10372}
10373
10374/*
10375 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
10376 * This function is used to set the default tx key index
10377 */
10378static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10379 struct net_device *ndev,
10380 u8 key_index,
10381 bool unicast, bool multicast)
10382{
10383 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10384 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10385 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10386 hdd_context_t *pHddCtx;
10387 int status;
10388
10389 ENTER();
10390
Anurag Chouhan6d760662016-02-20 16:05:43 +053010391 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010392 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010393 return -EINVAL;
10394 }
10395
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010396 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010397 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
10398 pAdapter->sessionId, key_index));
10399
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010400 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010401 hdd_device_mode_to_string(pAdapter->device_mode),
10402 pAdapter->device_mode, key_index);
10403
10404 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010405 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010406 return -EINVAL;
10407 }
10408
10409 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10410 status = wlan_hdd_validate_context(pHddCtx);
10411
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010412 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010413 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010414
Krunal Sonib4326f22016-03-10 13:05:51 -080010415 if ((pAdapter->device_mode == QDF_STA_MODE) ||
10416 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010417 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10418 pHddStaCtx->conn_info.ucEncryptionType) &&
10419 (eCSR_ENCRYPT_TYPE_AES !=
10420 pHddStaCtx->conn_info.ucEncryptionType)) {
10421 /* If default key index is not same as previous one,
10422 * then update the default key index */
10423
10424 tCsrRoamSetKey setKey;
10425 uint32_t roamId = 0xFF;
10426 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
10427
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010428 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010429
10430 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010431 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010432 setKey.keyId = key_index;
10433 setKey.keyLength = Keys->KeyLength[key_index];
10434
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010435 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010436 &Keys->KeyMaterial[key_index][0],
10437 Keys->KeyLength[key_index]);
10438
10439 setKey.keyDirection = eSIR_TX_RX;
10440
Anurag Chouhanc5548422016-02-24 18:33:27 +053010441 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010442 &pHddStaCtx->conn_info.bssId);
10443
10444 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
10445 pWextState->roamProfile.EncryptionType.
10446 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
10447 /* In the case of dynamic wep supplicant hardcodes DWEP type
10448 * to eCSR_ENCRYPT_TYPE_WEP104 even though ap is configured for
10449 * WEP-40 encryption. In this canse the key length is 5 but the
10450 * encryption type is 104 hence checking the key langht(5) and
10451 * encryption type(104) and switching encryption type to 40*/
10452 pWextState->roamProfile.EncryptionType.
10453 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10454 pWextState->roamProfile.mcEncryptionType.
10455 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10456 }
10457
10458 setKey.encType =
10459 pWextState->roamProfile.EncryptionType.
10460 encryptionType[0];
10461
10462 /* Issue set key request */
10463 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10464 pAdapter->sessionId, &setKey,
10465 &roamId);
10466
10467 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010468 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010469 status);
10470 return -EINVAL;
10471 }
10472 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010473 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010474 /* In SoftAp mode setting key direction for default mode */
10475 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10476 pWextState->roamProfile.EncryptionType.encryptionType[0])
10477 && (eCSR_ENCRYPT_TYPE_AES !=
10478 pWextState->roamProfile.EncryptionType.
10479 encryptionType[0])) {
10480 /* Saving key direction for default key index to TX default */
10481 hdd_ap_ctx_t *pAPCtx =
10482 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10483 pAPCtx->wepKey[key_index].keyDirection =
10484 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010485 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053010486 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010487 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010488 }
10489 }
10490
10491 EXIT();
10492 return status;
10493}
10494
10495static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10496 struct net_device *ndev,
10497 u8 key_index,
10498 bool unicast, bool multicast)
10499{
10500 int ret;
10501 cds_ssr_protect(__func__);
10502 ret =
10503 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
10504 multicast);
10505 cds_ssr_unprotect(__func__);
10506
10507 return ret;
10508}
10509
Abhishek Singhc9941602016-08-09 16:06:22 +053010510/*
10511 * wlan_hdd_cfg80211_get_bss :to get the bss from kernel cache.
10512 * @wiphy: wiphy pointer
10513 * @channel: channel of the BSS
10514 * @bssid: Bssid of BSS
10515 * @ssid: Ssid of the BSS
10516 * @ssid_len: ssid length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010517 *
Abhishek Singhc9941602016-08-09 16:06:22 +053010518 * Return: bss found in kernel cache
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010519 */
Abhishek Singhc9941602016-08-09 16:06:22 +053010520#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010521static
Abhishek Singhc9941602016-08-09 16:06:22 +053010522struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10523 struct ieee80211_channel *channel, const u8 *bssid,
10524 const u8 *ssid, size_t ssid_len)
10525{
10526 return cfg80211_get_bss(wiphy, channel, bssid,
10527 ssid,
10528 ssid_len,
10529 WLAN_CAPABILITY_ESS,
10530 WLAN_CAPABILITY_ESS);
10531}
10532#else
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010533static
Abhishek Singhc9941602016-08-09 16:06:22 +053010534struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10535 struct ieee80211_channel *channel, const u8 *bssid,
10536 const u8 *ssid, size_t ssid_len)
10537{
10538 return cfg80211_get_bss(wiphy, channel, bssid,
10539 ssid,
10540 ssid_len,
10541 IEEE80211_BSS_TYPE_ESS,
10542 IEEE80211_PRIVACY_ANY);
10543}
10544#endif
10545
10546
10547/*
10548 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
10549 * interface that BSS might have been lost.
10550 * @pAdapter: adaptor
10551 * @bssid: bssid which might have been lost
10552 *
10553 * Return: bss which is unlinked from kernel cache
10554 */
10555struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
10556 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010557{
10558 struct net_device *dev = pAdapter->dev;
10559 struct wireless_dev *wdev = dev->ieee80211_ptr;
10560 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010561 struct cfg80211_bss *bss = NULL;
10562
Abhishek Singhc9941602016-08-09 16:06:22 +053010563 bss = wlan_hdd_cfg80211_get_bss(wiphy, NULL, bssid,
10564 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010565 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010566 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010567 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053010568 hdd_info("cfg80211_unlink_bss called for BSSID "
10569 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010570 cfg80211_unlink_bss(wiphy, bss);
10571 }
10572 return bss;
10573}
10574
Abhishek Singhc9941602016-08-09 16:06:22 +053010575
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010576/**
10577 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
10578 * @pAdapter: Pointer to adapter
10579 * @bss_desc: Pointer to bss descriptor
10580 *
10581 * This function is used to inform the BSS details to nl80211 interface.
10582 *
10583 * Return: struct cfg80211_bss pointer
10584 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053010585struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
10586 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010587{
10588 /*
10589 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
10590 * already exists in bss data base of cfg80211 for that particular BSS
10591 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
10592 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
10593 * As of now there is no possibility to get the mgmt(probe response)
10594 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
10595 * and passing to cfg80211_inform_bss_frame.
10596 */
10597 struct net_device *dev = pAdapter->dev;
10598 struct wireless_dev *wdev = dev->ieee80211_ptr;
10599 struct wiphy *wiphy = wdev->wiphy;
10600 int chan_no = bss_desc->channelId;
10601#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10602 qcom_ie_age *qie_age = NULL;
10603 int ie_length =
10604 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
10605#else
10606 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
10607#endif
10608 const char *ie =
10609 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
10610 unsigned int freq;
10611 struct ieee80211_channel *chan;
10612 struct ieee80211_mgmt *mgmt = NULL;
10613 struct cfg80211_bss *bss_status = NULL;
10614 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
10615 int rssi = 0;
10616 hdd_context_t *pHddCtx;
10617 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010618 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010619 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010620
10621 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10622 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010623 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010624 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010625
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010626 cfg_param = pHddCtx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010627 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
10628 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010629 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010630 return NULL;
10631 }
10632
10633 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
10634
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010635 /* Android does not want the timestamp from the frame.
10636 Instead it wants a monotonic increasing value */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070010637 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010638 mgmt->u.probe_resp.timestamp =
10639 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010640
10641 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
10642 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
10643
10644#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10645 /* GPS Requirement: need age ie per entry. Using vendor specific. */
10646 /* Assuming this is the last IE, copy at the end */
10647 ie_length -= sizeof(qcom_ie_age);
10648 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
10649 qie_age->element_id = QCOM_VENDOR_IE_ID;
10650 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
10651 qie_age->oui_1 = QCOM_OUI1;
10652 qie_age->oui_2 = QCOM_OUI2;
10653 qie_age->oui_3 = QCOM_OUI3;
10654 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
Deepthi Gowrie2e3dfd2016-10-17 16:37:52 +053010655 /*
10656 * Lowi expects the timestamp of bss in units of 1/10 ms. In driver
10657 * all bss related timestamp is in units of ms. Due to this when scan
10658 * results are sent to lowi the scan age is high.To address this,
10659 * send age in units of 1/10 ms.
10660 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010661 qie_age->age =
Deepthi Gowrie2e3dfd2016-10-17 16:37:52 +053010662 (qdf_mc_timer_get_system_time() - bss_desc->received_time)/10;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010663 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070010664 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
10665 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070010666 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
10667 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010668#endif
10669
10670 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
10671 if (bss_desc->fProbeRsp) {
10672 mgmt->frame_control |=
10673 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
10674 } else {
10675 mgmt->frame_control |=
10676 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
10677 }
10678
10679 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
10680 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL)) {
10681 freq =
10682 ieee80211_channel_to_frequency(chan_no,
10683 IEEE80211_BAND_2GHZ);
10684 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
10685 && (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL)) {
10686 freq =
10687 ieee80211_channel_to_frequency(chan_no,
10688 IEEE80211_BAND_5GHZ);
10689 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010690 hdd_err("Invalid chan_no %d", chan_no);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010691 kfree(mgmt);
10692 return NULL;
10693 }
10694
10695 chan = __ieee80211_get_channel(wiphy, freq);
10696 /* When the band is changed on the fly using the GUI, three things are done
10697 * 1. scan abort
10698 * 2. flush scan results from cache
10699 * 3. update the band with the new band user specified (refer to the
10700 * hdd_set_band_helper function) as part of the scan abort, message will be
10701 * queued to PE and we proceed with flushing and changinh the band.
10702 * PE will stop the scanning further and report back the results what ever
10703 * it had till now by calling the call back function.
10704 * if the time between update band and scandone call back is sufficient
10705 * enough the band change reflects in SME, SME validates the channels
10706 * and discards the channels correponding to previous band and calls back
10707 * with zero bss results. but if the time between band update and scan done
10708 * callback is very small then band change will not reflect in SME and SME
10709 * reports to HDD all the channels correponding to previous band.this is due
10710 * to race condition.but those channels are invalid to the new band and so
10711 * this function __ieee80211_get_channel will return NULL.Each time we
10712 * report scan result with this pointer null warning kernel trace is printed.
10713 * if the scan results contain large number of APs continuosly kernel
10714 * warning trace is printed and it will lead to apps watch dog bark.
10715 * So drop the bss and continue to next bss.
10716 */
10717 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053010718 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
10719 chan_no, freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010720 kfree(mgmt);
10721 return NULL;
10722 }
10723
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010724 /* Based on .ini configuration, raw rssi can be reported for bss.
10725 * Raw rssi is typically used for estimating power.
10726 */
10727
10728 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
10729 bss_desc->rssi;
10730
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010731 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053010732 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010733
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010734 hdd_notice("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010735 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070010736 (int)(rssi / 100),
10737 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010738
10739 bss_status =
10740 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
10741 GFP_KERNEL);
10742 kfree(mgmt);
10743 return bss_status;
10744}
10745
10746/**
10747 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
10748 * @pAdapter: Pointer to adapter
10749 * @pRoamInfo: Pointer to roam info
10750 *
10751 * This function is used to update the BSS data base of CFG8011
10752 *
10753 * Return: struct cfg80211_bss pointer
10754 */
10755struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
10756 tCsrRoamInfo *pRoamInfo)
10757{
10758 tCsrRoamConnectedProfile roamProfile;
10759 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10760 struct cfg80211_bss *bss = NULL;
10761
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010762 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
10763 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
10764
10765 if (NULL != roamProfile.pBssDesc) {
10766 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10767 roamProfile.pBssDesc);
10768
10769 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010770 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010771
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080010772 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010773 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010774 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010775 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010776 return bss;
10777}
10778/**
10779 * wlan_hdd_cfg80211_update_bss() - update bss
10780 * @wiphy: Pointer to wiphy
10781 * @pAdapter: Pointer to adapter
10782 * @scan_time: scan request timestamp
10783 *
10784 * Return: zero if success, non-zero otherwise
10785 */
10786int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
10787 hdd_adapter_t *pAdapter,
10788 uint32_t scan_time)
10789{
10790 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10791 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010792 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010793 tScanResultHandle pResult;
10794 struct cfg80211_bss *bss_status = NULL;
10795 hdd_context_t *pHddCtx;
10796 int ret;
10797
10798 ENTER();
10799
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010800 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010801 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
10802 NO_SESSION, pAdapter->sessionId));
10803
10804 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10805 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010806 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010807 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010808
10809 /* start getting scan results and populate cgf80211 BSS database */
10810 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
10811
10812 /* no scan results */
10813 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010814 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053010815 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010816 }
10817
10818 pScanResult = sme_scan_result_get_first(hHal, pResult);
10819
10820 while (pScanResult) {
10821 /*
10822 * - cfg80211_inform_bss() is not updating ie field of bss
10823 * entry if entry already exists in bss data base of cfg80211
10824 * for that particular BSS ID. Using cfg80211_inform_bss_frame
10825 * to update thebss entry instead of cfg80211_inform_bss,
10826 * But this call expects mgmt packet as input. As of now
10827 * there is no possibility to get the mgmt(probe response)
10828 * frame from PE, converting bss_desc to
10829 * ieee80211_mgmt(probe response) and passing to c
10830 * fg80211_inform_bss_frame.
10831 * - Update BSS only if beacon timestamp is later than
10832 * scan request timestamp.
10833 */
10834 if ((scan_time == 0) ||
10835 (scan_time <
Deepthi Gowrie2e3dfd2016-10-17 16:37:52 +053010836 pScanResult->BssDescriptor.received_time)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010837 bss_status =
10838 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10839 &pScanResult->BssDescriptor);
10840
10841 if (NULL == bss_status) {
10842 hdd_info("NULL returned by cfg80211_inform_bss_frame");
10843 } else {
10844 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010845 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010846 bss_status);
10847 }
10848 } else {
10849 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
10850 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
10851 }
10852 pScanResult = sme_scan_result_get_next(hHal, pResult);
10853 }
10854
10855 sme_scan_result_purge(hHal, pResult);
10856 /*
10857 * For SAP mode, scan is invoked by hostapd during SAP start
10858 * if hostapd is restarted, we need to flush previous scan
10859 * result so that it will reflect environment change
10860 */
Krunal Sonib4326f22016-03-10 13:05:51 -080010861 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010862#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
10863 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
10864#endif
10865 )
10866 sme_scan_flush_result(hHal);
10867
10868 EXIT();
10869 return 0;
10870}
10871
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010872/**
10873 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
10874 * @pAdapter: Pointer to adapter
10875 * @pRoamInfo: Pointer to roam info
10876 * @index: Index
10877 * @preauth: Preauth flag
10878 *
10879 * This function is used to notify the supplicant of a new PMKSA candidate.
10880 *
10881 * Return: 0 for success, non-zero for failure
10882 */
10883int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
10884 tCsrRoamInfo *pRoamInfo,
10885 int index, bool preauth)
10886{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010887 struct net_device *dev = pAdapter->dev;
10888 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
10889
10890 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010891 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010892
10893 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010894 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010895 return -EINVAL;
10896 }
10897
10898 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010899 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010900 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
10901 cfg80211_pmksa_candidate_notify(dev, index,
10902 pRoamInfo->bssid.bytes,
10903 preauth, GFP_KERNEL);
10904 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010905 return 0;
10906}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010907
10908#ifdef FEATURE_WLAN_LFR_METRICS
10909/**
10910 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
10911 * @pAdapter: Pointer to adapter
10912 * @pRoamInfo: Pointer to roam info
10913 *
10914 * 802.11r/LFR metrics reporting function to report preauth initiation
10915 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010916 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010917 */
10918#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010919QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010920 tCsrRoamInfo *pRoamInfo)
10921{
10922 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10923 union iwreq_data wrqu;
10924
10925 ENTER();
10926
10927 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010928 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010929 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010930 }
10931
10932 /* create the event */
10933 memset(&wrqu, 0, sizeof(wrqu));
10934 memset(metrics_notification, 0, sizeof(metrics_notification));
10935
10936 wrqu.data.pointer = metrics_notification;
10937 wrqu.data.length = scnprintf(metrics_notification,
10938 sizeof(metrics_notification),
10939 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
10940 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10941
10942 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10943 metrics_notification);
10944
10945 EXIT();
10946
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010947 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010948}
10949
10950/**
10951 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
10952 * @pAdapter: Pointer to adapter
10953 * @pRoamInfo: Pointer to roam info
10954 * @preauth_status: Preauth status
10955 *
10956 * 802.11r/LFR metrics reporting function to report handover initiation
10957 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010958 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010959 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010960QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010961wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
10962 tCsrRoamInfo *pRoamInfo,
10963 bool preauth_status)
10964{
10965 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10966 union iwreq_data wrqu;
10967
10968 ENTER();
10969
10970 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010971 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010972 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010973 }
10974
10975 /* create the event */
10976 memset(&wrqu, 0, sizeof(wrqu));
10977 memset(metrics_notification, 0, sizeof(metrics_notification));
10978
10979 scnprintf(metrics_notification, sizeof(metrics_notification),
10980 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
10981 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10982
10983 if (1 == preauth_status)
10984 strlcat(metrics_notification, " true",
10985 sizeof(metrics_notification));
10986 else
10987 strlcat(metrics_notification, " false",
10988 sizeof(metrics_notification));
10989
10990 wrqu.data.pointer = metrics_notification;
10991 wrqu.data.length = strlen(metrics_notification);
10992
10993 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10994 metrics_notification);
10995
10996 EXIT();
10997
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010998 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010999}
11000
11001/**
11002 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
11003 * @pAdapter: Pointer to adapter
11004 * @pRoamInfo: Pointer to roam info
11005 *
11006 * 802.11r/LFR metrics reporting function to report handover initiation
11007 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053011008 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011009 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011010QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011011 tCsrRoamInfo *pRoamInfo)
11012{
11013 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
11014 union iwreq_data wrqu;
11015
11016 ENTER();
11017
11018 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011019 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011020 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011021 }
11022
11023 /* create the event */
11024 memset(&wrqu, 0, sizeof(wrqu));
11025 memset(metrics_notification, 0, sizeof(metrics_notification));
11026
11027 wrqu.data.pointer = metrics_notification;
11028 wrqu.data.length = scnprintf(metrics_notification,
11029 sizeof(metrics_notification),
11030 "QCOM: LFR_PREAUTH_HANDOVER "
11031 MAC_ADDRESS_STR,
11032 MAC_ADDR_ARRAY(pRoamInfo->bssid));
11033
11034 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
11035 metrics_notification);
11036
11037 EXIT();
11038
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011039 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011040}
11041#endif
11042
11043/**
11044 * hdd_select_cbmode() - select channel bonding mode
11045 * @pAdapter: Pointer to adapter
11046 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011047 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011048 *
11049 * Return: none
11050 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011051void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
11052 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011053{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011054 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011055 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011056 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011057
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011058 /*
11059 * CDS api expects secondary channel for calculating
11060 * the channel params
11061 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011062 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070011063 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
11064 if (operationChannel >= 1 && operationChannel <= 5)
11065 sec_ch = operationChannel + 4;
11066 else if (operationChannel >= 6 && operationChannel <= 13)
11067 sec_ch = operationChannel - 4;
11068 }
11069
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011070 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011071 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011072
11073 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011074 eHddDot11Mode hdd_dot11_mode;
11075 uint8_t iniDot11Mode =
11076 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
11077
11078 hdd_notice("Dot11Mode is %u", iniDot11Mode);
11079 switch (iniDot11Mode) {
11080 case eHDD_DOT11_MODE_AUTO:
11081 case eHDD_DOT11_MODE_11ac:
11082 case eHDD_DOT11_MODE_11ac_ONLY:
11083 if (sme_is_feature_supported_by_fw(DOT11AC))
11084 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
11085 else
11086 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11087 break;
11088 case eHDD_DOT11_MODE_11n:
11089 case eHDD_DOT11_MODE_11n_ONLY:
11090 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11091 break;
11092 default:
11093 hdd_dot11_mode = iniDot11Mode;
11094 break;
11095 }
11096 ch_info->channel_width = ch_params->ch_width;
11097 ch_info->phy_mode =
11098 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011099 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011100 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011101 hdd_info("ch_info width %d, phymode %d channel %d",
11102 ch_info->channel_width, ch_info->phy_mode,
11103 ch_info->channel);
11104 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011105}
11106
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011107/**
11108 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
11109 * @adapter: STA adapter
11110 * @roam_profile: STA roam profile
11111 *
11112 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
11113 *
11114 * Return: false if sta-sap conc is not allowed, else return true
11115 */
11116static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
11117 tCsrRoamProfile *roam_profile)
11118{
11119 hdd_context_t *hdd_ctx;
11120 hdd_adapter_t *ap_adapter;
11121 hdd_ap_ctx_t *hdd_ap_ctx;
11122 hdd_hostapd_state_t *hostapd_state;
11123 uint8_t channel = 0;
11124 QDF_STATUS status;
11125
11126 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11127 if (!hdd_ctx) {
11128 hdd_err("HDD context is NULL");
11129 return true;
11130 }
11131
11132 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
11133 /* probably no sap running, no handling required */
11134 if (ap_adapter == NULL)
11135 return true;
11136
11137 /*
11138 * sap is not in started state, so it is fine to go ahead with sta.
11139 * if sap is currently doing CAC then don't allow sta to go further.
11140 */
11141 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
11142 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
11143 return true;
11144
11145 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
11146 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
11147 return false;
11148 }
11149
11150 /*
11151 * log and return error, if we allow STA to go through, we don't
11152 * know what is going to happen better stop sta connection
11153 */
11154 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
11155 if (NULL == hdd_ap_ctx) {
11156 hdd_err("AP context not found");
11157 return false;
11158 }
11159
11160 /* sap is on non-dfs channel, nothing to handle */
11161 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
11162 hdd_info("sap is on non-dfs channel, sta is allowed");
11163 return true;
11164 }
11165 /*
11166 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053011167 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011168 */
11169 status = cds_get_channel_from_scan_result(adapter,
11170 roam_profile, &channel);
11171
Nitesh Shah59774522016-09-16 15:14:21 +053011172 /*
11173 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
11174 * channels for roaming case.
11175 */
11176 if (CDS_IS_CHANNEL_24GHZ(channel)) {
11177 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
11178 return true;
11179 }
11180
11181 /*
11182 * If channel is 0 or DFS then better to call pcl and find out the
11183 * best channel. If channel is non-dfs 5 GHz then better move SAP
11184 * to STA's channel to make scc, so we have room for 3port MCC
11185 * scenario.
11186 */
11187 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011188 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
11189 true);
11190
11191 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
11192 qdf_event_reset(&hostapd_state->qdf_event);
11193 status = wlansap_set_channel_change_with_csa(
11194 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
11195 hdd_ap_ctx->sapConfig.ch_width_orig);
11196
11197 if (QDF_STATUS_SUCCESS != status) {
11198 hdd_err("Set channel with CSA IE failed, can't allow STA");
11199 return false;
11200 }
11201
11202 /*
11203 * wait here for SAP to finish the channel switch. When channel
11204 * switch happens, SAP sends few beacons with CSA_IE. After
11205 * successfully Transmission of those beacons, it will move its
11206 * state from started to disconnected and move to new channel.
11207 * once it moves to new channel, sap again moves its state
11208 * machine from disconnected to started and set this event.
11209 * wait for 10 secs to finish this.
11210 */
11211 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
11212 if (!QDF_IS_STATUS_SUCCESS(status)) {
11213 hdd_err("wait for qdf_event failed, STA not allowed!!");
11214 return false;
11215 }
11216
11217 return true;
11218}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011219
Krunal Soni31949422016-07-29 17:17:53 -070011220/**
11221 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011222 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070011223 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011224 * @ssid_len: Length of ssid
11225 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070011226 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011227 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011228 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011229 *
11230 * This function is used to start the association process
11231 *
11232 * Return: 0 for success, non-zero for failure
11233 */
Krunal Soni31949422016-07-29 17:17:53 -070011234static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011235 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070011236 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011237 u8 operatingChannel,
11238 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011239{
11240 int status = 0;
11241 hdd_wext_state_t *pWextState;
11242 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011243 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011244 uint32_t roamId;
11245 tCsrRoamProfile *pRoamProfile;
11246 eCsrAuthType RSNAuthType;
11247 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053011248 uint8_t channel = 0;
11249 struct sir_hw_mode_params hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011250
11251 ENTER();
11252
11253 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11254 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011255 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011256
11257 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011258 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011259 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011260
11261 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011262 hdd_err("wrong SSID len");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011263 return -EINVAL;
11264 }
11265
11266 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053011267 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
11268 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011269
11270 if (pRoamProfile) {
11271 hdd_station_ctx_t *pHddStaCtx;
11272 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11273
11274 if (HDD_WMM_USER_MODE_NO_QOS ==
11275 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
11276 /*QoS not enabled in cfg file */
11277 pRoamProfile->uapsd_mask = 0;
11278 } else {
11279 /*QoS enabled, update uapsd mask from cfg file */
11280 pRoamProfile->uapsd_mask =
11281 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
11282 }
11283
11284 pRoamProfile->SSIDs.numOfSSIDs = 1;
11285 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011286 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011287 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011288 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011289 ssid, ssid_len);
11290
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011291 pRoamProfile->do_not_roam = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011292 if (bssid) {
11293 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011294 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011295 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011296 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011297 /*
11298 * Save BSSID in seperate variable as
11299 * pRoamProfile's BSSID is getting zeroed out in the
11300 * association process. In case of join failure
11301 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011302 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011303 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011304 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011305 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011306 } else if (bssid_hint) {
11307 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011308 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011309 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011310 /*
11311 * Save BSSID in a separate variable as
11312 * pRoamProfile's BSSID is getting zeroed out in the
11313 * association process. In case of join failure
11314 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011315 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011316 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011317 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011318 hdd_info("bssid_hint is given by upper layer %pM",
11319 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011320 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011321 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011322 QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011323 hdd_info("no bssid given by upper layer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011324 }
11325
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011326 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011327 pRoamProfile->SSIDs.SSIDList->SSID.length,
11328 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
11329 operatingChannel);
11330
11331 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
11332 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011333 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011334 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
11335 }
11336#ifdef FEATURE_WLAN_WAPI
11337 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011338 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011339 switch (pAdapter->wapi_info.wapiAuthMode) {
11340 case WAPI_AUTH_MODE_PSK:
11341 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011342 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011343 pAdapter->wapi_info.wapiAuthMode);
11344 pRoamProfile->AuthType.authType[0] =
11345 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
11346 break;
11347 }
11348 case WAPI_AUTH_MODE_CERT:
11349 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011350 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011351 pAdapter->wapi_info.wapiAuthMode);
11352 pRoamProfile->AuthType.authType[0] =
11353 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
11354 break;
11355 }
11356 } /* End of switch */
11357 if (pAdapter->wapi_info.wapiAuthMode ==
11358 WAPI_AUTH_MODE_PSK
11359 || pAdapter->wapi_info.wapiAuthMode ==
11360 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011361 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011362 pRoamProfile->AuthType.numEntries = 1;
11363 pRoamProfile->EncryptionType.numEntries = 1;
11364 pRoamProfile->EncryptionType.encryptionType[0] =
11365 eCSR_ENCRYPT_TYPE_WPI;
11366 pRoamProfile->mcEncryptionType.numEntries = 1;
11367 pRoamProfile->mcEncryptionType.
11368 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
11369 }
11370 }
Krunal Soni31949422016-07-29 17:17:53 -070011371#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011372#ifdef WLAN_FEATURE_GTK_OFFLOAD
11373 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080011374 if ((QDF_STA_MODE == pAdapter->device_mode) ||
11375 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011376 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
11377 sizeof(tSirGtkOffloadParams));
11378 pHddStaCtx->gtkOffloadReqParams.ulFlags =
11379 GTK_OFFLOAD_DISABLE;
11380 }
11381#endif
11382 pRoamProfile->csrPersona = pAdapter->device_mode;
11383
11384 if (operatingChannel) {
11385 pRoamProfile->ChannelInfo.ChannelList =
11386 &operatingChannel;
11387 pRoamProfile->ChannelInfo.numOfChannels = 1;
11388 } else {
11389 pRoamProfile->ChannelInfo.ChannelList = NULL;
11390 pRoamProfile->ChannelInfo.numOfChannels = 0;
11391 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011392 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011393 && operatingChannel) {
11394 /*
11395 * Need to post the IBSS power save parameters
11396 * to WMA. WMA will configure this parameters
11397 * to firmware if power save is enabled by the
11398 * firmware.
11399 */
11400 status = hdd_set_ibss_power_save_params(pAdapter);
11401
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011402 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011403 hdd_err("Set IBSS Power Save Params Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011404 return -EINVAL;
11405 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011406 pRoamProfile->ch_params.ch_width =
11407 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053011408 /*
11409 * In IBSS mode while operating in 2.4 GHz,
11410 * the device supports only 20 MHz.
11411 */
11412 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
11413 pRoamProfile->ch_params.ch_width =
11414 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011415 hdd_select_cbmode(pAdapter, operatingChannel,
11416 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011417 }
Abhishek Singh99bce862016-06-20 15:10:51 +053011418 /*
11419 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
11420 * or pmf=2 is an explicit configuration in the supplicant
11421 * configuration, drop the connection request.
11422 */
11423 if (pWextState->roamProfile.MFPEnabled &&
11424 !(pWextState->roamProfile.MFPRequired ||
11425 pWextState->roamProfile.MFPCapable)) {
11426 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
11427 pWextState->roamProfile.MFPEnabled,
11428 pWextState->roamProfile.MFPRequired,
11429 pWextState->roamProfile.MFPCapable);
11430 return -EINVAL;
11431 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011432
Krunal Soni3091bcc2016-06-23 12:28:21 -070011433 if (true == cds_is_connection_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011434 hdd_err("Connection refused: conn in progress");
11435 return -EINVAL;
11436 }
11437
Krunal Soni31949422016-07-29 17:17:53 -070011438 /*
11439 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011440 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070011441 * enhancements, the supplicant is not issuing the scan command
11442 * now. So the unicast frames which are sent from the host are
11443 * not having the additional IEs. If it is P2P CLIENT and there
11444 * is no additional IE present in roamProfile, then use the
11445 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011446 */
11447
Krunal Sonib4326f22016-03-10 13:05:51 -080011448 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011449 (!pRoamProfile->pAddIEScan)) {
11450 pRoamProfile->pAddIEScan =
11451 &pAdapter->scan_info.scanAddIE.addIEdata[0];
11452 pRoamProfile->nAddIEScanLength =
11453 pAdapter->scan_info.scanAddIE.length;
11454 }
11455 /*
11456 * When policy manager is enabled from ini file, we shouldn't
11457 * check for other concurrency rules.
11458 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070011459 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080011460 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011461 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011462 pAdapter, pRoamProfile, &roamId))
11463 return 0;
11464 }
11465
Krunal Soni3091bcc2016-06-23 12:28:21 -070011466 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011467 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
11468 pRoamProfile))) {
11469 hdd_err("sap-sta conc will fail, can't allow sta");
11470 hdd_conn_set_connection_state(pAdapter,
11471 eConnectionState_NotConnected);
11472 return -ENOMEM;
11473 }
11474
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011475 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011476 if (!sme_config) {
11477 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011478 hdd_conn_set_connection_state(pAdapter,
11479 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011480 return -ENOMEM;
11481 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011482 qdf_mem_zero(sme_config, sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011483 sme_get_config_param(pHddCtx->hHal, sme_config);
11484 /* These values are not sessionized. So, any change in these SME
11485 * configs on an older or parallel interface will affect the
11486 * cb mode. So, restoring the default INI params before starting
11487 * interfaces such as sta, cli etc.,
11488 */
11489 sme_config->csrConfig.channelBondingMode5GHz =
11490 pHddCtx->config->nChannelBondingMode5GHz;
11491 sme_config->csrConfig.channelBondingMode24GHz =
11492 pHddCtx->config->nChannelBondingMode24GHz;
11493 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011494 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053011495 /*
11496 * Change conn_state to connecting before sme_roam_connect(),
11497 * because sme_roam_connect() has a direct path to call
11498 * hdd_sme_roam_callback(), which will change the conn_state
11499 * If direct path, conn_state will be accordingly changed to
11500 * NotConnected or Associated by either
11501 * hdd_association_completion_handler() or
11502 * hdd_dis_connect_handler() in sme_RoamCallback()if
11503 * sme_RomConnect is to be queued,
11504 * Connecting state will remain until it is completed.
11505 *
11506 * If connection state is not changed, connection state will
11507 * remain in eConnectionState_NotConnected state.
11508 * In hdd_association_completion_handler, "hddDisconInProgress"
11509 * is set to true if conn state is
11510 * eConnectionState_NotConnected.
11511 * If "hddDisconInProgress" is set to true then cfg80211 layer
11512 * is not informed of connect result indication which
11513 * is an issue.
11514 */
11515 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053011516 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053011517 hdd_conn_set_connection_state(pAdapter,
11518 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011519
Komal Seelama89be8d2016-09-29 11:09:26 +053011520 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
11521 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011522 status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
11523 pAdapter->sessionId, pRoamProfile,
11524 &roamId);
11525
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011526 if ((QDF_STATUS_SUCCESS != status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080011527 (QDF_STA_MODE == pAdapter->device_mode ||
11528 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011529 hdd_err("sme_roam_connect (session %d) failed with "
11530 "status %d. -> NotConnected",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011531 pAdapter->sessionId, status);
11532 /* change back to NotAssociated */
11533 hdd_conn_set_connection_state(pAdapter,
11534 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053011535 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
11536 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011537 }
11538
11539 pRoamProfile->ChannelInfo.ChannelList = NULL;
11540 pRoamProfile->ChannelInfo.numOfChannels = 0;
11541
Nitesh Shah044fd672016-10-13 18:53:25 +053011542 if (!QDF_IS_STATUS_SUCCESS(
11543 wma_get_current_hw_mode(&hw_mode))) {
11544 hdd_err("wma_get_current_hw_mode failed");
11545 return status;
11546 }
11547
11548 if ((QDF_STA_MODE == pAdapter->device_mode)
11549 && hw_mode.dbs_cap) {
11550 cds_get_channel_from_scan_result(pAdapter,
11551 pRoamProfile, &channel);
11552 if (channel)
11553 cds_checkn_update_hw_mode_single_mac_mode
11554 (channel);
11555 }
11556
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011557 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011558 hdd_err("No valid Roam profile");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011559 return -EINVAL;
11560 }
11561 EXIT();
11562 return status;
11563}
11564
11565/**
11566 * wlan_hdd_cfg80211_set_auth_type() - set auth type
11567 * @pAdapter: Pointer to adapter
11568 * @auth_type: Auth type
11569 *
11570 * This function is used to set the authentication type (OPEN/SHARED).
11571 *
11572 * Return: 0 for success, non-zero for failure
11573 */
11574static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
11575 enum nl80211_auth_type auth_type)
11576{
11577 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11578 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11579
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011580 /*set authentication type */
11581 switch (auth_type) {
11582 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011583 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011584 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
11585 break;
11586
11587 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011588 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011589 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011590 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
11591 break;
11592
11593 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011594 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011595 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
11596 break;
11597#ifdef FEATURE_WLAN_ESE
11598 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011599 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011600 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
11601 break;
11602#endif
11603
11604 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011605 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011606 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
11607 return -EINVAL;
11608 }
11609
11610 pWextState->roamProfile.AuthType.authType[0] =
11611 pHddStaCtx->conn_info.authType;
11612 return 0;
11613}
11614
11615/**
11616 * wlan_hdd_set_akm_suite() - set key management type
11617 * @pAdapter: Pointer to adapter
11618 * @key_mgmt: Key management type
11619 *
11620 * This function is used to set the key mgmt type(PSK/8021x).
11621 *
11622 * Return: 0 for success, non-zero for failure
11623 */
11624static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
11625{
11626 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11627
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011628#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
11629#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
11630 /*set key mgmt type */
11631 switch (key_mgmt) {
11632 case WLAN_AKM_SUITE_PSK:
11633 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011634 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011635 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011636 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
11637 break;
11638
11639 case WLAN_AKM_SUITE_8021X_SHA256:
11640 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011641 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011642 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011643 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11644 break;
11645#ifdef FEATURE_WLAN_ESE
11646#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
11647#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
11648 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011649 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011650 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
11651 break;
11652#endif
11653#ifndef WLAN_AKM_SUITE_OSEN
11654#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
11655#endif
11656 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011657 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011658 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11659 break;
11660
11661 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011662 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011663 return -EINVAL;
11664
11665 }
11666 return 0;
11667}
11668
11669/**
11670 * wlan_hdd_cfg80211_set_cipher() - set encryption type
11671 * @pAdapter: Pointer to adapter
11672 * @cipher: Cipher type
11673 * @ucast: Unicast flag
11674 *
11675 * This function is used to set the encryption type
11676 * (NONE/WEP40/WEP104/TKIP/CCMP).
11677 *
11678 * Return: 0 for success, non-zero for failure
11679 */
11680static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
11681 u32 cipher, bool ucast)
11682{
11683 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11684 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11685 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11686
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011687 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080011688 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011689 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11690 } else {
11691
11692 /*set encryption method */
11693 switch (cipher) {
11694 case IW_AUTH_CIPHER_NONE:
11695 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11696 break;
11697
11698 case WLAN_CIPHER_SUITE_WEP40:
11699 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
11700 break;
11701
11702 case WLAN_CIPHER_SUITE_WEP104:
11703 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
11704 break;
11705
11706 case WLAN_CIPHER_SUITE_TKIP:
11707 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
11708 break;
11709
11710 case WLAN_CIPHER_SUITE_CCMP:
11711 encryptionType = eCSR_ENCRYPT_TYPE_AES;
11712 break;
11713#ifdef FEATURE_WLAN_WAPI
11714 case WLAN_CIPHER_SUITE_SMS4:
11715 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
11716 break;
11717#endif
11718
11719#ifdef FEATURE_WLAN_ESE
11720 case WLAN_CIPHER_SUITE_KRK:
11721 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
11722 break;
11723#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11724 case WLAN_CIPHER_SUITE_BTK:
11725 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
11726 break;
11727#endif
11728#endif
11729 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011730 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011731 return -EOPNOTSUPP;
11732 }
11733 }
11734
11735 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011736 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011737 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
11738 pWextState->roamProfile.EncryptionType.numEntries = 1;
11739 pWextState->roamProfile.EncryptionType.encryptionType[0] =
11740 encryptionType;
11741 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011742 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011743 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
11744 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
11745 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
11746 encryptionType;
11747 }
11748
11749 return 0;
11750}
11751
11752/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011753 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
11754 * @wext_state: Pointer to wext state
11755 * @gen_ie: Pointer to IE data
11756 * @len: length of IE data
11757 *
11758 * Return: 0 for success, non-zero for failure
11759 */
11760static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
11761 const uint8_t *gen_ie, uint16_t len)
11762{
11763 uint16_t cur_add_ie_len =
11764 wext_state->assocAddIE.length;
11765
11766 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11767 (wext_state->assocAddIE.length + len)) {
11768 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
11769 QDF_ASSERT(0);
11770 return -ENOMEM;
11771 }
11772 memcpy(wext_state->assocAddIE.addIEdata +
11773 cur_add_ie_len, gen_ie, len);
11774 wext_state->assocAddIE.length += len;
11775
11776 wext_state->roamProfile.pAddIEAssoc =
11777 wext_state->assocAddIE.addIEdata;
11778 wext_state->roamProfile.nAddIEAssocLength =
11779 wext_state->assocAddIE.length;
11780 return 0;
11781}
11782
11783/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011784 * wlan_hdd_cfg80211_set_ie() - set IEs
11785 * @pAdapter: Pointer to adapter
11786 * @ie: Pointer ot ie
11787 * @ie: IE length
11788 *
11789 * Return: 0 for success, non-zero for failure
11790 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070011791static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011792 size_t ie_len)
11793{
11794 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11795 const uint8_t *genie = ie;
11796 uint16_t remLen = ie_len;
11797#ifdef FEATURE_WLAN_WAPI
11798 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
11799 u16 *tmp;
11800 uint16_t akmsuiteCount;
11801 int *akmlist;
11802#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011803 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011804
11805 /* clear previous assocAddIE */
11806 pWextState->assocAddIE.length = 0;
11807 pWextState->roamProfile.bWPSAssociation = false;
11808 pWextState->roamProfile.bOSENAssociation = false;
11809
11810 while (remLen >= 2) {
11811 uint16_t eLen = 0;
11812 uint8_t elementId;
11813 elementId = *genie++;
11814 eLen = *genie++;
11815 remLen -= 2;
11816
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011817 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011818
11819 switch (elementId) {
11820 case DOT11F_EID_WPA:
11821 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 -070011822 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011823 return -EINVAL;
11824 } else if (0 ==
11825 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
11826 uint16_t curAddIELen =
11827 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011828 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011829
11830 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11831 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011832 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011833 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011834 return -ENOMEM;
11835 }
11836 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
11837 memcpy(pWextState->assocAddIE.addIEdata +
11838 curAddIELen, genie - 2, eLen + 2);
11839 pWextState->assocAddIE.length += eLen + 2;
11840
11841 pWextState->roamProfile.bWPSAssociation = true;
11842 pWextState->roamProfile.pAddIEAssoc =
11843 pWextState->assocAddIE.addIEdata;
11844 pWextState->roamProfile.nAddIEAssocLength =
11845 pWextState->assocAddIE.length;
11846 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011847 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011848 memset(pWextState->WPARSNIE, 0,
11849 MAX_WPA_RSN_IE_LEN);
11850 memcpy(pWextState->WPARSNIE, genie - 2,
11851 (eLen + 2));
11852 pWextState->roamProfile.pWPAReqIE =
11853 pWextState->WPARSNIE;
11854 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
11855 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
11856 P2P_OUI_TYPE_SIZE))) {
11857 uint16_t curAddIELen =
11858 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011859 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011860
11861 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11862 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011863 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011864 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011865 return -ENOMEM;
11866 }
11867 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
11868 memcpy(pWextState->assocAddIE.addIEdata +
11869 curAddIELen, genie - 2, eLen + 2);
11870 pWextState->assocAddIE.length += eLen + 2;
11871
11872 pWextState->roamProfile.pAddIEAssoc =
11873 pWextState->assocAddIE.addIEdata;
11874 pWextState->roamProfile.nAddIEAssocLength =
11875 pWextState->assocAddIE.length;
11876 }
11877#ifdef WLAN_FEATURE_WFD
11878 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
11879 WFD_OUI_TYPE_SIZE)) &&
11880 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080011881 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011882 pAdapter->device_mode)) {
11883 uint16_t curAddIELen =
11884 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011885 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011886
11887 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11888 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011889 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011890 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011891 return -ENOMEM;
11892 }
11893 /* WFD IE is saved to Additional IE ; it should
11894 * be accumulated to handle WPS IE + P2P IE +
11895 * WFD IE */
11896 memcpy(pWextState->assocAddIE.addIEdata +
11897 curAddIELen, genie - 2, eLen + 2);
11898 pWextState->assocAddIE.length += eLen + 2;
11899
11900 pWextState->roamProfile.pAddIEAssoc =
11901 pWextState->assocAddIE.addIEdata;
11902 pWextState->roamProfile.nAddIEAssocLength =
11903 pWextState->assocAddIE.length;
11904 }
11905#endif
11906 /* Appending HS 2.0 Indication Element in Assiciation Request */
11907 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
11908 HS20_OUI_TYPE_SIZE))) {
11909 uint16_t curAddIELen =
11910 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011911 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011912
11913 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11914 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011915 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011916 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011917 return -ENOMEM;
11918 }
11919 memcpy(pWextState->assocAddIE.addIEdata +
11920 curAddIELen, genie - 2, eLen + 2);
11921 pWextState->assocAddIE.length += eLen + 2;
11922
11923 pWextState->roamProfile.pAddIEAssoc =
11924 pWextState->assocAddIE.addIEdata;
11925 pWextState->roamProfile.nAddIEAssocLength =
11926 pWextState->assocAddIE.length;
11927 }
11928 /* Appending OSEN Information Element in Assiciation Request */
11929 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
11930 OSEN_OUI_TYPE_SIZE))) {
11931 uint16_t curAddIELen =
11932 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011933 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011934
11935 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11936 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011937 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011938 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011939 return -ENOMEM;
11940 }
11941 memcpy(pWextState->assocAddIE.addIEdata +
11942 curAddIELen, genie - 2, eLen + 2);
11943 pWextState->assocAddIE.length += eLen + 2;
11944
11945 pWextState->roamProfile.bOSENAssociation = true;
11946 pWextState->roamProfile.pAddIEAssoc =
11947 pWextState->assocAddIE.addIEdata;
11948 pWextState->roamProfile.nAddIEAssocLength =
11949 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011950 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
11951 MBO_OUI_TYPE_SIZE))){
11952 hdd_info("Set MBO IE(len %d)", eLen + 2);
11953 status = wlan_hdd_add_assoc_ie(pWextState,
11954 genie - 2, eLen + 2);
11955 if (status)
11956 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011957 } else {
11958 uint16_t add_ie_len =
11959 pWextState->assocAddIE.length;
11960
11961 hdd_info("Set OSEN IE(len %d)", eLen + 2);
11962
11963 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11964 (pWextState->assocAddIE.length + eLen)) {
11965 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011966 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011967 return -ENOMEM;
11968 }
11969
11970 memcpy(pWextState->assocAddIE.addIEdata +
11971 add_ie_len, genie - 2, eLen + 2);
11972 pWextState->assocAddIE.length += eLen + 2;
11973
11974 pWextState->roamProfile.pAddIEAssoc =
11975 pWextState->assocAddIE.addIEdata;
11976 pWextState->roamProfile.nAddIEAssocLength =
11977 pWextState->assocAddIE.length;
11978 }
11979 break;
11980 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011981 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011982 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
11983 memcpy(pWextState->WPARSNIE, genie - 2,
11984 (eLen + 2));
11985 pWextState->roamProfile.pRSNReqIE =
11986 pWextState->WPARSNIE;
11987 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
11988 break;
11989 /*
11990 * Appending Extended Capabilities with Interworking bit set
11991 * in Assoc Req.
11992 *
11993 * In assoc req this EXT Cap will only be taken into account if
11994 * interworkingService bit is set to 1. Currently
11995 * driver is only interested in interworkingService capability
11996 * from supplicant. If in future any other EXT Cap info is
11997 * required from supplicat, it needs to be handled while
11998 * sending Assoc Req in LIM.
11999 */
12000 case DOT11F_EID_EXTCAP:
12001 {
12002 uint16_t curAddIELen =
12003 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012004 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012005
12006 if (SIR_MAC_MAX_ADD_IE_LENGTH <
12007 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012008 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012009 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012010 return -ENOMEM;
12011 }
12012 memcpy(pWextState->assocAddIE.addIEdata +
12013 curAddIELen, genie - 2, eLen + 2);
12014 pWextState->assocAddIE.length += eLen + 2;
12015
12016 pWextState->roamProfile.pAddIEAssoc =
12017 pWextState->assocAddIE.addIEdata;
12018 pWextState->roamProfile.nAddIEAssocLength =
12019 pWextState->assocAddIE.length;
12020 break;
12021 }
12022#ifdef FEATURE_WLAN_WAPI
12023 case WLAN_EID_WAPI:
12024 /* Setting WAPI Mode to ON=1 */
12025 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012026 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012027 tmp = (u16 *) ie;
12028 tmp = tmp + 2; /* Skip element Id and Len, Version */
12029 akmsuiteCount = WPA_GET_LE16(tmp);
12030 tmp = tmp + 1;
12031 akmlist = (int *)(tmp);
12032 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
12033 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
12034 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012035 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012036 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012037 return -EINVAL;
12038 }
12039
12040 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012041 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012042 pAdapter->wapi_info.wapiAuthMode =
12043 WAPI_AUTH_MODE_PSK;
12044 }
12045 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012046 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012047 pAdapter->wapi_info.wapiAuthMode =
12048 WAPI_AUTH_MODE_CERT;
12049 }
12050 break;
12051#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053012052 case DOT11F_EID_SUPPOPERATINGCLASSES:
12053 {
12054 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
12055 status = wlan_hdd_add_assoc_ie(pWextState,
12056 genie - 2, eLen + 2);
12057 if (status)
12058 return status;
12059 break;
12060 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012061 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012062 hdd_err("Set UNKNOWN IE %X", elementId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012063 /* when Unknown IE is received we should break and continue
12064 * to the next IE in the buffer instead we were returning
12065 * so changing this to break */
12066 break;
12067 }
12068 genie += eLen;
12069 remLen -= eLen;
12070 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012071 return 0;
12072}
12073
12074/**
12075 * hdd_is_wpaie_present() - check for WPA ie
12076 * @ie: Pointer to ie
12077 * @ie_len: Ie length
12078 *
12079 * Parse the received IE to find the WPA IE
12080 *
12081 * Return: true if wpa ie is found else false
12082 */
12083static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
12084{
12085 uint8_t eLen = 0;
12086 uint16_t remLen = ie_len;
12087 uint8_t elementId = 0;
12088
12089 while (remLen >= 2) {
12090 elementId = *ie++;
12091 eLen = *ie++;
12092 remLen -= 2;
12093 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012094 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012095 return false;
12096 }
12097 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
12098 /* OUI - 0x00 0X50 0XF2
12099 * WPA Information Element - 0x01
12100 * WPA version - 0x01
12101 */
12102 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
12103 return true;
12104 }
12105 ie += eLen;
12106 remLen -= eLen;
12107 }
12108 return false;
12109}
12110
12111/**
12112 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
12113 * @pAdapter: Pointer to adapter
12114 * @req: Pointer to security parameters
12115 *
12116 * Return: 0 for success, non-zero for failure
12117 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012118static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
12119 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012120{
12121 int status = 0;
12122 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12123 ENTER();
12124
12125 /*set wpa version */
12126 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
12127
12128 if (req->crypto.wpa_versions) {
12129 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
12130 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
12131 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
12132 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12133 }
12134 }
12135
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012136 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012137
12138 /*set authentication type */
12139 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
12140
12141 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012142 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012143 return status;
12144 }
12145
12146 /*set key mgmt type */
12147 if (req->crypto.n_akm_suites) {
12148 status =
12149 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
12150 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012151 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012152 return status;
12153 }
12154 }
12155
12156 /*set pairwise cipher type */
12157 if (req->crypto.n_ciphers_pairwise) {
12158 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
12159 req->crypto.
12160 ciphers_pairwise[0],
12161 true);
12162 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012163 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012164 return status;
12165 }
12166 } else {
12167 /*Reset previous cipher suite to none */
12168 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
12169 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012170 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012171 return status;
12172 }
12173 }
12174
12175 /*set group cipher type */
12176 status =
12177 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
12178 false);
12179
12180 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012181 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012182 return status;
12183 }
12184#ifdef WLAN_FEATURE_11W
12185 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
12186#endif
12187
12188 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
12189 if (req->ie_len) {
12190 status =
12191 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
12192 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012193 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012194 return status;
12195 }
12196 }
12197
12198 /*incase of WEP set default key information */
12199 if (req->key && req->key_len) {
12200 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
12201 || (WLAN_CIPHER_SUITE_WEP104 ==
12202 req->crypto.ciphers_pairwise[0])
12203 ) {
12204 if (IW_AUTH_KEY_MGMT_802_1X
12205 ==
12206 (pWextState->
12207 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012208 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012209 return -EOPNOTSUPP;
12210 } else {
12211 u8 key_len = req->key_len;
12212 u8 key_idx = req->key_idx;
12213
12214 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
12215 key_len)
12216 && (CSR_MAX_NUM_KEY > key_idx)
12217 ) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012218 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012219 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012220 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012221 Keys.
12222 KeyMaterial[key_idx][0],
12223 req->key, key_len);
12224 pWextState->roamProfile.Keys.
12225 KeyLength[key_idx] = (u8) key_len;
12226 pWextState->roamProfile.Keys.
12227 defaultIndex = (u8) key_idx;
12228 }
12229 }
12230 }
12231 }
12232
12233 return status;
12234}
12235
12236/**
12237 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
12238 * @pAdapter: Pointer to adapter
12239 *
12240 * This function is used to disconnect from previous connection
12241 *
12242 * Return: 0 for success, non-zero for failure
12243 */
12244static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
12245{
12246 unsigned long rc;
12247 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012248 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012249
12250 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12251
Jeff Johnson9edf9572016-10-03 15:24:49 -070012252 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053012253 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
12254 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
12255 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012256 hdd_conn_set_connection_state(pAdapter,
12257 eConnectionState_Disconnecting);
12258 /* Issue disconnect to CSR */
12259 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012260
12261 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12262 pAdapter->sessionId,
12263 eCSR_DISCONNECT_REASON_UNSPECIFIED);
12264 /*
12265 * Wait here instead of returning directly, this will block the
12266 * next connect command and allow processing of the scan for
12267 * ssid and the previous connect command in CSR. Else we might
12268 * hit some race conditions leading to SME and HDD out of sync.
12269 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012270 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012271 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
12272 } else if (0 != status) {
12273 hdd_err("csrRoamDisconnect failure, returned %d",
12274 (int)status);
12275 pHddStaCtx->staDebugState = status;
12276 result = -EINVAL;
12277 goto disconnected;
12278 }
12279
12280 rc = wait_for_completion_timeout(
12281 &pAdapter->disconnect_comp_var,
12282 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012283 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012284 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
12285 pAdapter->sessionId, pHddStaCtx->staDebugState);
12286 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012287 }
12288 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012289 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012290 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012291 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012292 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012293 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012294 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012295 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012296 }
12297 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012298disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012299 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12300 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012301}
12302
12303/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012304 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
12305 * @adapter: Pointer to the HDD adapter
12306 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070012307 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012308 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012309 * This function will start reassociation if prev_bssid is set and bssid/
12310 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012311 *
Naveen Rawat07332902016-07-27 09:13:17 -070012312 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012313 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053012314#if defined(CFG80211_CONNECT_PREV_BSSID) || \
12315 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070012316static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12317 struct cfg80211_connect_params *req,
12318 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012319{
Naveen Rawat07332902016-07-27 09:13:17 -070012320 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012321 const uint8_t *bssid = NULL;
12322 uint16_t channel = 0;
12323
12324 if (req->bssid)
12325 bssid = req->bssid;
12326 else if (req->bssid_hint)
12327 bssid = req->bssid_hint;
12328
12329 if (req->channel)
12330 channel = req->channel->hw_value;
12331 else if (req->channel_hint)
12332 channel = req->channel_hint->hw_value;
12333
12334 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070012335 reassoc = true;
12336 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012337 channel, MAC_ADDR_ARRAY(bssid));
12338 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012339 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070012340 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012341 }
Naveen Rawat07332902016-07-27 09:13:17 -070012342 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012343}
12344#else
Naveen Rawat07332902016-07-27 09:13:17 -070012345static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12346 struct cfg80211_connect_params *req,
12347 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012348{
Naveen Rawat07332902016-07-27 09:13:17 -070012349 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012350}
12351#endif
12352
12353/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012354 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
12355 * @wiphy: Pointer to wiphy
12356 * @dev: Pointer to network device
12357 * @req: Pointer to cfg80211 connect request
12358 *
12359 * This function is used to start the association process
12360 *
12361 * Return: 0 for success, non-zero for failure
12362 */
12363static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12364 struct net_device *ndev,
12365 struct cfg80211_connect_params *req)
12366{
12367 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012368 u16 channel;
12369#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
12370 const u8 *bssid_hint = req->bssid_hint;
12371#else
12372 const u8 *bssid_hint = NULL;
12373#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012374 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12375 hdd_context_t *pHddCtx;
12376
12377 ENTER();
12378
Anurag Chouhan6d760662016-02-20 16:05:43 +053012379 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012380 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012381 return -EINVAL;
12382 }
12383
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012384 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012385 TRACE_CODE_HDD_CFG80211_CONNECT,
12386 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012387 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012388 hdd_device_mode_to_string(pAdapter->device_mode),
12389 pAdapter->device_mode);
12390
Krunal Sonib4326f22016-03-10 13:05:51 -080012391 if (pAdapter->device_mode != QDF_STA_MODE &&
12392 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012393 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012394 hdd_device_mode_to_string(pAdapter->device_mode),
12395 pAdapter->device_mode);
12396 return -EINVAL;
12397 }
12398
12399 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12400 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012401 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012402 return -EINVAL;
12403 }
12404
12405 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012406 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012407 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012408
Naveen Rawat07332902016-07-27 09:13:17 -070012409 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012410 return status;
12411
Agrawal Ashishf156e942016-08-04 14:54:47 +053012412 wlan_hdd_disable_roaming(pAdapter);
12413
12414 /* Try disconnecting if already in connected state */
12415 status = wlan_hdd_try_disconnect(pAdapter);
12416 if (0 > status) {
12417 hdd_err("Failed to disconnect the existing connection");
12418 return -EALREADY;
12419 }
12420
12421 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012422 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012423 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012424 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012425 pAdapter->device_mode),
12426 req->channel->hw_value, HW_MODE_20_MHZ)) {
12427 hdd_err("This concurrency combination is not allowed");
12428 return -ECONNREFUSED;
12429 }
12430 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012431 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012432 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012433 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
12434 hdd_err("This concurrency combination is not allowed");
12435 return -ECONNREFUSED;
12436 }
12437 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012438
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012439 /*initialise security parameters */
12440 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
12441
12442 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012443 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012444 return status;
12445 }
12446
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012447 if (req->channel)
12448 channel = req->channel->hw_value;
12449 else
12450 channel = 0;
12451 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
12452 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012453 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012454 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012455 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012456 return status;
12457 }
12458 EXIT();
12459 return status;
12460}
12461
12462/**
12463 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
12464 * @wiphy: Pointer to wiphy
12465 * @dev: Pointer to network device
12466 * @req: Pointer to cfg80211 connect request
12467 *
12468 * Return: 0 for success, non-zero for failure
12469 */
12470static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12471 struct net_device *ndev,
12472 struct cfg80211_connect_params *req)
12473{
12474 int ret;
12475 cds_ssr_protect(__func__);
12476 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
12477 cds_ssr_unprotect(__func__);
12478
12479 return ret;
12480}
12481
12482/**
12483 * wlan_hdd_disconnect() - hdd disconnect api
12484 * @pAdapter: Pointer to adapter
12485 * @reason: Disconnect reason code
12486 *
12487 * This function is used to issue a disconnect request to SME
12488 *
12489 * Return: 0 for success, non-zero for failure
12490 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012491static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012492{
12493 int status, result = 0;
12494 unsigned long rc;
12495 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12496 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12497
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012498 ENTER();
12499
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012500 status = wlan_hdd_validate_context(pHddCtx);
12501
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012502 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012503 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012504
12505 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012506 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012507 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
12508 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012509 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012510 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
12511 INIT_COMPLETION(pAdapter->disconnect_comp_var);
12512
12513 /*issue disconnect */
12514
12515 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12516 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053012517 /*
12518 * Wait here instead of returning directly, this will block the next
12519 * connect command and allow processing of the scan for ssid and
12520 * the previous connect command in CSR. Else we might hit some
12521 * race conditions leading to SME and HDD out of sync.
12522 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012523 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012524 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012525 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012526 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012527 (int)status);
12528 pHddStaCtx->staDebugState = status;
12529 result = -EINVAL;
12530 goto disconnected;
12531 }
12532 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
12533 msecs_to_jiffies
12534 (WLAN_WAIT_TIME_DISCONNECT));
12535
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012536 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012537 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012538 result = -ETIMEDOUT;
12539 }
12540disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012541 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12542#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
12543 /* Sending disconnect event to userspace for kernel version < 3.11
12544 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
12545 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012546 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053012547 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
12548 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012549#endif
12550
12551 return result;
12552}
12553
12554/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012555 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
12556 * @reason: ieee80211 reason code.
12557 *
12558 * This utility function helps log string conversion of reason code.
12559 *
12560 * Return: string conversion of reason code, if match found;
12561 * "Unknown" otherwise.
12562 */
12563static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
12564{
12565 switch (reason) {
12566 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
12567 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
12568 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
12569 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
12570 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
12571 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
12572 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
12573 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
12574 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
12575 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
12576 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
12577 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
12578 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
12579 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
12580 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
12581 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
12582 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
12583 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
12584 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
12585 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
12586 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
12587 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
12588 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
12589 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
12590 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
12591 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
12592 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
12593 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
12594 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
12595 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
12596 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
12597 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
12598 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
12599 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
12600 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
12601 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
12602 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
12603 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
12604 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
12605 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
12606 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
12607 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
12608 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
12609 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
12610 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
12611 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
12612 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
12613 default:
12614 return "Unknown";
12615 }
12616}
12617
12618/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012619 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12620 * @wiphy: Pointer to wiphy
12621 * @dev: Pointer to network device
12622 * @reason: Disconnect reason code
12623 *
12624 * This function is used to issue a disconnect request to SME
12625 *
12626 * Return: 0 for success, non-zero for failure
12627 */
12628static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12629 struct net_device *dev, u16 reason)
12630{
12631 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12632 int status;
12633 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12634 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12635#ifdef FEATURE_WLAN_TDLS
12636 uint8_t staIdx;
12637#endif
12638
12639 ENTER();
12640
Anurag Chouhan6d760662016-02-20 16:05:43 +053012641 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012642 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012643 return -EINVAL;
12644 }
12645
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012646 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012647 TRACE_CODE_HDD_CFG80211_DISCONNECT,
12648 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012649 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012650 hdd_device_mode_to_string(pAdapter->device_mode),
12651 pAdapter->device_mode, reason);
12652
12653 status = wlan_hdd_validate_context(pHddCtx);
12654
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012655 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012656 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012657
12658 /* Issue disconnect request to SME, if station is in connected state */
12659 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
12660 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
12661 eCsrRoamDisconnectReason reasonCode =
12662 eCSR_DISCONNECT_REASON_UNSPECIFIED;
12663 hdd_scaninfo_t *pScanInfo;
12664
12665 switch (reason) {
12666 case WLAN_REASON_MIC_FAILURE:
12667 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
12668 break;
12669
12670 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
12671 case WLAN_REASON_DISASSOC_AP_BUSY:
12672 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
12673 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
12674 break;
12675
12676 case WLAN_REASON_PREV_AUTH_NOT_VALID:
12677 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
12678 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
12679 break;
12680
12681 case WLAN_REASON_DEAUTH_LEAVING:
12682 reasonCode =
12683 pHddCtx->config->
12684 gEnableDeauthToDisassocMap ?
12685 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
12686 eCSR_DISCONNECT_REASON_DEAUTH;
12687 break;
12688 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
12689 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
12690 break;
12691 default:
12692 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
12693 break;
12694 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012695 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012696 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012697 pScanInfo = &pAdapter->scan_info;
12698 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012699 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012700 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
12701 eCSR_SCAN_ABORT_DEFAULT);
12702 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053012703 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012704#ifdef FEATURE_WLAN_TDLS
12705 /* First clean up the tdls peers if any */
12706 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
12707 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
12708 pAdapter->sessionId)
12709 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
12710 uint8_t *mac;
12711 mac =
12712 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012713 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
12714 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012715 pHddCtx->tdlsConnInfo[staIdx].staId,
12716 pAdapter->sessionId,
12717 MAC_ADDR_ARRAY(mac));
12718 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
12719 (pAdapter),
12720 pAdapter->sessionId, mac);
12721 }
12722 }
12723#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012724 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012725 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012726 hdd_info("Disconnect request from user space with reason: %s",
12727 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012728 status = wlan_hdd_disconnect(pAdapter, reasonCode);
12729 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012730 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012731 return -EINVAL;
12732 }
12733 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012734 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012735 pHddStaCtx->conn_info.connState);
12736 }
12737
12738 return status;
12739}
12740
12741/**
12742 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12743 * @wiphy: Pointer to wiphy
12744 * @dev: Pointer to network device
12745 * @reason: Disconnect reason code
12746 *
12747 * Return: 0 for success, non-zero for failure
12748 */
12749static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12750 struct net_device *dev, u16 reason)
12751{
12752 int ret;
12753 cds_ssr_protect(__func__);
12754 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
12755 cds_ssr_unprotect(__func__);
12756
12757 return ret;
12758}
12759
12760/**
12761 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
12762 * @pAdapter: Pointer to adapter
12763 * @param: Pointer to IBSS parameters
12764 *
12765 * This function is used to initialize the security settings in IBSS mode
12766 *
12767 * Return: 0 for success, non-zero for failure
12768 */
12769static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
12770 struct cfg80211_ibss_params
12771 *params)
12772{
12773 int status = 0;
12774 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12775 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12776 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12777
12778 ENTER();
12779
12780 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012781 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012782 pHddStaCtx->ibss_enc_key_installed = 0;
12783
12784 if (params->ie_len && (NULL != params->ie)) {
12785 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12786 params->ie_len, WLAN_EID_RSN)) {
12787 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12788 encryptionType = eCSR_ENCRYPT_TYPE_AES;
12789 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
12790 tDot11fIEWPA dot11WPAIE;
12791 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
12792 u8 *ie;
12793
12794 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
12795 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12796 params->ie_len,
12797 DOT11F_EID_WPA);
12798 if (NULL != ie) {
12799 pWextState->wpaVersion =
12800 IW_AUTH_WPA_VERSION_WPA;
12801 /* Unpack the WPA IE */
12802 /* Skip past the EID byte and length byte - and four byte WiFi OUI */
12803 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
12804 &ie[2 + 4],
12805 ie[1] - 4, &dot11WPAIE);
12806 /*Extract the multicast cipher, the encType for unicast
12807 cipher for wpa-none is none */
12808 encryptionType =
12809 hdd_translate_wpa_to_csr_encryption_type
12810 (dot11WPAIE.multicast_cipher);
12811 }
12812 }
12813
12814 status =
12815 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
12816 params->ie_len);
12817
12818 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012819 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012820 return status;
12821 }
12822 }
12823
12824 pWextState->roamProfile.AuthType.authType[0] =
12825 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
12826
12827 if (params->privacy) {
12828 /* Security enabled IBSS, At this time there is no information
12829 * available about the security paramters, so initialise the
12830 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
12831 * The correct security parameters will be updated later in
12832 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
12833 * set inorder enable privacy bit in beacons
12834 */
12835
12836 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
12837 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012838 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012839 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
12840 pWextState->roamProfile.EncryptionType.numEntries = 1;
12841 pWextState->roamProfile.EncryptionType.encryptionType[0] =
12842 encryptionType;
12843 return status;
12844}
12845
12846/**
12847 * __wlan_hdd_cfg80211_join_ibss() - join ibss
12848 * @wiphy: Pointer to wiphy
12849 * @dev: Pointer to network device
12850 * @param: Pointer to IBSS join parameters
12851 *
12852 * This function is used to create/join an IBSS network
12853 *
12854 * Return: 0 for success, non-zero for failure
12855 */
12856static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
12857 struct net_device *dev,
12858 struct cfg80211_ibss_params *params)
12859{
12860 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12861 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12862 tCsrRoamProfile *pRoamProfile;
12863 int status;
12864 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12865 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053012866 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012867 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012868
12869 ENTER();
12870
Anurag Chouhan6d760662016-02-20 16:05:43 +053012871 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012872 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012873 return -EINVAL;
12874 }
12875
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012876 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012877 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
12878 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012879 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012880 hdd_device_mode_to_string(pAdapter->device_mode),
12881 pAdapter->device_mode);
12882
12883 status = wlan_hdd_validate_context(pHddCtx);
12884
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012885 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012886 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012887
12888 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053012889 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012890 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
12891 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
12892 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12893 int indx;
12894
12895 /* Get channel number */
12896 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012897 params->
12898 chandef.
12899 chan->
12900 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012901
12902 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
12903 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012904 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012905 return -EOPNOTSUPP;
12906 }
12907
12908 for (indx = 0; indx < numChans; indx++) {
12909 if (channelNum == validChan[indx]) {
12910 break;
12911 }
12912 }
12913 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012914 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012915 return -EINVAL;
12916 }
12917 }
12918
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012919 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012920 HW_MODE_20_MHZ)) {
12921 hdd_err("This concurrency combination is not allowed");
12922 return -ECONNREFUSED;
12923 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012924
Krunal Soni3091bcc2016-06-23 12:28:21 -070012925 status = qdf_reset_connection_update();
12926 if (!QDF_IS_STATUS_SUCCESS(status))
12927 hdd_err("ERR: clear event failed");
12928
12929 status = cds_current_connections_update(pAdapter->sessionId,
12930 channelNum,
12931 SIR_UPDATE_REASON_JOIN_IBSS);
12932 if (QDF_STATUS_E_FAILURE == status) {
12933 hdd_err("ERROR: connections update failed!!");
12934 return -EINVAL;
12935 }
12936
12937 if (QDF_STATUS_SUCCESS == status) {
12938 status = qdf_wait_for_connection_update();
12939 if (!QDF_IS_STATUS_SUCCESS(status)) {
12940 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012941 return -EINVAL;
12942 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012943 }
12944
12945 /*Try disconnecting if already in connected state */
12946 status = wlan_hdd_try_disconnect(pAdapter);
12947 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012948 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012949 return -EALREADY;
12950 }
12951
12952 pRoamProfile = &pWextState->roamProfile;
12953
12954 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012955 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012956 return -EINVAL;
12957 }
12958
12959 /* enable selected protection checks in IBSS mode */
12960 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
12961
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012962 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012963 WNI_CFG_IBSS_ATIM_WIN_SIZE,
12964 pHddCtx->config->
12965 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012966 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012967 }
12968
12969 /* BSSID is provided by upper layers hence no need to AUTO generate */
12970 if (NULL != params->bssid) {
12971 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012972 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012973 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012974 return -EIO;
12975 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012976 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012977 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
12978 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012979 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012980 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012981 return -EIO;
12982 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053012983 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012984 }
12985 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
12986 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
12987 pRoamProfile->beaconInterval = params->beacon_interval;
12988 else {
12989 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012990 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012991 params->beacon_interval, pRoamProfile->beaconInterval);
12992 }
12993
12994 /* Set Channel */
12995 if (channelNum) {
12996 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012997 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012998 pRoamProfile->ChannelInfo.numOfChannels = 1;
12999 pHddStaCtx->conn_info.operationChannel = channelNum;
13000 pRoamProfile->ChannelInfo.ChannelList =
13001 &pHddStaCtx->conn_info.operationChannel;
13002 }
13003
13004 /* Initialize security parameters */
13005 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
13006 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013007 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013008 return status;
13009 }
13010
13011 /* Issue connect start */
13012 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
13013 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013014 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013015 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070013016 operationChannel,
13017 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013018
13019 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013020 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013021 return status;
13022 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013023 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013024 return 0;
13025}
13026
13027/**
13028 * wlan_hdd_cfg80211_join_ibss() - join ibss
13029 * @wiphy: Pointer to wiphy
13030 * @dev: Pointer to network device
13031 * @param: Pointer to IBSS join parameters
13032 *
13033 * This function is used to create/join an IBSS network
13034 *
13035 * Return: 0 for success, non-zero for failure
13036 */
13037static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
13038 struct net_device *dev,
13039 struct cfg80211_ibss_params *params)
13040{
13041 int ret = 0;
13042
13043 cds_ssr_protect(__func__);
13044 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
13045 cds_ssr_unprotect(__func__);
13046
13047 return ret;
13048}
13049
13050/**
13051 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
13052 * @wiphy: Pointer to wiphy
13053 * @dev: Pointer to network device
13054 *
13055 * This function is used to leave an IBSS network
13056 *
13057 * Return: 0 for success, non-zero for failure
13058 */
13059static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13060 struct net_device *dev)
13061{
13062 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13063 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13064 tCsrRoamProfile *pRoamProfile;
13065 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13066 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013067 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013068 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013069 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013070
13071 ENTER();
13072
Anurag Chouhan6d760662016-02-20 16:05:43 +053013073 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013074 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013075 return -EINVAL;
13076 }
13077
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013078 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013079 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
13080 pAdapter->sessionId,
13081 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
13082 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013083 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013084 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013085
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013086 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013087 hdd_device_mode_to_string(pAdapter->device_mode),
13088 pAdapter->device_mode);
13089 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013090 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013091 return -EIO;
13092 }
13093
13094 pRoamProfile = &pWextState->roamProfile;
13095
13096 /* Issue disconnect only if interface type is set to IBSS */
13097 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013098 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013099 return -EINVAL;
13100 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013101 /* Clearing add IE of beacon */
13102 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
13103 sizeof(tSirMacAddr));
13104 updateIE.smeSessionId = pAdapter->sessionId;
13105 updateIE.ieBufferlength = 0;
13106 updateIE.pAdditionIEBuffer = NULL;
13107 updateIE.append = true;
13108 updateIE.notify = true;
13109 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
13110 &updateIE,
13111 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013112 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013113 }
13114
13115 /* Reset WNI_CFG_PROBE_RSP Flags */
13116 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013117
13118 /* Issue Disconnect request */
13119 INIT_COMPLETION(pAdapter->disconnect_comp_var);
13120 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13121 pAdapter->sessionId,
13122 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013123 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013124 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013125 hal_status);
13126 return -EAGAIN;
13127 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013128
13129 /* wait for mc thread to cleanup and then return to upper stack
13130 * so by the time upper layer calls the change interface, we are
13131 * all set to proceed further
13132 */
13133 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
13134 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
13135 if (!rc) {
13136 hdd_err("Failed to disconnect, timed out");
13137 return -ETIMEDOUT;
13138 }
13139
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013140 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013141 return 0;
13142}
13143
13144/**
13145 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
13146 * @wiphy: Pointer to wiphy
13147 * @dev: Pointer to network device
13148 *
13149 * This function is used to leave an IBSS network
13150 *
13151 * Return: 0 for success, non-zero for failure
13152 */
13153static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13154 struct net_device *dev)
13155{
13156 int ret = 0;
13157
13158 cds_ssr_protect(__func__);
13159 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
13160 cds_ssr_unprotect(__func__);
13161
13162 return ret;
13163}
13164
13165/**
13166 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13167 * @wiphy: Pointer to wiphy
13168 * @changed: Parameters changed
13169 *
13170 * This function is used to set the phy parameters. RTS Threshold/FRAG
13171 * Threshold/Retry Count etc.
13172 *
13173 * Return: 0 for success, non-zero for failure
13174 */
13175static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
13176 u32 changed)
13177{
13178 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13179 tHalHandle hHal = pHddCtx->hHal;
13180 int status;
13181
13182 ENTER();
13183
Anurag Chouhan6d760662016-02-20 16:05:43 +053013184 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013185 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013186 return -EINVAL;
13187 }
13188
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013189 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013190 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
13191 NO_SESSION, wiphy->rts_threshold));
13192 status = wlan_hdd_validate_context(pHddCtx);
13193
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013194 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013195 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013196
13197 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
13198 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
13199 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
13200
13201 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
13202 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013203 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013204 rts_threshold);
13205 return -EINVAL;
13206 }
13207
13208 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
13209 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013210 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013211 rts_threshold);
13212 return -EIO;
13213 }
13214
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013215 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013216 }
13217
13218 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
13219 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
13220 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
13221 wiphy->frag_threshold;
13222
13223 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
13224 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013225 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013226 frag_threshold);
13227 return -EINVAL;
13228 }
13229
13230 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
13231 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013232 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013233 frag_threshold);
13234 return -EIO;
13235 }
13236
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013237 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013238 }
13239
13240 if ((changed & WIPHY_PARAM_RETRY_SHORT)
13241 || (changed & WIPHY_PARAM_RETRY_LONG)) {
13242 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
13243 wiphy->retry_short : wiphy->retry_long;
13244
13245 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
13246 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013247 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013248 return -EINVAL;
13249 }
13250
13251 if (changed & WIPHY_PARAM_RETRY_SHORT) {
13252 if (0 != sme_cfg_set_int(hHal,
13253 WNI_CFG_LONG_RETRY_LIMIT,
13254 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013255 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013256 retry_value);
13257 return -EIO;
13258 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013259 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013260 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
13261 if (0 != sme_cfg_set_int(hHal,
13262 WNI_CFG_SHORT_RETRY_LIMIT,
13263 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013264 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013265 retry_value);
13266 return -EIO;
13267 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013268 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013269 }
13270 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013271 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013272 return 0;
13273}
13274
13275/**
13276 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13277 * @wiphy: Pointer to wiphy
13278 * @changed: Parameters changed
13279 *
13280 * Return: 0 for success, non-zero for failure
13281 */
13282static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
13283{
13284 int ret;
13285
13286 cds_ssr_protect(__func__);
13287 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
13288 cds_ssr_unprotect(__func__);
13289
13290 return ret;
13291}
13292
13293/**
13294 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
13295 * key
13296 * @wiphy: Pointer to wiphy
13297 * @dev: Pointer to network device
13298 * @key_index: Key index
13299 *
13300 * Return: 0
13301 */
13302static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13303 struct net_device *netdev,
13304 u8 key_index)
13305{
13306 ENTER();
13307 return 0;
13308}
13309
13310/**
13311 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
13312 * wlan_hdd_set_default_mgmt_key
13313 * @wiphy: pointer to wiphy
13314 * @netdev: pointer to net_device structure
13315 * @key_index: key index
13316 *
13317 * Return: 0 on success, error number on failure
13318 */
13319static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13320 struct net_device *netdev,
13321 u8 key_index)
13322{
13323 int ret;
13324
13325 cds_ssr_protect(__func__);
13326 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
13327 cds_ssr_unprotect(__func__);
13328
13329 return ret;
13330}
13331
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013332/**
13333 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
13334 * @wiphy: Pointer to wiphy
13335 * @dev: Pointer to network device
13336 * @params: Pointer to tx queue parameters
13337 *
13338 * Return: 0
13339 */
13340static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
13341 struct net_device *dev,
13342 struct ieee80211_txq_params *params)
13343{
13344 ENTER();
13345 return 0;
13346}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013347
13348/**
13349 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
13350 * @wiphy: pointer to wiphy
13351 * @netdev: pointer to net_device structure
13352 * @params: pointer to ieee80211_txq_params
13353 *
13354 * Return: 0 on success, error number on failure
13355 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013356static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
13357 struct net_device *dev,
13358 struct ieee80211_txq_params *params)
13359{
13360 int ret;
13361
13362 cds_ssr_protect(__func__);
13363 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
13364 cds_ssr_unprotect(__func__);
13365
13366 return ret;
13367}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013368
13369/**
13370 * __wlan_hdd_cfg80211_del_station() - delete station v2
13371 * @wiphy: Pointer to wiphy
13372 * @param: Pointer to delete station parameter
13373 *
13374 * Return: 0 for success, non-zero for failure
13375 */
13376static
13377int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13378 struct net_device *dev,
13379 struct tagCsrDelStaParams *pDelStaParams)
13380{
13381 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13382 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013383 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013384 hdd_hostapd_state_t *hapd_state;
13385 int status;
13386 uint8_t staId;
13387 uint8_t *mac;
13388
13389 ENTER();
13390
Anurag Chouhan6d760662016-02-20 16:05:43 +053013391 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013392 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013393 return -EINVAL;
13394 }
13395
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013396 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013397 TRACE_CODE_HDD_CFG80211_DEL_STA,
13398 pAdapter->sessionId, pAdapter->device_mode));
13399
13400 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13401 status = wlan_hdd_validate_context(pHddCtx);
13402
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013403 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013404 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013405
13406 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
13407
Krunal Sonib4326f22016-03-10 13:05:51 -080013408 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
13409 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013410
13411 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
13412 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013413 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013414 return 0;
13415 }
13416
Anurag Chouhanc5548422016-02-24 18:33:27 +053013417 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013418 uint16_t i;
13419 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
13420 if ((pAdapter->aStaInfo[i].isUsed) &&
13421 (!pAdapter->aStaInfo[i].
13422 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013423 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013424 mac,
13425 pAdapter->aStaInfo[i].
13426 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013427 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013428 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13429 hdd_ipa_wlan_evt(pAdapter,
13430 pAdapter->
13431 aStaInfo[i].
13432 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013433 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013434 mac);
13435 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013436 hdd_notice("Delete STA with MAC::"
13437 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013438 MAC_ADDR_ARRAY(mac));
13439
13440 if (pHddCtx->dev_dfs_cac_status ==
13441 DFS_CAC_IN_PROGRESS)
13442 goto fn_end;
13443
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013444 qdf_event_reset(&hapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013445 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053013446 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013447 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013448 hdd_softap_sta_deauth(pAdapter,
13449 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013450 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013451 pAdapter->aStaInfo[i].
13452 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013453 qdf_status =
13454 qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013455 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013456 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013457 if (!QDF_IS_STATUS_SUCCESS(
13458 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013459 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013460 }
13461 }
13462 }
13463 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013464 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013465 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013466 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013467 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013468 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013469 hdd_notice("Skip DEL STA as this is not used::"
13470 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013471 MAC_ADDR_ARRAY(mac));
13472 return -ENOENT;
13473 }
13474
13475 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13476 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013477 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013478 }
13479
13480 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
13481 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013482 hdd_notice("Skip DEL STA as deauth is in progress::"
13483 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013484 MAC_ADDR_ARRAY(mac));
13485 return -ENOENT;
13486 }
13487
13488 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
13489
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013490 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013491 MAC_ADDR_ARRAY(mac));
13492
13493 /* Case: SAP in ACS selected DFS ch and client connected
13494 * Now Radar detected. Then if random channel is another
13495 * DFS ch then new CAC is initiated and no TX allowed.
13496 * So do not send any mgmt frames as it will timeout
13497 * during CAC.
13498 */
13499
13500 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
13501 goto fn_end;
13502
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013503 qdf_event_reset(&hapd_state->qdf_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053013504 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
13505 (pAdapter), pAdapter->sessionId,
13506 (uint8_t *)&pDelStaParams->peerMacAddr,
13507 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013508 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013509 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013510 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013511 pAdapter->aStaInfo[staId].isDeauthInProgress =
13512 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013513 hdd_notice("STA removal failed for ::"
13514 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013515 MAC_ADDR_ARRAY(mac));
13516 return -ENOENT;
13517 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053013518 qdf_status = qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013519 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013520 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013521 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013522 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013523 }
13524 }
13525 }
13526
13527fn_end:
13528 EXIT();
13529 return 0;
13530}
13531
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013532#if defined(USE_CFG80211_DEL_STA_V2)
13533/**
13534 * wlan_hdd_del_station() - delete station wrapper
13535 * @adapter: pointer to the hdd adapter
13536 *
13537 * Return: None
13538 */
13539void wlan_hdd_del_station(hdd_adapter_t *adapter)
13540{
13541 struct station_del_parameters del_sta;
13542 del_sta.mac = NULL;
13543 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
13544 del_sta.reason_code = eCsrForcedDeauthSta;
13545
13546 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
13547 &del_sta);
13548}
13549#else
13550void wlan_hdd_del_station(hdd_adapter_t *adapter)
13551{
13552 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
13553}
13554#endif
13555
13556#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013557/**
13558 * wlan_hdd_cfg80211_del_station() - delete station v2
13559 * @wiphy: Pointer to wiphy
13560 * @param: Pointer to delete station parameter
13561 *
13562 * Return: 0 for success, non-zero for failure
13563 */
13564int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13565 struct net_device *dev,
13566 struct station_del_parameters *param)
13567#else
13568/**
13569 * wlan_hdd_cfg80211_del_station() - delete station
13570 * @wiphy: Pointer to wiphy
13571 * @mac: Pointer to station mac address
13572 *
13573 * Return: 0 for success, non-zero for failure
13574 */
13575#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13576int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13577 struct net_device *dev,
13578 const uint8_t *mac)
13579#else
13580int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13581 struct net_device *dev,
13582 uint8_t *mac)
13583#endif
13584#endif
13585{
13586 int ret;
13587 struct tagCsrDelStaParams delStaParams;
13588
13589 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013590#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013591 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013592 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013593 return -EINVAL;
13594 }
13595 wlansap_populate_del_sta_params(param->mac, param->reason_code,
13596 param->subtype, &delStaParams);
13597#else
13598 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
13599 (SIR_MAC_MGMT_DEAUTH >> 4),
13600 &delStaParams);
13601#endif
13602 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
13603 cds_ssr_unprotect(__func__);
13604
13605 return ret;
13606}
13607
13608/**
13609 * __wlan_hdd_cfg80211_add_station() - add station
13610 * @wiphy: Pointer to wiphy
13611 * @mac: Pointer to station mac address
13612 * @pmksa: Pointer to add station parameter
13613 *
13614 * Return: 0 for success, non-zero for failure
13615 */
13616static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13617 struct net_device *dev,
13618 const uint8_t *mac,
13619 struct station_parameters *params)
13620{
13621 int status = -EPERM;
13622#ifdef FEATURE_WLAN_TDLS
13623 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13624 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13625 u32 mask, set;
13626
13627 ENTER();
13628
Anurag Chouhan6d760662016-02-20 16:05:43 +053013629 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013630 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013631 return -EINVAL;
13632 }
13633
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013634 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013635 TRACE_CODE_HDD_CFG80211_ADD_STA,
13636 pAdapter->sessionId, params->listen_interval));
13637
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013638 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013639 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013640
13641 mask = params->sta_flags_mask;
13642
13643 set = params->sta_flags_set;
13644
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013645 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013646 MAC_ADDR_ARRAY(mac));
13647
13648 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13649 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13650 status =
13651 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
13652 }
13653 }
13654#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013655 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013656 return status;
13657}
13658
13659/**
13660 * wlan_hdd_cfg80211_add_station() - add station
13661 * @wiphy: Pointer to wiphy
13662 * @mac: Pointer to station mac address
13663 * @pmksa: Pointer to add station parameter
13664 *
13665 * Return: 0 for success, non-zero for failure
13666 */
13667#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13668static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13669 struct net_device *dev,
13670 const uint8_t *mac,
13671 struct station_parameters *params)
13672#else
13673static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13674 struct net_device *dev, uint8_t *mac,
13675 struct station_parameters *params)
13676#endif
13677{
13678 int ret;
13679
13680 cds_ssr_protect(__func__);
13681 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
13682 cds_ssr_unprotect(__func__);
13683
13684 return ret;
13685}
13686
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013687/**
13688 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
13689 * @wiphy: Pointer to wiphy
13690 * @dev: Pointer to network device
13691 * @pmksa: Pointer to set pmksa parameter
13692 *
13693 * Return: 0 for success, non-zero for failure
13694 */
13695static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13696 struct net_device *dev,
13697 struct cfg80211_pmksa *pmksa)
13698{
13699 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13700 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13701 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013702 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013703 int status;
13704 tPmkidCacheInfo pmk_id;
13705
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013706 ENTER();
13707
Anurag Chouhan6d760662016-02-20 16:05:43 +053013708 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013709 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013710 return -EINVAL;
13711 }
13712
13713 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013714 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013715 return -EINVAL;
13716 }
13717
13718 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013719 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013720 pmksa->bssid, pmksa->pmkid);
13721 return -EINVAL;
13722 }
13723
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013724 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013725 MAC_ADDR_ARRAY(pmksa->bssid));
13726
13727 status = wlan_hdd_validate_context(pHddCtx);
13728
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013729 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013730 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013731
13732 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13733
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013734 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
13735 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013736
13737 /* Add to the PMKSA ID Cache in CSR */
13738 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
13739 &pmk_id, 1, false);
13740
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013741 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013742 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
13743 pAdapter->sessionId, result));
13744
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013745 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013746 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013747}
13748
13749/**
13750 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
13751 * @wiphy: Pointer to wiphy
13752 * @dev: Pointer to network device
13753 * @pmksa: Pointer to set pmksa parameter
13754 *
13755 * Return: 0 for success, non-zero for failure
13756 */
13757static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13758 struct net_device *dev,
13759 struct cfg80211_pmksa *pmksa)
13760{
13761 int ret;
13762
13763 cds_ssr_protect(__func__);
13764 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
13765 cds_ssr_unprotect(__func__);
13766
13767 return ret;
13768}
13769
13770/**
13771 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
13772 * @wiphy: Pointer to wiphy
13773 * @dev: Pointer to network device
13774 * @pmksa: Pointer to pmksa parameter
13775 *
13776 * Return: 0 for success, non-zero for failure
13777 */
13778static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
13779 struct net_device *dev,
13780 struct cfg80211_pmksa *pmksa)
13781{
13782 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13783 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13784 tHalHandle halHandle;
13785 int status = 0;
13786
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013787 ENTER();
13788
Anurag Chouhan6d760662016-02-20 16:05:43 +053013789 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013790 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013791 return -EINVAL;
13792 }
13793
13794 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013795 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013796 return -EINVAL;
13797 }
13798
13799 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013800 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013801 return -EINVAL;
13802 }
13803
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013804 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013805 MAC_ADDR_ARRAY(pmksa->bssid));
13806
13807 status = wlan_hdd_validate_context(pHddCtx);
13808
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013809 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013810 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013811
13812 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13813
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013814 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053013815 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
13816 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013817 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013818 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013819 sme_roam_del_pmkid_from_cache(halHandle,
13820 pAdapter->sessionId, pmksa->bssid,
13821 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013822 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013823 MAC_ADDR_ARRAY(pmksa->bssid));
13824 status = -EINVAL;
13825 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013826 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013827 return status;
13828}
13829
13830/**
13831 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
13832 * @wiphy: Pointer to wiphy
13833 * @dev: Pointer to network device
13834 * @pmksa: Pointer to pmksa parameter
13835 *
13836 * Return: 0 for success, non-zero for failure
13837 */
13838static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
13839 struct net_device *dev,
13840 struct cfg80211_pmksa *pmksa)
13841{
13842 int ret;
13843
13844 cds_ssr_protect(__func__);
13845 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
13846 cds_ssr_unprotect(__func__);
13847
13848 return ret;
13849
13850}
13851
13852/**
13853 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
13854 * @wiphy: Pointer to wiphy
13855 * @dev: Pointer to network device
13856 *
13857 * Return: 0 for success, non-zero for failure
13858 */
13859static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
13860 struct net_device *dev)
13861{
13862 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13863 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13864 tHalHandle halHandle;
13865 int status = 0;
13866
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013867 ENTER();
13868
Anurag Chouhan6d760662016-02-20 16:05:43 +053013869 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013870 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013871 return -EINVAL;
13872 }
13873
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013874 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013875
13876 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13877 status = wlan_hdd_validate_context(pHddCtx);
13878
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013879 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013880 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013881
13882 /* Retrieve halHandle */
13883 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13884
13885 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013886 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013887 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
13888 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013889 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013890 status = -EINVAL;
13891 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013892 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013893 return status;
13894}
13895
13896/**
13897 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
13898 * @wiphy: Pointer to wiphy
13899 * @dev: Pointer to network device
13900 *
13901 * Return: 0 for success, non-zero for failure
13902 */
13903static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
13904 struct net_device *dev)
13905{
13906 int ret;
13907
13908 cds_ssr_protect(__func__);
13909 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
13910 cds_ssr_unprotect(__func__);
13911
13912 return ret;
13913}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013914
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080013915#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013916/**
13917 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
13918 * @wiphy: Pointer to wiphy
13919 * @dev: Pointer to network device
13920 * @ftie: Pointer to fast transition ie parameter
13921 *
13922 * Return: 0 for success, non-zero for failure
13923 */
13924static int
13925__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
13926 struct net_device *dev,
13927 struct cfg80211_update_ft_ies_params *ftie)
13928{
13929 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
13930 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13931 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13932 int status;
13933
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013934 ENTER();
13935
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013936 status = wlan_hdd_validate_context(hdd_ctx);
13937 if (status)
13938 return status;
13939
Anurag Chouhan6d760662016-02-20 16:05:43 +053013940 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013941 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013942 return -EINVAL;
13943 }
13944
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013945 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013946 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
13947 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
13948 /* Added for debug on reception of Re-assoc Req. */
13949 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013950 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013951 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013952 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013953 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013954 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013955 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013956
13957 /* Pass the received FT IEs to SME */
13958 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
13959 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013960 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013961 return 0;
13962}
13963
13964/**
13965 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
13966 * @wiphy: Pointer to wiphy
13967 * @dev: Pointer to network device
13968 * @ftie: Pointer to fast transition ie parameter
13969 *
13970 * Return: 0 for success, non-zero for failure
13971 */
13972static int
13973wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
13974 struct net_device *dev,
13975 struct cfg80211_update_ft_ies_params *ftie)
13976{
13977 int ret;
13978
13979 cds_ssr_protect(__func__);
13980 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
13981 cds_ssr_unprotect(__func__);
13982
13983 return ret;
13984}
13985#endif
13986
13987#ifdef WLAN_FEATURE_GTK_OFFLOAD
13988/**
13989 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
13990 * @callbackContext: Callback context
13991 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
13992 *
13993 * Callback rountine called upon receiving response for get offload info
13994 *
13995 * Return: none
13996 */
13997void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
13998 tpSirGtkOffloadGetInfoRspParams
13999 pGtkOffloadGetInfoRsp)
14000{
14001 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
14002 uint8_t tempReplayCounter[8];
14003 hdd_station_ctx_t *pHddStaCtx;
14004
14005 ENTER();
14006
14007 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014008 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014009 return;
14010 }
14011
14012 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014013 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014014 return;
14015 }
14016
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014017 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014018 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014019 return;
14020 }
14021
14022 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14023 /* Update replay counter */
14024 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
14025 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14026
14027 {
14028 /* changing from little to big endian since supplicant
14029 * works on big endian format
14030 */
14031 int i;
14032 uint8_t *p =
14033 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
14034
14035 for (i = 0; i < 8; i++) {
14036 tempReplayCounter[7 - i] = (uint8_t) p[i];
14037 }
14038 }
14039
14040 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014041 cfg80211_gtk_rekey_notify(pAdapter->dev,
14042 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014043 tempReplayCounter, GFP_KERNEL);
14044}
14045
14046/**
14047 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14048 * @wiphy: Pointer to wiphy
14049 * @dev: Pointer to network device
14050 * @data: Pointer to rekey data
14051 *
14052 * This function is used to offload GTK rekeying job to the firmware.
14053 *
14054 * Return: 0 for success, non-zero for failure
14055 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014056static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014057int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14058 struct net_device *dev,
14059 struct cfg80211_gtk_rekey_data *data)
14060{
14061 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14062 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14063 hdd_station_ctx_t *pHddStaCtx;
14064 tHalHandle hHal;
14065 int result;
14066 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014067 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014068
14069 ENTER();
14070
Anurag Chouhan6d760662016-02-20 16:05:43 +053014071 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014072 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014073 return -EINVAL;
14074 }
14075
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014076 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014077 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
14078 pAdapter->sessionId, pAdapter->device_mode));
14079
14080 result = wlan_hdd_validate_context(pHddCtx);
14081
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014082 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014083 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014084
14085 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14086 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14087 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014088 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014089 return -EAGAIN;
14090 }
14091
14092 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
14093 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
14094 NL80211_KCK_LEN);
14095 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
14096 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053014097 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014098 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014099 {
14100 /* changing from big to little endian since driver
14101 * works on little endian format
14102 */
14103 uint8_t *p =
14104 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
14105 ullKeyReplayCounter;
14106 int i;
14107
14108 for (i = 0; i < 8; i++) {
14109 p[7 - i] = data->replay_ctr[i];
14110 }
14111 }
14112
14113 if (true == pHddCtx->hdd_wlan_suspended) {
14114 /* if wlan is suspended, enable GTK offload directly from here */
14115 memcpy(&hddGtkOffloadReqParams,
14116 &pHddStaCtx->gtkOffloadReqParams,
14117 sizeof(tSirGtkOffloadParams));
14118 status =
14119 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
14120 pAdapter->sessionId);
14121
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014122 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014123 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014124 status);
14125 return -EINVAL;
14126 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014127 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014128 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014129 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014130 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014131 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014132 return result;
14133}
14134
14135/**
14136 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14137 * @wiphy: Pointer to wiphy
14138 * @dev: Pointer to network device
14139 * @data: Pointer to rekey data
14140 *
14141 * This function is used to offload GTK rekeying job to the firmware.
14142 *
14143 * Return: 0 for success, non-zero for failure
14144 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014145static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014146int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14147 struct net_device *dev,
14148 struct cfg80211_gtk_rekey_data *data)
14149{
14150 int ret;
14151
14152 cds_ssr_protect(__func__);
14153 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
14154 cds_ssr_unprotect(__func__);
14155
14156 return ret;
14157}
14158#endif /*WLAN_FEATURE_GTK_OFFLOAD */
14159
14160/**
14161 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
14162 * @wiphy: Pointer to wiphy
14163 * @dev: Pointer to network device
14164 * @param: Pointer to access control parameter
14165 *
14166 * Return: 0 for success, non-zero for failure
14167 */
14168static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14169 struct net_device *dev,
14170 const struct cfg80211_acl_data *params)
14171{
14172 int i;
14173 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14174 hdd_hostapd_state_t *pHostapdState;
14175 tsap_Config_t *pConfig;
14176 v_CONTEXT_t p_cds_context = NULL;
14177 hdd_context_t *pHddCtx;
14178 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014179 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014180
14181 ENTER();
14182
Anurag Chouhan6d760662016-02-20 16:05:43 +053014183 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014184 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014185 return -EINVAL;
14186 }
14187
14188 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014189 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014190 return -EINVAL;
14191 }
14192
14193 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14194 status = wlan_hdd_validate_context(pHddCtx);
14195
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014196 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014197 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014198
14199 p_cds_context = pHddCtx->pcds_context;
14200 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14201
14202 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014203 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014204 return -EINVAL;
14205 }
14206
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014207 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014208 params->n_acl_entries);
14209
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014210 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014211 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
14212 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080014213 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014214 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
14215
14216 /* default value */
14217 pConfig->num_accept_mac = 0;
14218 pConfig->num_deny_mac = 0;
14219
14220 /**
14221 * access control policy
14222 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
14223 * listed in hostapd.deny file.
14224 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
14225 * listed in hostapd.accept file.
14226 */
14227 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
14228 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
14229 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
14230 params->acl_policy) {
14231 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
14232 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014233 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014234 params->acl_policy);
14235 return -ENOTSUPP;
14236 }
14237
14238 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
14239 pConfig->num_accept_mac = params->n_acl_entries;
14240 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014241 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
14242 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014243 MAC_ADDR_ARRAY(
14244 params->mac_addrs[i].addr));
14245
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014246 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014247 params->mac_addrs[i].addr,
14248 sizeof(qcmacaddr));
14249 }
14250 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
14251 pConfig->num_deny_mac = params->n_acl_entries;
14252 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014253 hdd_notice("** Add ACL MAC entry %i in BlackList :"
14254 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014255 MAC_ADDR_ARRAY(
14256 params->mac_addrs[i].addr));
14257
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014258 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014259 params->mac_addrs[i].addr,
14260 sizeof(qcmacaddr));
14261 }
14262 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070014263 qdf_status = wlansap_set_mac_acl(
14264 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014265 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014266 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014267 return -EINVAL;
14268 }
14269 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014270 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014271 hdd_device_mode_to_string(pAdapter->device_mode),
14272 pAdapter->device_mode);
14273 return -EINVAL;
14274 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014275 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014276 return 0;
14277}
14278
14279/**
14280 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
14281 * __wlan_hdd_cfg80211_set_mac_acl
14282 * @wiphy: pointer to wiphy structure
14283 * @dev: pointer to net_device
14284 * @params: pointer to cfg80211_acl_data
14285 *
14286 * Return; 0 on success, error number otherwise
14287 */
14288static int
14289wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14290 struct net_device *dev,
14291 const struct cfg80211_acl_data *params)
14292{
14293 int ret;
14294
14295 cds_ssr_protect(__func__);
14296 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
14297 cds_ssr_unprotect(__func__);
14298
14299 return ret;
14300}
14301
14302#ifdef WLAN_NL80211_TESTMODE
14303#ifdef FEATURE_WLAN_LPHB
14304/**
14305 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
14306 * @pHddCtx: Pointer to hdd context
14307 * @lphbInd: Pointer to low power heart beat indication parameter
14308 *
14309 * Return: none
14310 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014311static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
14312 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014313{
14314 struct sk_buff *skb;
14315
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014316 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014317
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014318 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014319 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014320
14321 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014322 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014323 return;
14324 }
14325
14326 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
14327 wiphy, sizeof(tSirLPHBInd),
14328 GFP_ATOMIC);
14329 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014330 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014331 return;
14332 }
14333
14334 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014335 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014336 goto nla_put_failure;
14337 }
14338 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014339 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014340 goto nla_put_failure;
14341 }
14342 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014343 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014344 goto nla_put_failure;
14345 }
14346 cfg80211_testmode_event(skb, GFP_ATOMIC);
14347 return;
14348
14349nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014350 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014351 kfree_skb(skb);
14352
14353 return;
14354}
14355#endif /* FEATURE_WLAN_LPHB */
14356
14357/**
14358 * __wlan_hdd_cfg80211_testmode() - test mode
14359 * @wiphy: Pointer to wiphy
14360 * @data: Data pointer
14361 * @len: Data length
14362 *
14363 * Return: 0 for success, non-zero for failure
14364 */
14365static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14366 void *data, int len)
14367{
14368 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
14369 int err;
14370 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14371
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014372 ENTER();
14373
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014374 err = wlan_hdd_validate_context(pHddCtx);
14375 if (err)
14376 return err;
14377
14378 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
14379 len, wlan_hdd_tm_policy);
14380 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014381 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014382 return err;
14383 }
14384
14385 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014386 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014387 return -EINVAL;
14388 }
14389
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014390 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014391 TRACE_CODE_HDD_CFG80211_TESTMODE,
14392 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014393 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
14394#ifdef FEATURE_WLAN_LPHB
14395 /* Low Power Heartbeat configuration request */
14396 case WLAN_HDD_TM_CMD_WLAN_HB:
14397 {
14398 int buf_len;
14399 void *buf;
14400 tSirLPHBReq *hb_params = NULL;
14401 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014402 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014403
14404 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014405 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014406 return -EINVAL;
14407 }
14408
14409 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14410 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14411
14412 hb_params_temp = (tSirLPHBReq *) buf;
14413 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
14414 && (hb_params_temp->params.lphbTcpParamReq.
14415 timePeriodSec == 0))
14416 return -EINVAL;
14417
14418 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014419 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014420 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014421 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014422 return -ENOMEM;
14423 }
14424
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014425 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014426 smeStatus =
14427 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
14428 hb_params,
14429 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014430 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014431 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014432 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014433 }
14434 return 0;
14435 }
14436#endif /* FEATURE_WLAN_LPHB */
14437
14438#if defined(QCA_WIFI_FTM)
14439 case WLAN_HDD_TM_CMD_WLAN_FTM:
14440 {
14441 int buf_len;
14442 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014443 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014444 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014445 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014446 return -EINVAL;
14447 }
14448
14449 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14450 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14451
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014452 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014453
14454 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
14455
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014456 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014457 err = -EBUSY;
14458 break;
14459 }
14460#endif
14461
14462 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014463 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014464 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
14465 return -EOPNOTSUPP;
14466 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014467 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014468 return err;
14469}
14470
14471/**
14472 * wlan_hdd_cfg80211_testmode() - test mode
14473 * @wiphy: Pointer to wiphy
14474 * @dev: Pointer to network device
14475 * @data: Data pointer
14476 * @len: Data length
14477 *
14478 * Return: 0 for success, non-zero for failure
14479 */
14480static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14481#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
14482 struct wireless_dev *wdev,
14483#endif
14484 void *data, int len)
14485{
14486 int ret;
14487
14488 cds_ssr_protect(__func__);
14489 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
14490 cds_ssr_unprotect(__func__);
14491
14492 return ret;
14493}
14494
14495#if defined(QCA_WIFI_FTM)
14496/**
14497 * wlan_hdd_testmode_rx_event() - test mode rx event handler
14498 * @buf: Pointer to buffer
14499 * @buf_len: Buffer length
14500 *
14501 * Return: none
14502 */
14503void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
14504{
14505 struct sk_buff *skb;
14506 hdd_context_t *hdd_ctx;
14507
14508 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014509 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014510 return;
14511 }
14512
Anurag Chouhan6d760662016-02-20 16:05:43 +053014513 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014514 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014515 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014516 return;
14517 }
14518
14519 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
14520 buf_len, GFP_KERNEL);
14521 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014522 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014523 return;
14524 }
14525
14526 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
14527 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
14528 goto nla_put_failure;
14529
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014530 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014531
14532 cfg80211_testmode_event(skb, GFP_KERNEL);
14533 return;
14534
14535nla_put_failure:
14536 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014537 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014538}
14539#endif
14540#endif /* CONFIG_NL80211_TESTMODE */
14541
14542#ifdef QCA_HT_2040_COEX
14543/**
14544 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14545 * @wiphy: Pointer to wiphy
14546 * @dev: Pointer to network device
14547 * @chandef: Pointer to channel definition parameter
14548 *
14549 * Return: 0 for success, non-zero for failure
14550 */
14551static int
14552__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14553 struct net_device *dev,
14554 struct cfg80211_chan_def *chandef)
14555{
14556 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14557 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014558 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014559 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053014560 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014561
Anurag Chouhan6d760662016-02-20 16:05:43 +053014562 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014563 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014564 return -EINVAL;
14565 }
14566
14567 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14568 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053014569 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014570 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014571
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014572 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014573 sme_get_config_param(pHddCtx->hHal, &sme_config);
14574 switch (chandef->width) {
14575 case NL80211_CHAN_WIDTH_20:
14576 if (sme_config.csrConfig.channelBondingMode24GHz !=
14577 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14578 sme_config.csrConfig.channelBondingMode24GHz =
14579 eCSR_INI_SINGLE_CHANNEL_CENTERED;
14580 sme_update_config(pHddCtx->hHal, &sme_config);
14581 cbModeChange = true;
14582 }
14583 break;
14584
14585 case NL80211_CHAN_WIDTH_40:
14586 if (sme_config.csrConfig.channelBondingMode24GHz ==
14587 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14588 if (NL80211_CHAN_HT40MINUS ==
14589 cfg80211_get_chandef_type(chandef))
14590 sme_config.csrConfig.channelBondingMode24GHz =
14591 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
14592 else
14593 sme_config.csrConfig.channelBondingMode24GHz =
14594 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
14595 sme_update_config(pHddCtx->hHal, &sme_config);
14596 cbModeChange = true;
14597 }
14598 break;
14599
14600 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014601 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014602 return -EINVAL;
14603 }
14604
14605 if (!cbModeChange)
14606 return 0;
14607
Krunal Sonib4326f22016-03-10 13:05:51 -080014608 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014609 return 0;
14610
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014611 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014612 sme_config.csrConfig.channelBondingMode24GHz);
14613
14614 /* Change SAP ht2040 mode */
14615 status = hdd_set_sap_ht2040_mode(pAdapter,
14616 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014617 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014618 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014619 return -EINVAL;
14620 }
14621
14622 return 0;
14623}
14624
14625/**
14626 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14627 * @wiphy: Pointer to wiphy
14628 * @dev: Pointer to network device
14629 * @chandef: Pointer to channel definition parameter
14630 *
14631 * Return: 0 for success, non-zero for failure
14632 */
14633static int
14634wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14635 struct net_device *dev,
14636 struct cfg80211_chan_def *chandef)
14637{
14638 int ret;
14639
14640 cds_ssr_protect(__func__);
14641 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
14642 cds_ssr_unprotect(__func__);
14643
14644 return ret;
14645}
14646#endif
14647
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014648#ifdef CHANNEL_SWITCH_SUPPORTED
14649/**
14650 * __wlan_hdd_cfg80211_channel_switch()- function to switch
14651 * channel in SAP/GO
14652 * @wiphy: wiphy pointer
14653 * @dev: dev pointer.
14654 * @csa_params: Change channel params
14655 *
14656 * This function is called to switch channel in SAP/GO
14657 *
14658 * Return: 0 if success else return non zero
14659 */
14660static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14661 struct net_device *dev,
14662 struct cfg80211_csa_settings *csa_params)
14663{
14664 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
14665 hdd_context_t *hdd_ctx;
14666 uint8_t channel;
14667 uint16_t freq;
14668 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080014669 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014670
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014671 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014672 csa_params->chandef.chan->center_freq);
14673
14674 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
14675 ret = wlan_hdd_validate_context(hdd_ctx);
14676
14677 if (0 != ret)
14678 return ret;
14679
Krunal Sonib4326f22016-03-10 13:05:51 -080014680 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
14681 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014682 return -ENOTSUPP;
14683
14684 freq = csa_params->chandef.chan->center_freq;
14685 channel = cds_freq_to_chan(freq);
14686
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053014687 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
14688
14689 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014690 return ret;
14691}
14692
14693/**
14694 * wlan_hdd_cfg80211_channel_switch()- function to switch
14695 * channel in SAP/GO
14696 * @wiphy: wiphy pointer
14697 * @dev: dev pointer.
14698 * @csa_params: Change channel params
14699 *
14700 * This function is called to switch channel in SAP/GO
14701 *
14702 * Return: 0 if success else return non zero
14703 */
14704static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14705 struct net_device *dev,
14706 struct cfg80211_csa_settings *csa_params)
14707{
14708 int ret;
14709
14710 cds_ssr_protect(__func__);
14711 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
14712 cds_ssr_unprotect(__func__);
14713 return ret;
14714}
14715#endif
14716
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014717/**
14718 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
14719 * translation from NL to policy manager type
14720 * @type: Generic connection mode type defined in NL
14721 *
14722 *
14723 * This function provides the type translation
14724 *
14725 * Return: cds_con_mode enum
14726 */
14727enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
14728 enum nl80211_iftype type)
14729{
14730 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
14731 switch (type) {
14732 case NL80211_IFTYPE_STATION:
14733 mode = CDS_STA_MODE;
14734 break;
14735 case NL80211_IFTYPE_P2P_CLIENT:
14736 mode = CDS_P2P_CLIENT_MODE;
14737 break;
14738 case NL80211_IFTYPE_P2P_GO:
14739 mode = CDS_P2P_GO_MODE;
14740 break;
14741 case NL80211_IFTYPE_AP:
14742 mode = CDS_SAP_MODE;
14743 break;
14744 case NL80211_IFTYPE_ADHOC:
14745 mode = CDS_IBSS_MODE;
14746 break;
14747 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014748 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014749 type);
14750 }
14751 return mode;
14752}
14753
14754/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014755 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
14756 * @wiphy: Handle to struct wiphy to get handle to module context.
14757 * @chandef: Contains information about the capture channel to be set.
14758 *
14759 * This interface is called if and only if monitor mode interface alone is
14760 * active.
14761 *
14762 * Return: 0 success or error code on failure.
14763 */
14764static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
14765 struct cfg80211_chan_def *chandef)
14766{
14767 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
14768 hdd_adapter_t *adapter;
14769 hdd_station_ctx_t *sta_ctx;
14770 struct hdd_mon_set_ch_info *ch_info;
14771 QDF_STATUS status;
14772 tHalHandle hal_hdl;
14773 struct qdf_mac_addr bssid;
14774 tCsrRoamProfile roam_profile;
14775 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070014776 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014777 int ret;
14778 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
14779
14780 ENTER();
14781
14782 ret = wlan_hdd_validate_context(hdd_ctx);
14783 if (ret)
14784 return ret;
14785
14786 hal_hdl = hdd_ctx->hHal;
14787
14788 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
14789 if (!adapter)
14790 return -EIO;
14791
14792 hdd_info("%s: set monitor mode Channel %d and freq %d",
14793 adapter->dev->name, chan_num, chandef->chan->center_freq);
14794
14795 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
14796 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014797 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
14798 roam_profile.ChannelInfo.numOfChannels = 1;
14799 roam_profile.phyMode = ch_info->phy_mode;
14800 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014801 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014802
14803 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
14804 QDF_MAC_ADDR_SIZE);
14805
14806 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070014807 /*
14808 * CDS api expects secondary channel for calculating
14809 * the channel params
14810 */
14811 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
14812 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
14813 if (chan_num >= 1 && chan_num <= 5)
14814 sec_ch = chan_num + 4;
14815 else if (chan_num >= 6 && chan_num <= 13)
14816 sec_ch = chan_num - 4;
14817 }
14818 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014819 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
14820 &roam_profile);
14821 if (status) {
14822 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
14823 status);
14824 ret = qdf_status_to_os_return(status);
14825 return ret;
14826 }
14827 EXIT();
14828 return 0;
14829}
14830
14831/**
14832 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
14833 * @wiphy: Handle to struct wiphy to get handle to module context.
14834 * @chandef: Contains information about the capture channel to be set.
14835 *
14836 * This interface is called if and only if monitor mode interface alone is
14837 * active.
14838 *
14839 * Return: 0 success or error code on failure.
14840 */
14841static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
14842 struct cfg80211_chan_def *chandef)
14843{
14844 int ret;
14845
14846 cds_ssr_protect(__func__);
14847 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
14848 cds_ssr_unprotect(__func__);
14849 return ret;
14850}
14851
14852/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014853 * struct cfg80211_ops - cfg80211_ops
14854 *
14855 * @add_virtual_intf: Add virtual interface
14856 * @del_virtual_intf: Delete virtual interface
14857 * @change_virtual_intf: Change virtual interface
14858 * @change_station: Change station
14859 * @add_beacon: Add beacon in sap mode
14860 * @del_beacon: Delete beacon in sap mode
14861 * @set_beacon: Set beacon in sap mode
14862 * @start_ap: Start ap
14863 * @change_beacon: Change beacon
14864 * @stop_ap: Stop ap
14865 * @change_bss: Change bss
14866 * @add_key: Add key
14867 * @get_key: Get key
14868 * @del_key: Delete key
14869 * @set_default_key: Set default key
14870 * @set_channel: Set channel
14871 * @scan: Scan
14872 * @connect: Connect
14873 * @disconnect: Disconnect
14874 * @join_ibss = Join ibss
14875 * @leave_ibss = Leave ibss
14876 * @set_wiphy_params = Set wiphy params
14877 * @set_tx_power = Set tx power
14878 * @get_tx_power = get tx power
14879 * @remain_on_channel = Remain on channel
14880 * @cancel_remain_on_channel = Cancel remain on channel
14881 * @mgmt_tx = Tx management frame
14882 * @mgmt_tx_cancel_wait = Cancel management tx wait
14883 * @set_default_mgmt_key = Set default management key
14884 * @set_txq_params = Set tx queue parameters
14885 * @get_station = Get station
14886 * @set_power_mgmt = Set power management
14887 * @del_station = Delete station
14888 * @add_station = Add station
14889 * @set_pmksa = Set pmksa
14890 * @del_pmksa = Delete pmksa
14891 * @flush_pmksa = Flush pmksa
14892 * @update_ft_ies = Update FT IEs
14893 * @tdls_mgmt = Tdls management
14894 * @tdls_oper = Tdls operation
14895 * @set_rekey_data = Set rekey data
14896 * @sched_scan_start = Scheduled scan start
14897 * @sched_scan_stop = Scheduled scan stop
14898 * @resume = Resume wlan
14899 * @suspend = Suspend wlan
14900 * @set_mac_acl = Set mac acl
14901 * @testmode_cmd = Test mode command
14902 * @set_ap_chanwidth = Set AP channel bandwidth
14903 * @dump_survey = Dump survey
14904 * @key_mgmt_set_pmk = Set pmk key management
14905 */
14906static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
14907 .add_virtual_intf = wlan_hdd_add_virtual_intf,
14908 .del_virtual_intf = wlan_hdd_del_virtual_intf,
14909 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
14910 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014911 .start_ap = wlan_hdd_cfg80211_start_ap,
14912 .change_beacon = wlan_hdd_cfg80211_change_beacon,
14913 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014914 .change_bss = wlan_hdd_cfg80211_change_bss,
14915 .add_key = wlan_hdd_cfg80211_add_key,
14916 .get_key = wlan_hdd_cfg80211_get_key,
14917 .del_key = wlan_hdd_cfg80211_del_key,
14918 .set_default_key = wlan_hdd_cfg80211_set_default_key,
14919 .scan = wlan_hdd_cfg80211_scan,
14920 .connect = wlan_hdd_cfg80211_connect,
14921 .disconnect = wlan_hdd_cfg80211_disconnect,
14922 .join_ibss = wlan_hdd_cfg80211_join_ibss,
14923 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
14924 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
14925 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
14926 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
14927 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
14928 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
14929 .mgmt_tx = wlan_hdd_mgmt_tx,
14930 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
14931 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
14932 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053014933 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014934 .get_station = wlan_hdd_cfg80211_get_station,
14935 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
14936 .del_station = wlan_hdd_cfg80211_del_station,
14937 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014938 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
14939 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
14940 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080014941#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014942 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
14943#endif
14944#ifdef FEATURE_WLAN_TDLS
14945 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
14946 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
14947#endif
14948#ifdef WLAN_FEATURE_GTK_OFFLOAD
14949 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
14950#endif /* WLAN_FEATURE_GTK_OFFLOAD */
14951#ifdef FEATURE_WLAN_SCAN_PNO
14952 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
14953 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
14954#endif /*FEATURE_WLAN_SCAN_PNO */
14955 .resume = wlan_hdd_cfg80211_resume_wlan,
14956 .suspend = wlan_hdd_cfg80211_suspend_wlan,
14957 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
14958#ifdef WLAN_NL80211_TESTMODE
14959 .testmode_cmd = wlan_hdd_cfg80211_testmode,
14960#endif
14961#ifdef QCA_HT_2040_COEX
14962 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
14963#endif
14964 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014965#ifdef CHANNEL_SWITCH_SUPPORTED
14966 .channel_switch = wlan_hdd_cfg80211_channel_switch,
14967#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014968 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053014969#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
14970 defined(CFG80211_ABORT_SCAN)
14971 .abort_scan = wlan_hdd_cfg80211_abort_scan,
14972#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014973};