blob: ac58c814d1b3599b52a8d4790c11cbcd8c5bfbcf [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 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003892};
3893
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003894/**
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05303895 * wlan_hdd_save_default_scan_ies() - API to store the default scan IEs
3896 *
3897 * @adapter: Pointer to HDD adapter
3898 * @ie_data: Pointer to Scan IEs buffer
3899 * @ie_len: Length of Scan IEs
3900 *
3901 * Return: 0 on success; error number otherwise
3902 */
3903static int wlan_hdd_save_default_scan_ies(hdd_adapter_t *adapter,
3904 uint8_t *ie_data, uint8_t ie_len)
3905{
3906 hdd_scaninfo_t *scan_info = NULL;
3907 scan_info = &adapter->scan_info;
3908
3909 if (scan_info->default_scan_ies) {
3910 qdf_mem_free(scan_info->default_scan_ies);
3911 scan_info->default_scan_ies = NULL;
3912 }
3913
3914 scan_info->default_scan_ies = qdf_mem_malloc(ie_len);
3915 if (!scan_info->default_scan_ies)
3916 return -ENOMEM;
3917
3918 memcpy(scan_info->default_scan_ies, ie_data, ie_len);
3919 scan_info->default_scan_ies_len = ie_len;
3920 return 0;
3921}
3922
3923/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003924 * __wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
3925 * vendor command
3926 *
3927 * @wiphy: wiphy device pointer
3928 * @wdev: wireless device pointer
3929 * @data: Vendor command data buffer
3930 * @data_len: Buffer length
3931 *
3932 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
3933 *
3934 * Return: Error code.
3935 */
3936static int
3937__wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
3938 struct wireless_dev *wdev,
3939 const void *data,
3940 int data_len)
3941{
3942 struct net_device *dev = wdev->netdev;
3943 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
3944 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
3945 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
3946 int ret_val = 0;
3947 u32 modulated_dtim;
3948 u16 stats_avg_factor;
3949 u32 guard_time;
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05303950 uint8_t set_value;
Krunal Sonie3531942016-04-12 17:43:53 -07003951 u32 ftm_capab;
Dustin Brown10a7b712016-10-07 10:31:16 -07003952 u8 qpower;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05303953 QDF_STATUS status;
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05303954 int attr_len;
3955 int access_policy = 0;
3956 char vendor_ie[SIR_MAC_MAX_IE_LENGTH + 2];
3957 bool vendor_ie_present = false, access_policy_present = false;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05303958 uint16_t scan_ie_len = 0;
3959 uint8_t *scan_ie;
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05303960 struct sir_set_tx_rx_aggregation_size request;
3961 QDF_STATUS qdf_status;
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05303962
Jeff Johnson1f61b612016-02-12 16:28:33 -08003963 ENTER_DEV(dev);
3964
Anurag Chouhan6d760662016-02-20 16:05:43 +05303965 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003966 hdd_err("Command not allowed in FTM mode");
3967 return -EPERM;
3968 }
3969
3970 ret_val = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05303971 if (ret_val)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003972 return ret_val;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003973
3974 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX,
3975 data, data_len,
3976 wlan_hdd_wifi_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07003977 hdd_err("invalid attr");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003978 return -EINVAL;
3979 }
3980
Krunal Sonie3531942016-04-12 17:43:53 -07003981 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
3982 ftm_capab = nla_get_u32(tb[
3983 QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
3984 hdd_ctx->config->fine_time_meas_cap =
3985 hdd_ctx->fine_time_meas_cap_target & ftm_capab;
3986 sme_update_fine_time_measurement_capab(hdd_ctx->hHal,
Selvaraj, Sridhar57bb4d02016-08-31 16:14:15 +05303987 adapter->sessionId,
Krunal Sonie3531942016-04-12 17:43:53 -07003988 hdd_ctx->config->fine_time_meas_cap);
3989 hdd_info("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
3990 ftm_capab, hdd_ctx->fine_time_meas_cap_target,
3991 hdd_ctx->config->fine_time_meas_cap);
3992 }
3993
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003994 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {
3995 modulated_dtim = nla_get_u32(
3996 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
3997
3998 status = sme_configure_modulated_dtim(hdd_ctx->hHal,
3999 adapter->sessionId,
4000 modulated_dtim);
4001
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304002 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004003 ret_val = -EPERM;
4004 }
4005
Kapil Gupta6213c012016-09-02 19:39:09 +05304006 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
4007 qpower = nla_get_u8(
4008 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);
4009 if (hdd_set_qpower_config(hdd_ctx, adapter, qpower) != 0)
4010 ret_val = -EINVAL;
4011 }
4012
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004013 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]) {
4014 stats_avg_factor = nla_get_u16(
4015 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR]);
4016 status = sme_configure_stats_avg_factor(hdd_ctx->hHal,
4017 adapter->sessionId,
4018 stats_avg_factor);
4019
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304020 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004021 ret_val = -EPERM;
4022 }
4023
4024
4025 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
4026 guard_time = nla_get_u32(
4027 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
4028 status = sme_configure_guard_time(hdd_ctx->hHal,
4029 adapter->sessionId,
4030 guard_time);
4031
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304032 if (QDF_STATUS_SUCCESS != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004033 ret_val = -EPERM;
4034 }
4035
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304036 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]) {
4037 qdf_mem_zero(&vendor_ie[0], SIR_MAC_MAX_IE_LENGTH + 2);
4038 attr_len = nla_len(
4039 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST]);
4040 if (attr_len < 0 || attr_len > SIR_MAC_MAX_IE_LENGTH + 2) {
4041 hdd_info("Invalid value. attr_len %d",
4042 attr_len);
4043 return -EINVAL;
4044 }
4045
4046 nla_memcpy(&vendor_ie,
4047 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST],
4048 attr_len);
4049 vendor_ie_present = true;
4050 hdd_info("Access policy vendor ie present.attr_len %d",
4051 attr_len);
4052 qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
4053 &vendor_ie[0], attr_len);
4054 }
4055
4056 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]) {
4057 access_policy = (int) nla_get_u32(
4058 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY]);
4059 if ((access_policy < QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED) ||
4060 (access_policy >
4061 QCA_ACCESS_POLICY_DENY_UNLESS_LISTED)) {
4062 hdd_info("Invalid value. access_policy %d",
4063 access_policy);
4064 return -EINVAL;
4065 }
4066 access_policy_present = true;
4067 hdd_info("Access policy present. access_policy %d",
4068 access_policy);
4069 }
4070
4071 if (vendor_ie_present && access_policy_present) {
4072 if (access_policy == QCA_ACCESS_POLICY_DENY_UNLESS_LISTED) {
4073 access_policy =
4074 WLAN_HDD_VENDOR_IE_ACCESS_ALLOW_IF_LISTED;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304075 } else {
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304076 access_policy = WLAN_HDD_VENDOR_IE_ACCESS_NONE;
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304077 }
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304078
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304079 hdd_info("calling sme_update_access_policy_vendor_ie");
4080 status = sme_update_access_policy_vendor_ie(hdd_ctx->hHal,
4081 adapter->sessionId, &vendor_ie[0],
4082 access_policy);
4083 if (QDF_STATUS_SUCCESS != status) {
4084 hdd_info("Failed to set vendor ie and access policy.");
Kondabattini, Ganesh44f6a212016-09-05 15:14:25 +05304085 return -EINVAL;
4086 }
4087 }
4088
Selvaraj, Sridharebda0f22016-08-29 16:05:23 +05304089 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) {
4090 set_value = nla_get_u8(
4091 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]);
4092 hdd_info("set_value: %d", set_value);
4093 ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value);
4094 }
4095
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304096 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]) {
4097 scan_ie_len = nla_len(
4098 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
4099 hdd_info("Received default scan IE of len %d session %d device mode %d",
4100 scan_ie_len, adapter->sessionId,
4101 adapter->device_mode);
4102 if (scan_ie_len && (scan_ie_len <= MAX_DEFAULT_SCAN_IE_LEN)) {
4103 scan_ie = (uint8_t *) nla_data(tb
4104 [QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES]);
Selvaraj, Sridhar4ea106e2016-08-05 20:34:46 +05304105
4106 if (wlan_hdd_save_default_scan_ies(adapter, scan_ie,
4107 scan_ie_len))
4108 hdd_err("Failed to save default scan IEs");
4109
Deepak Dhamdhereb106ae52016-08-10 20:55:30 +05304110 if (adapter->device_mode == QDF_STA_MODE) {
4111 status = sme_set_default_scan_ie(hdd_ctx->hHal,
4112 adapter->sessionId, scan_ie,
4113 scan_ie_len);
4114 if (QDF_STATUS_SUCCESS != status)
4115 ret_val = -EPERM;
4116 }
4117 } else
4118 ret_val = -EPERM;
4119 }
Padma, Santhosh Kumara7119672016-08-16 16:05:14 +05304120
4121 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4122 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4123 /* if one is specified, both must be specified */
4124 if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION] ||
4125 !tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]) {
4126 hdd_err("Both TX and RX MPDU Aggregation required");
4127 return -EINVAL;
4128 }
4129
4130 request.tx_aggregation_size = nla_get_u8(
4131 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION]);
4132 request.rx_aggregation_size = nla_get_u8(
4133 tb[QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION]);
4134 request.vdev_id = adapter->sessionId;
4135
4136 if (request.tx_aggregation_size >=
4137 CFG_TX_AGGREGATION_SIZE_MIN &&
4138 request.tx_aggregation_size <=
4139 CFG_TX_AGGREGATION_SIZE_MAX &&
4140 request.rx_aggregation_size >=
4141 CFG_RX_AGGREGATION_SIZE_MIN &&
4142 request.rx_aggregation_size <=
4143 CFG_RX_AGGREGATION_SIZE_MAX) {
4144 qdf_status = wma_set_tx_rx_aggregation_size(&request);
4145 if (qdf_status != QDF_STATUS_SUCCESS) {
4146 hdd_err("failed to set aggr sizes err %d",
4147 qdf_status);
4148 ret_val = -EPERM;
4149 }
4150 } else {
4151 hdd_err("TX %d RX %d MPDU aggr size not in range",
4152 request.tx_aggregation_size,
4153 request.rx_aggregation_size);
4154 ret_val = -EINVAL;
4155 }
4156 }
4157
Selvaraj, Sridharac4fcf32016-09-28 12:57:32 +05304158 if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]) {
4159 uint8_t ignore_assoc_disallowed;
4160
4161 ignore_assoc_disallowed
4162 = nla_get_u8(tb[
4163 QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED]);
4164 hdd_info("Set ignore_assoc_disallowed value - %d",
4165 ignore_assoc_disallowed);
4166 if ((ignore_assoc_disallowed <
4167 QCA_IGNORE_ASSOC_DISALLOWED_DISABLE) ||
4168 (ignore_assoc_disallowed >
4169 QCA_IGNORE_ASSOC_DISALLOWED_ENABLE))
4170 return -EPERM;
4171
4172 sme_update_session_param(hdd_ctx->hHal,
4173 adapter->sessionId,
4174 SIR_PARAM_IGNORE_ASSOC_DISALLOWED,
4175 ignore_assoc_disallowed);
4176 }
4177
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004178 return ret_val;
4179}
4180
4181/**
4182 * wlan_hdd_cfg80211_wifi_configuration_set() - Wifi configuration
4183 * vendor command
4184 *
4185 * @wiphy: wiphy device pointer
4186 * @wdev: wireless device pointer
4187 * @data: Vendor command data buffer
4188 * @data_len: Buffer length
4189 *
4190 * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
4191 *
4192 * Return: EOK or other error codes.
4193 */
4194static int wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
4195 struct wireless_dev *wdev,
4196 const void *data,
4197 int data_len)
4198{
4199 int ret;
4200
4201 cds_ssr_protect(__func__);
4202 ret = __wlan_hdd_cfg80211_wifi_configuration_set(wiphy, wdev,
4203 data, data_len);
4204 cds_ssr_unprotect(__func__);
4205
4206 return ret;
4207}
4208
4209static const struct
4210nla_policy
4211qca_wlan_vendor_wifi_logger_start_policy
4212[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1] = {
4213 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]
4214 = {.type = NLA_U32 },
4215 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]
4216 = {.type = NLA_U32 },
4217 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]
4218 = {.type = NLA_U32 },
4219};
4220
4221/**
4222 * __wlan_hdd_cfg80211_wifi_logger_start() - This function is used to enable
4223 * or disable the collection of packet statistics from the firmware
4224 * @wiphy: WIPHY structure pointer
4225 * @wdev: Wireless device structure pointer
4226 * @data: Pointer to the data received
4227 * @data_len: Length of the data received
4228 *
4229 * This function enables or disables the collection of packet statistics from
4230 * the firmware
4231 *
4232 * Return: 0 on success and errno on failure
4233 */
4234static int __wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4235 struct wireless_dev *wdev,
4236 const void *data,
4237 int data_len)
4238{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304239 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004240 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4241 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX + 1];
4242 struct sir_wifi_start_log start_log;
4243
Jeff Johnson1f61b612016-02-12 16:28:33 -08004244 ENTER_DEV(wdev->netdev);
4245
Anurag Chouhan6d760662016-02-20 16:05:43 +05304246 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004247 hdd_err("Command not allowed in FTM mode");
4248 return -EPERM;
4249 }
4250
4251 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304252 if (status)
4253 return status;
4254
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004255
4256 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_MAX,
4257 data, data_len,
4258 qca_wlan_vendor_wifi_logger_start_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004259 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004260 return -EINVAL;
4261 }
4262
4263 /* Parse and fetch ring id */
4264 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004265 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004266 return -EINVAL;
4267 }
4268 start_log.ring_id = nla_get_u32(
4269 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004270 hdd_info("Ring ID=%d", start_log.ring_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004271
4272 /* Parse and fetch verbose level */
4273 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004274 hdd_err("attr verbose_level failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004275 return -EINVAL;
4276 }
4277 start_log.verbose_level = nla_get_u32(
4278 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL]);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08004279 hdd_info("verbose_level=%d", start_log.verbose_level);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004280
4281 /* Parse and fetch flag */
4282 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004283 hdd_err("attr flag failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004284 return -EINVAL;
4285 }
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304286 start_log.is_iwpriv_command = nla_get_u32(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004287 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS]);
Poddar, Siddartheefe3482016-09-21 18:12:59 +05304288 hdd_info("is_iwpriv_command =%d", start_log.is_iwpriv_command);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004289
4290 cds_set_ring_log_level(start_log.ring_id, start_log.verbose_level);
4291
4292 if (start_log.ring_id == RING_ID_WAKELOCK) {
4293 /* Start/stop wakelock events */
4294 if (start_log.verbose_level > WLAN_LOG_LEVEL_OFF)
4295 cds_set_wakelock_logging(true);
4296 else
4297 cds_set_wakelock_logging(false);
4298 return 0;
4299 }
4300
4301 status = sme_wifi_start_logger(hdd_ctx->hHal, start_log);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304302 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004303 hdd_err("sme_wifi_start_logger failed(err=%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004304 status);
4305 return -EINVAL;
4306 }
4307 return 0;
4308}
4309
4310/**
4311 * wlan_hdd_cfg80211_wifi_logger_start() - Wrapper function used to enable
4312 * or disable the collection of packet statistics from the firmware
4313 * @wiphy: WIPHY structure pointer
4314 * @wdev: Wireless device structure pointer
4315 * @data: Pointer to the data received
4316 * @data_len: Length of the data received
4317 *
4318 * This function is used to enable or disable the collection of packet
4319 * statistics from the firmware
4320 *
4321 * Return: 0 on success and errno on failure
4322 */
4323static int wlan_hdd_cfg80211_wifi_logger_start(struct wiphy *wiphy,
4324 struct wireless_dev *wdev,
4325 const void *data,
4326 int data_len)
4327{
4328 int ret = 0;
4329
4330 cds_ssr_protect(__func__);
4331 ret = __wlan_hdd_cfg80211_wifi_logger_start(wiphy,
4332 wdev, data, data_len);
4333 cds_ssr_unprotect(__func__);
4334
4335 return ret;
4336}
4337
4338static const struct
4339nla_policy
4340qca_wlan_vendor_wifi_logger_get_ring_data_policy
4341[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1] = {
4342 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]
4343 = {.type = NLA_U32 },
4344};
4345
4346/**
4347 * __wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Flush per packet stats
4348 * @wiphy: WIPHY structure pointer
4349 * @wdev: Wireless device structure pointer
4350 * @data: Pointer to the data received
4351 * @data_len: Length of the data received
4352 *
4353 * This function is used to flush or retrieve the per packet statistics from
4354 * the driver
4355 *
4356 * Return: 0 on success and errno on failure
4357 */
4358static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4359 struct wireless_dev *wdev,
4360 const void *data,
4361 int data_len)
4362{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304363 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004364 uint32_t ring_id;
4365 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4366 struct nlattr *tb
4367 [QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX + 1];
4368
Jeff Johnson1f61b612016-02-12 16:28:33 -08004369 ENTER_DEV(wdev->netdev);
4370
Anurag Chouhan6d760662016-02-20 16:05:43 +05304371 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004372 hdd_err("Command not allowed in FTM mode");
4373 return -EPERM;
4374 }
4375
4376 status = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304377 if (status)
4378 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004379
4380 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_MAX,
4381 data, data_len,
4382 qca_wlan_vendor_wifi_logger_get_ring_data_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004383 hdd_err("Invalid attribute");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004384 return -EINVAL;
4385 }
4386
4387 /* Parse and fetch ring id */
4388 if (!tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004389 hdd_err("attr ATTR failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004390 return -EINVAL;
4391 }
4392
4393 ring_id = nla_get_u32(
4394 tb[QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_GET_RING_DATA_ID]);
4395
4396 if (ring_id == RING_ID_PER_PACKET_STATS) {
4397 wlan_logging_set_per_pkt_stats();
Jeff Johnson77848112016-06-29 14:52:06 -07004398 hdd_notice("Flushing/Retrieving packet stats");
Sreelakshmi Konamkic3815ba2016-08-18 12:01:57 +05304399 } else if (ring_id == RING_ID_DRIVER_DEBUG) {
4400 /*
4401 * As part of DRIVER ring ID, flush both driver and fw logs.
4402 * For other Ring ID's driver doesn't have any rings to flush
4403 */
4404 hdd_notice("Bug report triggered by framework");
4405
4406 status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
4407 WLAN_LOG_INDICATOR_FRAMEWORK,
4408 WLAN_LOG_REASON_CODE_UNUSED,
4409 true, false);
4410 if (QDF_STATUS_SUCCESS != status) {
4411 hdd_err("Failed to trigger bug report");
4412 return -EINVAL;
4413 }
4414 } else {
4415 wlan_report_log_completion(WLAN_LOG_TYPE_NON_FATAL,
4416 WLAN_LOG_INDICATOR_FRAMEWORK,
4417 WLAN_LOG_REASON_CODE_UNUSED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004418 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004419 return 0;
4420}
4421
4422/**
4423 * wlan_hdd_cfg80211_wifi_logger_get_ring_data() - Wrapper to flush packet stats
4424 * @wiphy: WIPHY structure pointer
4425 * @wdev: Wireless device structure pointer
4426 * @data: Pointer to the data received
4427 * @data_len: Length of the data received
4428 *
4429 * This function is used to flush or retrieve the per packet statistics from
4430 * the driver
4431 *
4432 * Return: 0 on success and errno on failure
4433 */
4434static int wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy,
4435 struct wireless_dev *wdev,
4436 const void *data,
4437 int data_len)
4438{
4439 int ret = 0;
4440
4441 cds_ssr_protect(__func__);
4442 ret = __wlan_hdd_cfg80211_wifi_logger_get_ring_data(wiphy,
4443 wdev, data, data_len);
4444 cds_ssr_unprotect(__func__);
4445
4446 return ret;
4447}
4448
4449#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
4450/**
4451 * hdd_map_req_id_to_pattern_id() - map request id to pattern id
4452 * @hdd_ctx: HDD context
4453 * @request_id: [input] request id
4454 * @pattern_id: [output] pattern id
4455 *
4456 * This function loops through request id to pattern id array
4457 * if the slot is available, store the request id and return pattern id
4458 * if entry exists, return the pattern id
4459 *
4460 * Return: 0 on success and errno on failure
4461 */
4462static int hdd_map_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4463 uint32_t request_id,
4464 uint8_t *pattern_id)
4465{
4466 uint32_t i;
4467
4468 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4469 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4470 if (hdd_ctx->op_ctx.op_table[i].request_id == MAX_REQUEST_ID) {
4471 hdd_ctx->op_ctx.op_table[i].request_id = request_id;
4472 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4473 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4474 return 0;
4475 } else if (hdd_ctx->op_ctx.op_table[i].request_id ==
4476 request_id) {
4477 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4478 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4479 return 0;
4480 }
4481 }
4482 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4483 return -EINVAL;
4484}
4485
4486/**
4487 * hdd_unmap_req_id_to_pattern_id() - unmap request id to pattern id
4488 * @hdd_ctx: HDD context
4489 * @request_id: [input] request id
4490 * @pattern_id: [output] pattern id
4491 *
4492 * This function loops through request id to pattern id array
4493 * reset request id to 0 (slot available again) and
4494 * return pattern id
4495 *
4496 * Return: 0 on success and errno on failure
4497 */
4498static int hdd_unmap_req_id_to_pattern_id(hdd_context_t *hdd_ctx,
4499 uint32_t request_id,
4500 uint8_t *pattern_id)
4501{
4502 uint32_t i;
4503
4504 mutex_lock(&hdd_ctx->op_ctx.op_lock);
4505 for (i = 0; i < MAXNUM_PERIODIC_TX_PTRNS; i++) {
4506 if (hdd_ctx->op_ctx.op_table[i].request_id == request_id) {
4507 hdd_ctx->op_ctx.op_table[i].request_id = MAX_REQUEST_ID;
4508 *pattern_id = hdd_ctx->op_ctx.op_table[i].pattern_id;
4509 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4510 return 0;
4511 }
4512 }
4513 mutex_unlock(&hdd_ctx->op_ctx.op_lock);
4514 return -EINVAL;
4515}
4516
4517
4518/*
4519 * define short names for the global vendor params
4520 * used by __wlan_hdd_cfg80211_offloaded_packets()
4521 */
4522#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX
4523#define PARAM_REQUEST_ID \
4524 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID
4525#define PARAM_CONTROL \
4526 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL
4527#define PARAM_IP_PACKET \
4528 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA
4529#define PARAM_SRC_MAC_ADDR \
4530 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR
4531#define PARAM_DST_MAC_ADDR \
4532 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR
4533#define PARAM_PERIOD QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD
4534
4535/**
4536 * wlan_hdd_add_tx_ptrn() - add tx pattern
4537 * @adapter: adapter pointer
4538 * @hdd_ctx: hdd context
4539 * @tb: nl attributes
4540 *
4541 * This function reads the NL attributes and forms a AddTxPtrn message
4542 * posts it to SME.
4543 *
4544 */
4545static int
4546wlan_hdd_add_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4547 struct nlattr **tb)
4548{
4549 struct sSirAddPeriodicTxPtrn *add_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304550 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004551 uint32_t request_id, ret, len;
4552 uint8_t pattern_id = 0;
Anurag Chouhan6d760662016-02-20 16:05:43 +05304553 struct qdf_mac_addr dst_addr;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004554 uint16_t eth_type = htons(ETH_P_IP);
4555
4556 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004557 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004558 return -ENOTSUPP;
4559 }
4560
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304561 add_req = qdf_mem_malloc(sizeof(*add_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004562 if (!add_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004563 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004564 return -ENOMEM;
4565 }
4566
4567 /* Parse and fetch request Id */
4568 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004569 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004570 goto fail;
4571 }
4572
4573 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4574 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004575 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004576 return -EINVAL;
4577 }
Jeff Johnson77848112016-06-29 14:52:06 -07004578 hdd_notice("Request Id: %u", request_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004579
4580 if (!tb[PARAM_PERIOD]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004581 hdd_err("attr period failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004582 goto fail;
4583 }
4584 add_req->usPtrnIntervalMs = nla_get_u32(tb[PARAM_PERIOD]);
Jeff Johnson77848112016-06-29 14:52:06 -07004585 hdd_notice("Period: %u ms", add_req->usPtrnIntervalMs);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004586 if (add_req->usPtrnIntervalMs == 0) {
Jeff Johnson77848112016-06-29 14:52:06 -07004587 hdd_err("Invalid interval zero, return failure");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004588 goto fail;
4589 }
4590
4591 if (!tb[PARAM_SRC_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004592 hdd_err("attr source mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004593 goto fail;
4594 }
Srinivas Girigowda31896552015-11-18 22:59:52 -08004595 nla_memcpy(add_req->mac_address.bytes, tb[PARAM_SRC_MAC_ADDR],
Anurag Chouhan6d760662016-02-20 16:05:43 +05304596 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004597 hdd_notice("input src mac address: "MAC_ADDRESS_STR,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004598 MAC_ADDR_ARRAY(add_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004599
Anurag Chouhanc5548422016-02-24 18:33:27 +05304600 if (!qdf_is_macaddr_equal(&add_req->mac_address,
Srinivas Girigowda31896552015-11-18 22:59:52 -08004601 &adapter->macAddressCurrent)) {
4602 hdd_err("input src mac address and connected ap bssid are different");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004603 goto fail;
4604 }
4605
4606 if (!tb[PARAM_DST_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004607 hdd_err("attr dst mac address failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004608 goto fail;
4609 }
Anurag Chouhan6d760662016-02-20 16:05:43 +05304610 nla_memcpy(dst_addr.bytes, tb[PARAM_DST_MAC_ADDR], QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07004611 hdd_notice("input dst mac address: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004612 MAC_ADDR_ARRAY(dst_addr.bytes));
4613
4614 if (!tb[PARAM_IP_PACKET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004615 hdd_err("attr ip packet failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004616 goto fail;
4617 }
4618 add_req->ucPtrnSize = nla_len(tb[PARAM_IP_PACKET]);
Jeff Johnson77848112016-06-29 14:52:06 -07004619 hdd_notice("IP packet len: %u", add_req->ucPtrnSize);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004620
4621 if (add_req->ucPtrnSize < 0 ||
4622 add_req->ucPtrnSize > (PERIODIC_TX_PTRN_MAX_SIZE -
4623 ETH_HLEN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004624 hdd_err("Invalid IP packet len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004625 add_req->ucPtrnSize);
4626 goto fail;
4627 }
4628
4629 len = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304630 qdf_mem_copy(&add_req->ucPattern[0], dst_addr.bytes, QDF_MAC_ADDR_SIZE);
Anurag Chouhan6d760662016-02-20 16:05:43 +05304631 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304632 qdf_mem_copy(&add_req->ucPattern[len], add_req->mac_address.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304633 QDF_MAC_ADDR_SIZE);
4634 len += QDF_MAC_ADDR_SIZE;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304635 qdf_mem_copy(&add_req->ucPattern[len], &eth_type, 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004636 len += 2;
4637
4638 /*
4639 * This is the IP packet, add 14 bytes Ethernet (802.3) header
4640 * ------------------------------------------------------------
4641 * | 14 bytes Ethernet (802.3) header | IP header and payload |
4642 * ------------------------------------------------------------
4643 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304644 qdf_mem_copy(&add_req->ucPattern[len],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004645 nla_data(tb[PARAM_IP_PACKET]),
4646 add_req->ucPtrnSize);
4647 add_req->ucPtrnSize += len;
4648
4649 ret = hdd_map_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4650 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004651 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004652 goto fail;
4653 }
4654 add_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004655 hdd_notice("pattern id: %d", add_req->ucPtrnId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004656
4657 status = sme_add_periodic_tx_ptrn(hdd_ctx->hHal, add_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304658 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004659 hdd_err("sme_add_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004660 goto fail;
4661 }
4662
4663 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304664 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004665 return 0;
4666
4667fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304668 qdf_mem_free(add_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004669 return -EINVAL;
4670}
4671
4672/**
4673 * wlan_hdd_del_tx_ptrn() - delete tx pattern
4674 * @adapter: adapter pointer
4675 * @hdd_ctx: hdd context
4676 * @tb: nl attributes
4677 *
4678 * This function reads the NL attributes and forms a DelTxPtrn message
4679 * posts it to SME.
4680 *
4681 */
4682static int
4683wlan_hdd_del_tx_ptrn(hdd_adapter_t *adapter, hdd_context_t *hdd_ctx,
4684 struct nlattr **tb)
4685{
4686 struct sSirDelPeriodicTxPtrn *del_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304687 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004688 uint32_t request_id, ret;
4689 uint8_t pattern_id = 0;
4690
4691 /* Parse and fetch request Id */
4692 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004693 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004694 return -EINVAL;
4695 }
4696 request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4697 if (request_id == MAX_REQUEST_ID) {
Jeff Johnson77848112016-06-29 14:52:06 -07004698 hdd_err("request_id cannot be MAX");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004699 return -EINVAL;
4700 }
4701
4702 ret = hdd_unmap_req_id_to_pattern_id(hdd_ctx, request_id, &pattern_id);
4703 if (ret) {
Jeff Johnson77848112016-06-29 14:52:06 -07004704 hdd_warn("req id to pattern id failed (ret=%d)", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004705 return -EINVAL;
4706 }
4707
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304708 del_req = qdf_mem_malloc(sizeof(*del_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004709 if (!del_req) {
Jeff Johnson77848112016-06-29 14:52:06 -07004710 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004711 return -ENOMEM;
4712 }
4713
Anurag Chouhanc5548422016-02-24 18:33:27 +05304714 qdf_copy_macaddr(&del_req->mac_address, &adapter->macAddressCurrent);
Srinivas Girigowdaa5bba7a2015-11-18 22:44:36 -08004715 hdd_info(MAC_ADDRESS_STR, MAC_ADDR_ARRAY(del_req->mac_address.bytes));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004716 del_req->ucPtrnId = pattern_id;
Jeff Johnson77848112016-06-29 14:52:06 -07004717 hdd_notice("Request Id: %u Pattern id: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004718 request_id, del_req->ucPtrnId);
4719
4720 status = sme_del_periodic_tx_ptrn(hdd_ctx->hHal, del_req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304721 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004722 hdd_err("sme_del_periodic_tx_ptrn failed (err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004723 goto fail;
4724 }
4725
4726 EXIT();
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304727 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004728 return 0;
4729
4730fail:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05304731 qdf_mem_free(del_req);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004732 return -EINVAL;
4733}
4734
4735
4736/**
4737 * __wlan_hdd_cfg80211_offloaded_packets() - send offloaded packets
4738 * @wiphy: Pointer to wireless phy
4739 * @wdev: Pointer to wireless device
4740 * @data: Pointer to data
4741 * @data_len: Data length
4742 *
4743 * Return: 0 on success, negative errno on failure
4744 */
4745static int
4746__wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4747 struct wireless_dev *wdev,
4748 const void *data,
4749 int data_len)
4750{
4751 struct net_device *dev = wdev->netdev;
4752 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4753 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4754 struct nlattr *tb[PARAM_MAX + 1];
4755 uint8_t control;
4756 int ret;
4757 static const struct nla_policy policy[PARAM_MAX + 1] = {
4758 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4759 [PARAM_CONTROL] = { .type = NLA_U32 },
4760 [PARAM_SRC_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304761 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004762 [PARAM_DST_MAC_ADDR] = { .type = NLA_BINARY,
Anurag Chouhan6d760662016-02-20 16:05:43 +05304763 .len = QDF_MAC_ADDR_SIZE },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004764 [PARAM_PERIOD] = { .type = NLA_U32 },
4765 };
4766
Jeff Johnson1f61b612016-02-12 16:28:33 -08004767 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004768
Anurag Chouhan6d760662016-02-20 16:05:43 +05304769 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004770 hdd_err("Command not allowed in FTM mode");
4771 return -EPERM;
4772 }
4773
4774 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304775 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004776 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004777
4778 if (!sme_is_feature_supported_by_fw(WLAN_PERIODIC_TX_PTRN)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004779 hdd_err("Periodic Tx Pattern Offload feature is not supported in FW!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004780 return -ENOTSUPP;
4781 }
4782
4783 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004784 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004785 return -EINVAL;
4786 }
4787
4788 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004789 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004790 return -EINVAL;
4791 }
4792 control = nla_get_u32(tb[PARAM_CONTROL]);
Jeff Johnson77848112016-06-29 14:52:06 -07004793 hdd_notice("Control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004794
4795 if (control == WLAN_START_OFFLOADED_PACKETS)
4796 return wlan_hdd_add_tx_ptrn(adapter, hdd_ctx, tb);
4797 else if (control == WLAN_STOP_OFFLOADED_PACKETS)
4798 return wlan_hdd_del_tx_ptrn(adapter, hdd_ctx, tb);
4799 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004800 hdd_err("Invalid control: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004801 return -EINVAL;
4802 }
4803}
4804
4805/*
4806 * done with short names for the global vendor params
4807 * used by __wlan_hdd_cfg80211_offloaded_packets()
4808 */
4809#undef PARAM_MAX
4810#undef PARAM_REQUEST_ID
4811#undef PARAM_CONTROL
4812#undef PARAM_IP_PACKET
4813#undef PARAM_SRC_MAC_ADDR
4814#undef PARAM_DST_MAC_ADDR
4815#undef PARAM_PERIOD
4816
4817/**
4818 * wlan_hdd_cfg80211_offloaded_packets() - Wrapper to offload packets
4819 * @wiphy: wiphy structure pointer
4820 * @wdev: Wireless device structure pointer
4821 * @data: Pointer to the data received
4822 * @data_len: Length of @data
4823 *
4824 * Return: 0 on success; errno on failure
4825 */
4826static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
4827 struct wireless_dev *wdev,
4828 const void *data,
4829 int data_len)
4830{
4831 int ret = 0;
4832
4833 cds_ssr_protect(__func__);
4834 ret = __wlan_hdd_cfg80211_offloaded_packets(wiphy,
4835 wdev, data, data_len);
4836 cds_ssr_unprotect(__func__);
4837
4838 return ret;
4839}
4840#endif
4841
4842/*
4843 * define short names for the global vendor params
4844 * used by __wlan_hdd_cfg80211_monitor_rssi()
4845 */
4846#define PARAM_MAX QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
4847#define PARAM_REQUEST_ID QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID
4848#define PARAM_CONTROL QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL
4849#define PARAM_MIN_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI
4850#define PARAM_MAX_RSSI QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI
4851
4852/**
4853 * __wlan_hdd_cfg80211_monitor_rssi() - monitor rssi
4854 * @wiphy: Pointer to wireless phy
4855 * @wdev: Pointer to wireless device
4856 * @data: Pointer to data
4857 * @data_len: Data length
4858 *
4859 * Return: 0 on success, negative errno on failure
4860 */
4861static int
4862__wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy,
4863 struct wireless_dev *wdev,
4864 const void *data,
4865 int data_len)
4866{
4867 struct net_device *dev = wdev->netdev;
4868 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
4869 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
4870 struct nlattr *tb[PARAM_MAX + 1];
4871 struct rssi_monitor_req req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304872 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004873 int ret;
4874 uint32_t control;
4875 static const struct nla_policy policy[PARAM_MAX + 1] = {
4876 [PARAM_REQUEST_ID] = { .type = NLA_U32 },
4877 [PARAM_CONTROL] = { .type = NLA_U32 },
4878 [PARAM_MIN_RSSI] = { .type = NLA_S8 },
4879 [PARAM_MAX_RSSI] = { .type = NLA_S8 },
4880 };
4881
Jeff Johnson1f61b612016-02-12 16:28:33 -08004882 ENTER_DEV(dev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004883
4884 ret = wlan_hdd_validate_context(hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +05304885 if (ret)
4886 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004887
4888 if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
Jeff Johnson77848112016-06-29 14:52:06 -07004889 hdd_err("Not in Connected state!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004890 return -ENOTSUPP;
4891 }
4892
4893 if (nla_parse(tb, PARAM_MAX, data, data_len, policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004894 hdd_err("Invalid ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004895 return -EINVAL;
4896 }
4897
4898 if (!tb[PARAM_REQUEST_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004899 hdd_err("attr request id failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004900 return -EINVAL;
4901 }
4902
4903 if (!tb[PARAM_CONTROL]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004904 hdd_err("attr control failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004905 return -EINVAL;
4906 }
4907
4908 req.request_id = nla_get_u32(tb[PARAM_REQUEST_ID]);
4909 req.session_id = adapter->sessionId;
4910 control = nla_get_u32(tb[PARAM_CONTROL]);
4911
4912 if (control == QCA_WLAN_RSSI_MONITORING_START) {
4913 req.control = true;
4914 if (!tb[PARAM_MIN_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004915 hdd_err("attr min rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004916 return -EINVAL;
4917 }
4918
4919 if (!tb[PARAM_MAX_RSSI]) {
Jeff Johnson77848112016-06-29 14:52:06 -07004920 hdd_err("attr max rssi failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004921 return -EINVAL;
4922 }
4923
4924 req.min_rssi = nla_get_s8(tb[PARAM_MIN_RSSI]);
4925 req.max_rssi = nla_get_s8(tb[PARAM_MAX_RSSI]);
4926
4927 if (!(req.min_rssi < req.max_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004928 hdd_warn("min_rssi: %d must be less than max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004929 req.min_rssi, req.max_rssi);
4930 return -EINVAL;
4931 }
Jeff Johnson77848112016-06-29 14:52:06 -07004932 hdd_notice("Min_rssi: %d Max_rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004933 req.min_rssi, req.max_rssi);
4934
4935 } else if (control == QCA_WLAN_RSSI_MONITORING_STOP)
4936 req.control = false;
4937 else {
Jeff Johnson77848112016-06-29 14:52:06 -07004938 hdd_err("Invalid control cmd: %d", control);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004939 return -EINVAL;
4940 }
Jeff Johnson77848112016-06-29 14:52:06 -07004941 hdd_notice("Request Id: %u Session_id: %d Control: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004942 req.request_id, req.session_id, req.control);
4943
4944 status = sme_set_rssi_monitoring(hdd_ctx->hHal, &req);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05304945 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07004946 hdd_err("sme_set_rssi_monitoring failed(err=%d)", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08004947 return -EINVAL;
4948 }
4949
4950 return 0;
4951}
4952
4953/*
4954 * done with short names for the global vendor params
4955 * used by __wlan_hdd_cfg80211_monitor_rssi()
4956 */
4957#undef PARAM_MAX
4958#undef PARAM_CONTROL
4959#undef PARAM_REQUEST_ID
4960#undef PARAM_MAX_RSSI
4961#undef PARAM_MIN_RSSI
4962
4963/**
4964 * wlan_hdd_cfg80211_monitor_rssi() - SSR wrapper to rssi monitoring
4965 * @wiphy: wiphy structure pointer
4966 * @wdev: Wireless device structure pointer
4967 * @data: Pointer to the data received
4968 * @data_len: Length of @data
4969 *
4970 * Return: 0 on success; errno on failure
4971 */
4972static int
4973wlan_hdd_cfg80211_monitor_rssi(struct wiphy *wiphy, struct wireless_dev *wdev,
4974 const void *data, int data_len)
4975{
4976 int ret;
4977
4978 cds_ssr_protect(__func__);
4979 ret = __wlan_hdd_cfg80211_monitor_rssi(wiphy, wdev, data, data_len);
4980 cds_ssr_unprotect(__func__);
4981
4982 return ret;
4983}
4984
4985/**
4986 * hdd_rssi_threshold_breached() - rssi breached NL event
4987 * @hddctx: HDD context
4988 * @data: rssi breached event data
4989 *
4990 * This function reads the rssi breached event %data and fill in the skb with
4991 * NL attributes and send up the NL event.
4992 *
4993 * Return: none
4994 */
4995void hdd_rssi_threshold_breached(void *hddctx,
4996 struct rssi_breach_event *data)
4997{
4998 hdd_context_t *hdd_ctx = hddctx;
4999 struct sk_buff *skb;
5000
5001 ENTER();
5002
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05305003 if (wlan_hdd_validate_context(hdd_ctx))
5004 return;
5005 if (!data) {
Jeff Johnson77848112016-06-29 14:52:06 -07005006 hdd_err("data is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005007 return;
5008 }
5009
5010 skb = cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
5011 NULL,
5012 EXTSCAN_EVENT_BUF_SIZE + NLMSG_HDRLEN,
5013 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI_INDEX,
5014 GFP_KERNEL);
5015
5016 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005017 hdd_err("cfg80211_vendor_event_alloc failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005018 return;
5019 }
5020
Jeff Johnson77848112016-06-29 14:52:06 -07005021 hdd_notice("Req Id: %u Current rssi: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005022 data->request_id, data->curr_rssi);
Jeff Johnson77848112016-06-29 14:52:06 -07005023 hdd_notice("Current BSSID: "MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005024 MAC_ADDR_ARRAY(data->curr_bssid.bytes));
5025
5026 if (nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
5027 data->request_id) ||
5028 nla_put(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
5029 sizeof(data->curr_bssid), data->curr_bssid.bytes) ||
5030 nla_put_s8(skb, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI,
5031 data->curr_rssi)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005032 hdd_err("nla put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005033 goto fail;
5034 }
5035
5036 cfg80211_vendor_event(skb, GFP_KERNEL);
5037 return;
5038
5039fail:
5040 kfree_skb(skb);
5041 return;
5042}
5043
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305044static const struct nla_policy
5045ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = {
5046 [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8},
5047};
5048
5049/**
5050 * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5051 * @wiphy: Pointer to wireless phy
5052 * @wdev: Pointer to wireless device
5053 * @data: Pointer to data
5054 * @data_len: Length of @data
5055 *
5056 * Return: 0 on success, negative errno on failure
5057 */
5058static int
5059__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5060 struct wireless_dev *wdev,
5061 const void *data, int data_len)
5062{
5063 int status;
5064 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1];
5065 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
Dustin Brownd8279d22016-09-07 14:52:57 -07005066 struct net_device *dev = wdev->netdev;
5067 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305068
5069 ENTER_DEV(wdev->netdev);
5070
5071 status = wlan_hdd_validate_context(pHddCtx);
5072 if (0 != status)
5073 return status;
5074 if (!pHddCtx->config->fhostNSOffload) {
5075 hdd_err("ND Offload not supported");
5076 return -EINVAL;
5077 }
5078
5079 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX,
5080 (struct nlattr *)data,
5081 data_len, ns_offload_set_policy)) {
5082 hdd_err("nla_parse failed");
5083 return -EINVAL;
5084 }
5085
5086 if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) {
5087 hdd_err("ND Offload flag attribute not present");
5088 return -EINVAL;
5089 }
5090
5091 pHddCtx->ns_offload_enable =
5092 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]);
5093
Dustin Brownd8279d22016-09-07 14:52:57 -07005094 /* update ns offload in case it is already enabled/disabled */
5095 hdd_conf_ns_offload(adapter, pHddCtx->ns_offload_enable);
5096
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05305097 return 0;
5098}
5099
5100/**
5101 * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload
5102 * @wiphy: pointer to wireless wiphy structure.
5103 * @wdev: pointer to wireless_dev structure.
5104 * @data: Pointer to the data to be passed via vendor interface
5105 * @data_len:Length of the data to be passed
5106 *
5107 * Return: Return the Success or Failure code.
5108 */
5109static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy,
5110 struct wireless_dev *wdev,
5111 const void *data, int data_len)
5112{
5113 int ret;
5114
5115 cds_ssr_protect(__func__);
5116 ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len);
5117 cds_ssr_unprotect(__func__);
5118
5119 return ret;
5120}
5121
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005122/** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list
5123 * @wiphy: Pointer to wireless phy
5124 * @wdev: Pointer to wireless device
5125 * @data: Pointer to data
5126 * @data_len: Data length
5127 *
5128 * This function return the preferred frequency list generated by the policy
5129 * manager.
5130 *
5131 * Return: success or failure code
5132 */
5133static int __wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5134 struct wireless_dev
5135 *wdev, const void *data,
5136 int data_len)
5137{
5138 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5139 int i, ret = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305140 QDF_STATUS status;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305141 uint8_t pcl[QDF_MAX_NUM_CHAN], weight_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005142 uint32_t pcl_len = 0;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05305143 uint32_t freq_list[QDF_MAX_NUM_CHAN];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005144 enum cds_con_mode intf_mode;
5145 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5146 struct sk_buff *reply_skb;
5147
Jeff Johnson1f61b612016-02-12 16:28:33 -08005148 ENTER_DEV(wdev->netdev);
5149
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005150 ret = wlan_hdd_validate_context(hdd_ctx);
5151 if (ret)
5152 return -EINVAL;
5153
5154 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX,
5155 data, data_len, NULL)) {
5156 hdd_err("Invalid ATTR");
5157 return -EINVAL;
5158 }
5159
5160 if (!tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]) {
5161 hdd_err("attr interface type failed");
5162 return -EINVAL;
5163 }
5164
5165 intf_mode = nla_get_u32(tb
5166 [QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE]);
5167
5168 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5169 hdd_err("Invalid interface type");
5170 return -EINVAL;
5171 }
5172
5173 hdd_debug("Userspace requested pref freq list");
5174
Manishekar Chandrasekaran7009f252016-04-21 19:14:15 +05305175 status = cds_get_pcl(intf_mode, pcl, &pcl_len,
5176 weight_list, QDF_ARRAY_SIZE(weight_list));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305177 if (status != QDF_STATUS_SUCCESS) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005178 hdd_err("Get pcl failed");
5179 return -EINVAL;
5180 }
5181
5182 /* convert channel number to frequency */
5183 for (i = 0; i < pcl_len; i++) {
5184 if (pcl[i] <= ARRAY_SIZE(hdd_channels_2_4_ghz))
5185 freq_list[i] =
5186 ieee80211_channel_to_frequency(pcl[i],
5187 IEEE80211_BAND_2GHZ);
5188 else
5189 freq_list[i] =
5190 ieee80211_channel_to_frequency(pcl[i],
5191 IEEE80211_BAND_5GHZ);
5192 }
5193
5194 /* send the freq_list back to supplicant */
5195 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(u32) +
5196 sizeof(u32) *
5197 pcl_len +
5198 NLMSG_HDRLEN);
5199
5200 if (!reply_skb) {
5201 hdd_err("Allocate reply_skb failed");
5202 return -EINVAL;
5203 }
5204
5205 if (nla_put_u32(reply_skb,
5206 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
5207 intf_mode) ||
5208 nla_put(reply_skb,
5209 QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
5210 sizeof(uint32_t) * pcl_len,
5211 freq_list)) {
5212 hdd_err("nla put fail");
5213 kfree_skb(reply_skb);
5214 return -EINVAL;
5215 }
5216
5217 return cfg80211_vendor_cmd_reply(reply_skb);
5218}
5219
5220/** wlan_hdd_cfg80211_get_preferred_freq_list () - get preferred frequency list
5221 * @wiphy: Pointer to wireless phy
5222 * @wdev: Pointer to wireless device
5223 * @data: Pointer to data
5224 * @data_len: Data length
5225 *
5226 * This function return the preferred frequency list generated by the policy
5227 * manager.
5228 *
5229 * Return: success or failure code
5230 */
5231static int wlan_hdd_cfg80211_get_preferred_freq_list(struct wiphy *wiphy,
5232 struct wireless_dev
5233 *wdev, const void *data,
5234 int data_len)
5235{
5236 int ret = 0;
5237
5238 cds_ssr_protect(__func__);
5239 ret = __wlan_hdd_cfg80211_get_preferred_freq_list(wiphy, wdev,
5240 data, data_len);
5241 cds_ssr_unprotect(__func__);
5242
5243 return ret;
5244}
5245
5246/**
5247 * __wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5248 * @wiphy: Pointer to wireless phy
5249 * @wdev: Pointer to wireless device
5250 * @data: Pointer to data
5251 * @data_len: Data length
5252 *
5253 * Return: 0 on success, negative errno on failure
5254 */
5255static int __wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5256 struct wireless_dev *wdev,
5257 const void *data,
5258 int data_len)
5259{
Chandrasekaran, Manishekaref70c0d2015-10-20 19:54:55 +05305260 struct net_device *ndev = wdev->netdev;
5261 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005262 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5263 int ret = 0;
5264 enum cds_con_mode intf_mode;
5265 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX + 1];
5266 uint32_t channel_hint;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005267
Jeff Johnson1f61b612016-02-12 16:28:33 -08005268 ENTER_DEV(ndev);
5269
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005270 ret = wlan_hdd_validate_context(hdd_ctx);
5271 if (ret)
5272 return ret;
5273
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005274 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX,
5275 data, data_len, NULL)) {
5276 hdd_err("Invalid ATTR");
5277 return -EINVAL;
5278 }
5279
5280 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]) {
5281 hdd_err("attr interface type failed");
5282 return -EINVAL;
5283 }
5284
5285 intf_mode = nla_get_u32(tb
5286 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE]);
5287
5288 if (intf_mode < CDS_STA_MODE || intf_mode >= CDS_MAX_NUM_OF_MODE) {
5289 hdd_err("Invalid interface type");
5290 return -EINVAL;
5291 }
5292
5293 if (!tb[QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]) {
5294 hdd_err("attr probable freq failed");
5295 return -EINVAL;
5296 }
5297
5298 channel_hint = cds_freq_to_chan(nla_get_u32(tb
5299 [QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ]));
5300
5301 /* check pcl table */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08005302 if (!cds_allow_concurrency(intf_mode,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005303 channel_hint, HW_MODE_20_MHZ)) {
5304 hdd_err("Set channel hint failed due to concurrency check");
5305 return -EINVAL;
5306 }
5307
Krunal Soni09e55032016-06-07 10:06:55 -07005308 if (0 != wlan_hdd_check_remain_on_channel(adapter))
5309 hdd_warn("Remain On Channel Pending");
5310
Krunal Soni3091bcc2016-06-23 12:28:21 -07005311 ret = qdf_reset_connection_update();
5312 if (!QDF_IS_STATUS_SUCCESS(ret))
5313 hdd_err("clearing event failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005314
Krunal Soni3091bcc2016-06-23 12:28:21 -07005315 ret = cds_current_connections_update(adapter->sessionId,
5316 channel_hint,
5317 SIR_UPDATE_REASON_SET_OPER_CHAN);
5318 if (QDF_STATUS_E_FAILURE == ret) {
5319 /* return in the failure case */
5320 hdd_err("ERROR: connections update failed!!");
5321 return -EINVAL;
5322 }
5323
5324 if (QDF_STATUS_SUCCESS == ret) {
5325 /*
5326 * Success is the only case for which we expect hw mode
5327 * change to take place, hence we need to wait.
5328 * For any other return value it should be a pass
5329 * through
5330 */
5331 ret = qdf_wait_for_connection_update();
5332 if (!QDF_IS_STATUS_SUCCESS(ret)) {
5333 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005334 return -EINVAL;
5335 }
5336
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08005337 }
5338
5339 return 0;
5340}
5341
5342/**
5343 * wlan_hdd_cfg80211_set_probable_oper_channel () - set probable channel
5344 * @wiphy: Pointer to wireless phy
5345 * @wdev: Pointer to wireless device
5346 * @data: Pointer to data
5347 * @data_len: Data length
5348 *
5349 * Return: 0 on success, negative errno on failure
5350 */
5351static int wlan_hdd_cfg80211_set_probable_oper_channel(struct wiphy *wiphy,
5352 struct wireless_dev *wdev,
5353 const void *data,
5354 int data_len)
5355{
5356 int ret = 0;
5357
5358 cds_ssr_protect(__func__);
5359 ret = __wlan_hdd_cfg80211_set_probable_oper_channel(wiphy, wdev,
5360 data, data_len);
5361 cds_ssr_unprotect(__func__);
5362
5363 return ret;
5364}
5365
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305366static const struct
5367nla_policy
5368qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
5369 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
5370};
5371
5372/**
5373 * __wlan_hdd_cfg80211_get_link_properties() - Get link properties
5374 * @wiphy: WIPHY structure pointer
5375 * @wdev: Wireless device structure pointer
5376 * @data: Pointer to the data received
5377 * @data_len: Length of the data received
5378 *
5379 * This function is used to get link properties like nss, rate flags and
5380 * operating frequency for the active connection with the given peer.
5381 *
5382 * Return: 0 on success and errno on failure
5383 */
5384static int __wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5385 struct wireless_dev *wdev,
5386 const void *data,
5387 int data_len)
5388{
5389 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5390 struct net_device *dev = wdev->netdev;
5391 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5392 hdd_station_ctx_t *hdd_sta_ctx;
5393 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
Anurag Chouhan6d760662016-02-20 16:05:43 +05305394 uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305395 uint32_t sta_id;
5396 struct sk_buff *reply_skb;
5397 uint32_t rate_flags = 0;
5398 uint8_t nss;
5399 uint8_t final_rate_flags = 0;
5400 uint32_t freq;
5401
Jeff Johnson1f61b612016-02-12 16:28:33 -08005402 ENTER_DEV(dev);
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305403
Anurag Chouhan6d760662016-02-20 16:05:43 +05305404 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305405 hdd_err("Command not allowed in FTM mode");
5406 return -EPERM;
5407 }
5408
5409 if (0 != wlan_hdd_validate_context(hdd_ctx))
5410 return -EINVAL;
5411
5412 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
5413 qca_wlan_vendor_attr_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005414 hdd_err("Invalid attribute");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305415 return -EINVAL;
5416 }
5417
5418 if (!tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) {
Jeff Johnson77848112016-06-29 14:52:06 -07005419 hdd_err("Attribute peerMac not provided for mode=%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305420 adapter->device_mode);
5421 return -EINVAL;
5422 }
5423
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305424 qdf_mem_copy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
Anurag Chouhan6d760662016-02-20 16:05:43 +05305425 QDF_MAC_ADDR_SIZE);
Jeff Johnson77848112016-06-29 14:52:06 -07005426 hdd_notice("peerMac="MAC_ADDRESS_STR" for device_mode:%d",
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305427 MAC_ADDR_ARRAY(peer_mac), adapter->device_mode);
5428
Krunal Sonib4326f22016-03-10 13:05:51 -08005429 if (adapter->device_mode == QDF_STA_MODE ||
5430 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305431 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
5432 if ((hdd_sta_ctx->conn_info.connState !=
5433 eConnectionState_Associated) ||
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305434 qdf_mem_cmp(hdd_sta_ctx->conn_info.bssId.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305435 peer_mac, QDF_MAC_ADDR_SIZE)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005436 hdd_err("Not Associated to mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305437 MAC_ADDR_ARRAY(peer_mac));
5438 return -EINVAL;
5439 }
5440
5441 nss = hdd_sta_ctx->conn_info.nss;
5442 freq = cds_chan_to_freq(
5443 hdd_sta_ctx->conn_info.operationChannel);
5444 rate_flags = hdd_sta_ctx->conn_info.rate_flags;
Krunal Sonib4326f22016-03-10 13:05:51 -08005445 } else if (adapter->device_mode == QDF_P2P_GO_MODE ||
5446 adapter->device_mode == QDF_SAP_MODE) {
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305447
5448 for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
5449 if (adapter->aStaInfo[sta_id].isUsed &&
Anurag Chouhanc5548422016-02-24 18:33:27 +05305450 !qdf_is_macaddr_broadcast(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305451 &adapter->aStaInfo[sta_id].macAddrSTA) &&
Anurag Chouhan600c3a02016-03-01 10:33:54 +05305452 !qdf_mem_cmp(
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305453 &adapter->aStaInfo[sta_id].macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +05305454 peer_mac, QDF_MAC_ADDR_SIZE))
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305455 break;
5456 }
5457
5458 if (WLAN_MAX_STA_COUNT == sta_id) {
Jeff Johnson77848112016-06-29 14:52:06 -07005459 hdd_err("No active peer with mac="MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305460 MAC_ADDR_ARRAY(peer_mac));
5461 return -EINVAL;
5462 }
5463
5464 nss = adapter->aStaInfo[sta_id].nss;
5465 freq = cds_chan_to_freq(
5466 (WLAN_HDD_GET_AP_CTX_PTR(adapter))->operatingChannel);
5467 rate_flags = adapter->aStaInfo[sta_id].rate_flags;
5468 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07005469 hdd_err("Not Associated! with mac "MAC_ADDRESS_STR,
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305470 MAC_ADDR_ARRAY(peer_mac));
5471 return -EINVAL;
5472 }
5473
5474 if (!(rate_flags & eHAL_TX_RATE_LEGACY)) {
5475 if (rate_flags & eHAL_TX_RATE_VHT80) {
5476 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005477#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305478 final_rate_flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005479#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305480 } else if (rate_flags & eHAL_TX_RATE_VHT40) {
5481 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005482#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305483 final_rate_flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005484#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305485 } else if (rate_flags & eHAL_TX_RATE_VHT20) {
5486 final_rate_flags |= RATE_INFO_FLAGS_VHT_MCS;
5487 } else if (rate_flags &
5488 (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) {
5489 final_rate_flags |= RATE_INFO_FLAGS_MCS;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005490#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305491 if (rate_flags & eHAL_TX_RATE_HT40)
5492 final_rate_flags |=
5493 RATE_INFO_FLAGS_40_MHZ_WIDTH;
Ryan Hsu3a0f5232016-01-21 14:40:11 -08005494#endif
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305495 }
5496
5497 if (rate_flags & eHAL_TX_RATE_SGI) {
5498 if (!(final_rate_flags & RATE_INFO_FLAGS_VHT_MCS))
5499 final_rate_flags |= RATE_INFO_FLAGS_MCS;
5500 final_rate_flags |= RATE_INFO_FLAGS_SHORT_GI;
5501 }
5502 }
5503
5504 reply_skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
5505 sizeof(u8) + sizeof(u8) + sizeof(u32) + NLMSG_HDRLEN);
5506
5507 if (NULL == reply_skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07005508 hdd_err("getLinkProperties: skb alloc failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305509 return -EINVAL;
5510 }
5511
5512 if (nla_put_u8(reply_skb,
5513 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_NSS,
5514 nss) ||
5515 nla_put_u8(reply_skb,
5516 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_RATE_FLAGS,
5517 final_rate_flags) ||
5518 nla_put_u32(reply_skb,
5519 QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_FREQ,
5520 freq)) {
Jeff Johnson77848112016-06-29 14:52:06 -07005521 hdd_err("nla_put failed");
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05305522 kfree_skb(reply_skb);
5523 return -EINVAL;
5524 }
5525
5526 return cfg80211_vendor_cmd_reply(reply_skb);
5527}
5528
5529/**
5530 * wlan_hdd_cfg80211_get_link_properties() - Wrapper function to get link
5531 * properties.
5532 * @wiphy: WIPHY structure pointer
5533 * @wdev: Wireless device structure pointer
5534 * @data: Pointer to the data received
5535 * @data_len: Length of the data received
5536 *
5537 * This function is used to get link properties like nss, rate flags and
5538 * operating frequency for the active connection with the given peer.
5539 *
5540 * Return: 0 on success and errno on failure
5541 */
5542static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
5543 struct wireless_dev *wdev,
5544 const void *data,
5545 int data_len)
5546{
5547 int ret = 0;
5548
5549 cds_ssr_protect(__func__);
5550 ret = __wlan_hdd_cfg80211_get_link_properties(wiphy,
5551 wdev, data, data_len);
5552 cds_ssr_unprotect(__func__);
5553
5554 return ret;
5555}
5556
Peng Xu278d0122015-09-24 16:34:17 -07005557static const struct
5558nla_policy
5559qca_wlan_vendor_ota_test_policy
5560[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1] = {
5561 [QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE] = {.type = NLA_U8 },
5562};
5563
5564/**
5565 * __wlan_hdd_cfg80211_set_ota_test () - enable/disable OTA test
5566 * @wiphy: Pointer to wireless phy
5567 * @wdev: Pointer to wireless device
5568 * @data: Pointer to data
5569 * @data_len: Data length
5570 *
5571 * Return: 0 on success, negative errno on failure
5572 */
5573static int __wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5574 struct wireless_dev *wdev,
5575 const void *data,
5576 int data_len)
5577{
5578 struct net_device *dev = wdev->netdev;
5579 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5580 tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
5581 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5582 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX + 1];
5583 uint8_t ota_enable = 0;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305584 QDF_STATUS status;
Peng Xu278d0122015-09-24 16:34:17 -07005585 uint32_t current_roam_state;
5586
Jeff Johnson1f61b612016-02-12 16:28:33 -08005587 ENTER_DEV(dev);
5588
Anurag Chouhan6d760662016-02-20 16:05:43 +05305589 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Peng Xu278d0122015-09-24 16:34:17 -07005590 hdd_err("Command not allowed in FTM mode");
5591 return -EPERM;
5592 }
5593
5594 if (0 != wlan_hdd_validate_context(hdd_ctx))
5595 return -EINVAL;
5596
5597 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX,
5598 data, data_len,
5599 qca_wlan_vendor_ota_test_policy)) {
5600 hdd_err("invalid attr");
5601 return -EINVAL;
5602 }
5603
5604 if (!tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]) {
5605 hdd_err("attr ota test failed");
5606 return -EINVAL;
5607 }
5608
5609 ota_enable = nla_get_u8(
5610 tb[QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE]);
5611
5612 hdd_info(" OTA test enable = %d", ota_enable);
5613 if (ota_enable != 1) {
5614 hdd_err("Invalid value, only enable test mode is supported!");
5615 return -EINVAL;
5616 }
5617
5618 current_roam_state =
5619 sme_get_current_roam_state(hal, adapter->sessionId);
5620 status = sme_stop_roaming(hal, adapter->sessionId,
5621 eCsrHddIssued);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305622 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005623 hdd_err("Enable/Disable roaming failed");
5624 return -EINVAL;
5625 }
5626
5627 status = sme_ps_enable_disable(hal, adapter->sessionId,
5628 SME_PS_DISABLE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305629 if (status != QDF_STATUS_SUCCESS) {
Peng Xu278d0122015-09-24 16:34:17 -07005630 hdd_err("Enable/Disable power save failed");
5631 /* restore previous roaming setting */
5632 if (current_roam_state == eCSR_ROAMING_STATE_JOINING ||
5633 current_roam_state == eCSR_ROAMING_STATE_JOINED)
5634 status = sme_start_roaming(hal, adapter->sessionId,
5635 eCsrHddIssued);
5636 else if (current_roam_state == eCSR_ROAMING_STATE_STOP ||
5637 current_roam_state == eCSR_ROAMING_STATE_IDLE)
5638 status = sme_stop_roaming(hal, adapter->sessionId,
5639 eCsrHddIssued);
5640
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05305641 if (status != QDF_STATUS_SUCCESS)
Peng Xu278d0122015-09-24 16:34:17 -07005642 hdd_err("Restoring roaming state failed");
5643
5644 return -EINVAL;
5645 }
5646
5647
5648 return 0;
5649}
5650
5651/**
5652 * wlan_hdd_cfg80211_set_ota_test () - Enable or disable OTA test
5653 * @wiphy: Pointer to wireless phy
5654 * @wdev: Pointer to wireless device
5655 * @data: Pointer to data
5656 * @data_len: Data length
5657 *
5658 * Return: 0 on success, negative errno on failure
5659 */
5660static int wlan_hdd_cfg80211_set_ota_test(struct wiphy *wiphy,
5661 struct wireless_dev *wdev,
5662 const void *data,
5663 int data_len)
5664{
5665 int ret = 0;
5666
5667 cds_ssr_protect(__func__);
5668 ret = __wlan_hdd_cfg80211_set_ota_test(wiphy, wdev, data, data_len);
5669 cds_ssr_unprotect(__func__);
5670
5671 return ret;
5672}
5673
Peng Xu4d67c8f2015-10-16 16:02:26 -07005674/**
5675 * __wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5676 * @wiphy: Pointer to wireless phy
5677 * @wdev: Pointer to wireless device
5678 * @data: Pointer to data
5679 * @data_len: Data length
5680 *
5681 * Return: 0 on success, negative errno on failure
5682 */
5683static int __wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5684 struct wireless_dev *wdev,
5685 const void *data,
5686 int data_len)
5687{
5688 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5689 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005690 hdd_adapter_t *adapter;
5691 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005692 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX + 1];
5693 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005694 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005695
Jeff Johnson1f61b612016-02-12 16:28:33 -08005696 ENTER_DEV(dev);
5697
Peng Xu4d67c8f2015-10-16 16:02:26 -07005698 ret = wlan_hdd_validate_context(hdd_ctx);
5699 if (ret)
5700 return ret;
5701
5702 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5703
5704 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX,
5705 data, data_len, NULL)) {
5706 hdd_err("Invalid ATTR");
5707 return -EINVAL;
5708 }
5709
5710 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]) {
5711 hdd_err("attr tx power scale failed");
5712 return -EINVAL;
5713 }
5714
5715 scale_value = nla_get_u8(tb
5716 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE]);
5717
5718 if (scale_value > MAX_TXPOWER_SCALE) {
5719 hdd_err("Invalid tx power scale level");
5720 return -EINVAL;
5721 }
5722
Peng Xu62c8c432016-05-09 15:23:02 -07005723 status = wma_set_tx_power_scale(adapter->sessionId, scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005724
Peng Xu62c8c432016-05-09 15:23:02 -07005725 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005726 hdd_err("Set tx power scale failed");
5727 return -EINVAL;
5728 }
5729
5730 return 0;
5731}
5732
5733/**
5734 * wlan_hdd_cfg80211_txpower_scale () - txpower scaling
5735 * @wiphy: Pointer to wireless phy
5736 * @wdev: Pointer to wireless device
5737 * @data: Pointer to data
5738 * @data_len: Data length
5739 *
5740 * Return: 0 on success, negative errno on failure
5741 */
5742static int wlan_hdd_cfg80211_txpower_scale(struct wiphy *wiphy,
5743 struct wireless_dev *wdev,
5744 const void *data,
5745 int data_len)
5746{
Peng Xu62c8c432016-05-09 15:23:02 -07005747 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005748
5749 cds_ssr_protect(__func__);
5750 ret = __wlan_hdd_cfg80211_txpower_scale(wiphy, wdev,
5751 data, data_len);
5752 cds_ssr_unprotect(__func__);
5753
5754 return ret;
5755}
5756
5757/**
5758 * __wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5759 * @wiphy: Pointer to wireless phy
5760 * @wdev: Pointer to wireless device
5761 * @data: Pointer to data
5762 * @data_len: Data length
5763 *
5764 * Return: 0 on success, negative errno on failure
5765 */
5766static int __wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5767 struct wireless_dev *wdev,
5768 const void *data,
5769 int data_len)
5770{
5771 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5772 struct net_device *dev = wdev->netdev;
Peng Xu62c8c432016-05-09 15:23:02 -07005773 hdd_adapter_t *adapter;
5774 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005775 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX + 1];
5776 uint8_t scale_value;
Peng Xu62c8c432016-05-09 15:23:02 -07005777 QDF_STATUS status;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005778
Jeff Johnson1f61b612016-02-12 16:28:33 -08005779 ENTER_DEV(dev);
5780
Peng Xu4d67c8f2015-10-16 16:02:26 -07005781 ret = wlan_hdd_validate_context(hdd_ctx);
5782 if (ret)
5783 return ret;
5784
5785 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5786
5787 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB_MAX,
5788 data, data_len, NULL)) {
5789 hdd_err("Invalid ATTR");
5790 return -EINVAL;
5791 }
5792
5793 if (!tb[QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]) {
5794 hdd_err("attr tx power decrease db value failed");
5795 return -EINVAL;
5796 }
5797
5798 scale_value = nla_get_u8(tb
5799 [QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_DECR_DB]);
5800
Peng Xu62c8c432016-05-09 15:23:02 -07005801 status = wma_set_tx_power_scale_decr_db(adapter->sessionId,
5802 scale_value);
Peng Xu4d67c8f2015-10-16 16:02:26 -07005803
Peng Xu62c8c432016-05-09 15:23:02 -07005804 if (QDF_STATUS_SUCCESS != status) {
Peng Xu4d67c8f2015-10-16 16:02:26 -07005805 hdd_err("Set tx power decrease db failed");
5806 return -EINVAL;
5807 }
5808
5809 return 0;
5810}
5811
5812/**
5813 * wlan_hdd_cfg80211_txpower_scale_decr_db () - txpower scaling
5814 * @wiphy: Pointer to wireless phy
5815 * @wdev: Pointer to wireless device
5816 * @data: Pointer to data
5817 * @data_len: Data length
5818 *
5819 * Return: 0 on success, negative errno on failure
5820 */
5821static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy,
5822 struct wireless_dev *wdev,
5823 const void *data,
5824 int data_len)
5825{
Peng Xu62c8c432016-05-09 15:23:02 -07005826 int ret;
Peng Xu4d67c8f2015-10-16 16:02:26 -07005827
5828 cds_ssr_protect(__func__);
5829 ret = __wlan_hdd_cfg80211_txpower_scale_decr_db(wiphy, wdev,
5830 data, data_len);
5831 cds_ssr_unprotect(__func__);
5832
5833 return ret;
5834}
Peng Xu8fdaa492016-06-22 10:20:47 -07005835
5836/**
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05305837 * __wlan_hdd_cfg80211_conditional_chan_switch() - Conditional channel switch
5838 * @wiphy: Pointer to wireless phy
5839 * @wdev: Pointer to wireless device
5840 * @data: Pointer to data
5841 * @data_len: Data length
5842 *
5843 * Processes the conditional channel switch request and invokes the helper
5844 * APIs to process the channel switch request.
5845 *
5846 * Return: 0 on success, negative errno on failure
5847 */
5848static int __wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
5849 struct wireless_dev *wdev,
5850 const void *data,
5851 int data_len)
5852{
5853 int ret;
5854 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5855 struct net_device *dev = wdev->netdev;
5856 hdd_adapter_t *adapter;
5857 struct nlattr
5858 *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX + 1];
5859 uint32_t freq_len, i;
5860 uint32_t *freq;
5861 uint8_t chans[QDF_MAX_NUM_CHAN];
5862
5863 ENTER_DEV(dev);
5864
5865 ret = wlan_hdd_validate_context(hdd_ctx);
5866 if (ret)
5867 return ret;
5868
5869 if (!hdd_ctx->config->enableDFSMasterCap) {
5870 hdd_err("DFS master capability is not present in the driver");
5871 return -EINVAL;
5872 }
5873
5874 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5875 hdd_err("Command not allowed in FTM mode");
5876 return -EPERM;
5877 }
5878
5879 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5880 if (adapter->device_mode != QDF_SAP_MODE) {
5881 hdd_err("Invalid device mode %d", adapter->device_mode);
5882 return -EINVAL;
5883 }
5884
5885 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX,
5886 data, data_len, NULL)) {
5887 hdd_err("Invalid ATTR");
5888 return -EINVAL;
5889 }
5890
5891 if (!tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]) {
5892 hdd_err("Frequency list is missing");
5893 return -EINVAL;
5894 }
5895
5896 freq_len = nla_len(
5897 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST])/
5898 sizeof(uint32_t);
5899
5900 if (freq_len > QDF_MAX_NUM_CHAN) {
5901 hdd_err("insufficient space to hold channels");
5902 return -ENOMEM;
5903 }
5904
5905 hdd_debug("freq_len=%d", freq_len);
5906
5907 freq = nla_data(
5908 tb[QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST]);
5909
5910
5911 for (i = 0; i < freq_len; i++) {
5912 if (freq[i] == 0)
5913 chans[i] = 0;
5914 else
5915 chans[i] = ieee80211_frequency_to_channel(freq[i]);
5916
5917 hdd_debug("freq[%d]=%d", i, freq[i]);
5918 }
5919
5920 /*
5921 * The input frequency list from user space is designed to be a
5922 * priority based frequency list. This is only to accommodate any
5923 * future request. But, current requirement is only to perform CAC
5924 * on a single channel. So, the first entry from the list is picked.
5925 *
5926 * If channel is zero, any channel in the available outdoor regulatory
5927 * domain will be selected.
5928 */
5929 ret = wlan_hdd_request_pre_cac(chans[0]);
5930 if (ret) {
5931 hdd_err("pre cac request failed with reason:%d", ret);
5932 return ret;
5933 }
5934
5935 return 0;
5936}
5937
5938/**
Peng Xu8fdaa492016-06-22 10:20:47 -07005939 * __wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
5940 * @wiphy: Pointer to wireless phy
5941 * @wdev: Pointer to wireless device
5942 * @data: Pointer to data
5943 * @data_len: Data length
5944 *
5945 * This function is to process the p2p listen offload start vendor
5946 * command. It parses the input parameters and invoke WMA API to
5947 * send the command to firmware.
5948 *
5949 * Return: 0 on success, negative errno on failure
5950 */
5951static int __wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
5952 struct wireless_dev *wdev,
5953 const void *data,
5954 int data_len)
5955{
5956 int ret;
5957 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
5958 struct net_device *dev = wdev->netdev;
5959 hdd_adapter_t *adapter;
5960 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
5961 struct sir_p2p_lo_start params;
5962 QDF_STATUS status;
5963
5964 ENTER_DEV(dev);
5965
5966 ret = wlan_hdd_validate_context(hdd_ctx);
5967 if (ret)
5968 return ret;
5969
5970 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
5971 hdd_err("Command not allowed in FTM mode");
5972 return -EPERM;
5973 }
5974
5975 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
5976 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
5977 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
5978 (adapter->device_mode != QDF_P2P_GO_MODE)) {
5979 hdd_err("Invalid device mode %d", adapter->device_mode);
5980 return -EINVAL;
5981 }
5982
5983 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
5984 data, data_len, NULL)) {
5985 hdd_err("Invalid ATTR");
5986 return -EINVAL;
5987 }
5988
5989 memset(&params, 0, sizeof(params));
5990
5991 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG])
5992 params.ctl_flags = 1; /* set to default value */
5993 else
5994 params.ctl_flags = nla_get_u32(tb
5995 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG]);
5996
5997 if (!tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL] ||
5998 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD] ||
5999 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL] ||
6000 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT] ||
6001 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES] ||
6002 !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]) {
6003 hdd_err("Attribute parsing failed");
6004 return -EINVAL;
6005 }
6006
6007 params.vdev_id = adapter->sessionId;
6008 params.freq = nla_get_u32(tb
6009 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL]);
6010 if ((params.freq != 2412) && (params.freq != 2437) &&
6011 (params.freq != 2462)) {
6012 hdd_err("Invalid listening channel: %d", params.freq);
6013 return -EINVAL;
6014 }
6015
6016 params.period = nla_get_u32(tb
6017 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD]);
6018 if (!((params.period > 0) && (params.period < UINT_MAX))) {
6019 hdd_err("Invalid period: %d", params.period);
6020 return -EINVAL;
6021 }
6022
6023 params.interval = nla_get_u32(tb
6024 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL]);
6025 if (!((params.interval > 0) && (params.interval < UINT_MAX))) {
6026 hdd_err("Invalid interval: %d", params.interval);
6027 return -EINVAL;
6028 }
6029
6030 params.count = nla_get_u32(tb
6031 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT]);
6032 if (!((params.count > 0) && (params.count < UINT_MAX))) {
6033 hdd_err("Invalid count: %d", params.count);
6034 return -EINVAL;
6035 }
6036
6037 params.device_types = nla_data(tb
6038 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6039 if (params.device_types == NULL) {
6040 hdd_err("Invalid device types");
6041 return -EINVAL;
6042 }
6043
6044 params.dev_types_len = nla_len(tb
6045 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES]);
6046 if (params.dev_types_len < 8) {
6047 hdd_err("Invalid device type length: %d", params.dev_types_len);
6048 return -EINVAL;
6049 }
6050
6051 params.probe_resp_tmplt = nla_data(tb
6052 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6053 if (params.probe_resp_tmplt == NULL) {
6054 hdd_err("Invalid probe response template");
6055 return -EINVAL;
6056 }
6057
6058 params.probe_resp_len = nla_len(tb
6059 [QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE]);
6060 if (params.probe_resp_len == 0) {
6061 hdd_err("Invalid probe resp template length: %d",
6062 params.probe_resp_len);
6063 return -EINVAL;
6064 }
6065
6066 hdd_debug("P2P LO params: freq=%d, period=%d, interval=%d, count=%d",
6067 params.freq, params.period, params.interval, params.count);
6068
6069 status = wma_p2p_lo_start(&params);
6070
6071 if (!QDF_IS_STATUS_SUCCESS(status)) {
6072 hdd_err("P2P LO start failed");
6073 return -EINVAL;
6074 }
6075
6076 return 0;
6077}
6078
6079
6080/**
6081 * wlan_hdd_cfg80211_p2p_lo_start () - start P2P Listen Offload
6082 * @wiphy: Pointer to wireless phy
6083 * @wdev: Pointer to wireless device
6084 * @data: Pointer to data
6085 * @data_len: Data length
6086 *
6087 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_start()
6088 * to process p2p listen offload start vendor command.
6089 *
6090 * Return: 0 on success, negative errno on failure
6091 */
6092static int wlan_hdd_cfg80211_p2p_lo_start(struct wiphy *wiphy,
6093 struct wireless_dev *wdev,
6094 const void *data,
6095 int data_len)
6096{
6097 int ret = 0;
6098
6099 cds_ssr_protect(__func__);
6100 ret = __wlan_hdd_cfg80211_p2p_lo_start(wiphy, wdev,
6101 data, data_len);
6102 cds_ssr_unprotect(__func__);
6103
6104 return ret;
6105}
6106
6107/**
6108 * __wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6109 * @wiphy: Pointer to wireless phy
6110 * @wdev: Pointer to wireless device
6111 * @data: Pointer to data
6112 * @data_len: Data length
6113 *
6114 * This function is to process the p2p listen offload stop vendor
6115 * command. It invokes WMA API to send command to firmware.
6116 *
6117 * Return: 0 on success, negative errno on failure
6118 */
6119static int __wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6120 struct wireless_dev *wdev,
6121 const void *data,
6122 int data_len)
6123{
6124 QDF_STATUS status;
6125 hdd_adapter_t *adapter;
6126 struct net_device *dev = wdev->netdev;
6127
6128 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6129 hdd_err("Command not allowed in FTM mode");
6130 return -EPERM;
6131 }
6132
6133 adapter = WLAN_HDD_GET_PRIV_PTR(dev);
6134 if ((adapter->device_mode != QDF_P2P_DEVICE_MODE) &&
6135 (adapter->device_mode != QDF_P2P_CLIENT_MODE) &&
6136 (adapter->device_mode != QDF_P2P_GO_MODE)) {
6137 hdd_err("Invalid device mode");
6138 return -EINVAL;
6139 }
6140
6141 status = wma_p2p_lo_stop(adapter->sessionId);
6142
6143 if (!QDF_IS_STATUS_SUCCESS(status)) {
6144 hdd_err("P2P LO stop failed");
6145 return -EINVAL;
6146 }
6147
6148 return 0;
6149}
6150
6151/**
6152 * wlan_hdd_cfg80211_p2p_lo_stop () - stop P2P Listen Offload
6153 * @wiphy: Pointer to wireless phy
6154 * @wdev: Pointer to wireless device
6155 * @data: Pointer to data
6156 * @data_len: Data length
6157 *
6158 * This function inovkes internal __wlan_hdd_cfg80211_p2p_lo_stop()
6159 * to process p2p listen offload stop vendor command.
6160 *
6161 * Return: 0 on success, negative errno on failure
6162 */
6163static int wlan_hdd_cfg80211_p2p_lo_stop(struct wiphy *wiphy,
6164 struct wireless_dev *wdev,
6165 const void *data,
6166 int data_len)
6167{
6168 int ret = 0;
6169
6170 cds_ssr_protect(__func__);
6171 ret = __wlan_hdd_cfg80211_p2p_lo_stop(wiphy, wdev,
6172 data, data_len);
6173 cds_ssr_unprotect(__func__);
6174
6175 return ret;
6176}
6177
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306178/**
6179 * wlan_hdd_cfg80211_conditional_chan_switch() - SAP conditional channel switch
6180 * @wiphy: Pointer to wireless phy
6181 * @wdev: Pointer to wireless device
6182 * @data: Pointer to data
6183 * @data_len: Data length
6184 *
6185 * Inovkes internal API __wlan_hdd_cfg80211_conditional_chan_switch()
6186 * to process the conditional channel switch request.
6187 *
6188 * Return: 0 on success, negative errno on failure
6189 */
6190static int wlan_hdd_cfg80211_conditional_chan_switch(struct wiphy *wiphy,
6191 struct wireless_dev *wdev,
6192 const void *data,
6193 int data_len)
6194{
6195 int ret;
6196
6197 cds_ssr_protect(__func__);
6198 ret = __wlan_hdd_cfg80211_conditional_chan_switch(wiphy, wdev,
6199 data, data_len);
6200 cds_ssr_unprotect(__func__);
6201
6202 return ret;
6203}
6204
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306205/*
6206 * define short names for the global vendor params
6207 * used by __wlan_hdd_cfg80211_bpf_offload()
6208 */
6209#define BPF_INVALID \
6210 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID
6211#define BPF_SET_RESET \
6212 QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER
6213#define BPF_VERSION \
6214 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION
6215#define BPF_FILTER_ID \
6216 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID
6217#define BPF_PACKET_SIZE \
6218 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE
6219#define BPF_CURRENT_OFFSET \
6220 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET
6221#define BPF_PROGRAM \
6222 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM
6223#define BPF_MAX \
6224 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX
Peng Xu4d67c8f2015-10-16 16:02:26 -07006225
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306226static const struct nla_policy
6227wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = {
6228 [BPF_SET_RESET] = {.type = NLA_U32},
6229 [BPF_VERSION] = {.type = NLA_U32},
6230 [BPF_FILTER_ID] = {.type = NLA_U32},
6231 [BPF_PACKET_SIZE] = {.type = NLA_U32},
6232 [BPF_CURRENT_OFFSET] = {.type = NLA_U32},
6233 [BPF_PROGRAM] = {.type = NLA_U8},
6234};
6235
6236/**
6237 * hdd_get_bpf_offload_cb() - Callback function to BPF Offload
6238 * @hdd_context: hdd_context
6239 * @bpf_get_offload: struct for get offload
6240 *
6241 * This function receives the response/data from the lower layer and
6242 * checks to see if the thread is still waiting then post the results to
6243 * upper layer, if the request has timed out then ignore.
6244 *
6245 * Return: None
6246 */
6247void hdd_get_bpf_offload_cb(void *hdd_context,
6248 struct sir_bpf_get_offload *data)
6249{
6250 hdd_context_t *hdd_ctx = hdd_context;
6251 struct hdd_bpf_context *context;
6252
6253 ENTER();
6254
6255 if (wlan_hdd_validate_context(hdd_ctx) || !data) {
Jeff Johnson77848112016-06-29 14:52:06 -07006256 hdd_err("HDD context is invalid or data(%p) is null",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306257 data);
6258 return;
6259 }
6260
6261 spin_lock(&hdd_context_lock);
6262
6263 context = &bpf_context;
6264 /* The caller presumably timed out so there is nothing we can do */
6265 if (context->magic != BPF_CONTEXT_MAGIC) {
6266 spin_unlock(&hdd_context_lock);
6267 return;
6268 }
6269
6270 /* context is valid so caller is still waiting */
6271 /* paranoia: invalidate the magic */
6272 context->magic = 0;
6273
6274 context->capability_response = *data;
6275 complete(&context->completion);
6276
6277 spin_unlock(&hdd_context_lock);
6278
6279 return;
6280}
6281
6282/**
6283 * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload
6284 * @hdd_context: hdd_context
6285 * @bpf_get_offload: struct for get offload
6286 *
6287 * Return: 0 on success, error number otherwise.
6288 */
6289static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx,
6290 struct sir_bpf_get_offload *bpf_get_offload)
6291{
6292 struct sk_buff *skb;
6293 uint32_t nl_buf_len;
6294
6295 ENTER();
6296
6297 nl_buf_len = NLMSG_HDRLEN;
6298 nl_buf_len +=
6299 (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) +
6300 (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN);
6301
6302 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
6303 if (!skb) {
Jeff Johnson77848112016-06-29 14:52:06 -07006304 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306305 return -ENOMEM;
6306 }
6307
Jeff Johnson77848112016-06-29 14:52:06 -07006308 hdd_notice("BPF Version: %u BPF max bytes: %u",
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306309 bpf_get_offload->bpf_version,
6310 bpf_get_offload->max_bytes_for_bpf_inst);
6311
6312 if (nla_put_u32(skb, BPF_PACKET_SIZE,
6313 bpf_get_offload->max_bytes_for_bpf_inst) ||
6314 nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006315 hdd_err("nla put failure");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306316 goto nla_put_failure;
6317 }
6318
6319 cfg80211_vendor_cmd_reply(skb);
6320 EXIT();
6321 return 0;
6322
6323nla_put_failure:
6324 kfree_skb(skb);
6325 return -EINVAL;
6326}
6327
6328/**
6329 * hdd_get_bpf_offload - Get BPF offload Capabilities
6330 * @hdd_ctx: Hdd context
6331 *
6332 * Return: 0 on success, errno on failure
6333 */
6334static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx)
6335{
6336 unsigned long rc;
6337 struct hdd_bpf_context *context;
6338 QDF_STATUS status;
6339 int ret;
6340
6341 ENTER();
6342
6343 spin_lock(&hdd_context_lock);
6344 context = &bpf_context;
6345 context->magic = BPF_CONTEXT_MAGIC;
6346 INIT_COMPLETION(context->completion);
6347 spin_unlock(&hdd_context_lock);
6348
6349 status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal);
6350 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006351 hdd_err("Unable to retrieve BPF caps");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306352 return -EINVAL;
6353 }
6354 /* request was sent -- wait for the response */
6355 rc = wait_for_completion_timeout(&context->completion,
6356 msecs_to_jiffies(WLAN_WAIT_TIME_BPF));
6357 if (!rc) {
Jeff Johnson77848112016-06-29 14:52:06 -07006358 hdd_err("Target response timed out");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306359 spin_lock(&hdd_context_lock);
6360 context->magic = 0;
6361 spin_unlock(&hdd_context_lock);
6362
6363 return -ETIMEDOUT;
6364 }
6365 ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx,
6366 &bpf_context.capability_response);
6367 if (ret)
Jeff Johnson77848112016-06-29 14:52:06 -07006368 hdd_err("Failed to post get bpf capabilities");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306369
6370 EXIT();
6371 return ret;
6372}
6373
6374/**
6375 * hdd_set_reset_bpf_offload - Post set/reset bpf to SME
6376 * @hdd_ctx: Hdd context
6377 * @tb: Length of @data
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306378 * @adapter: pointer to adapter struct
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306379 *
6380 * Return: 0 on success; errno on failure
6381 */
6382static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx,
6383 struct nlattr **tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306384 hdd_adapter_t *adapter)
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306385{
6386 struct sir_bpf_set_offload *bpf_set_offload;
6387 QDF_STATUS status;
6388 int prog_len;
Arun Khandavalli08500812016-07-25 14:58:42 +05306389 int ret = 0;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306390
6391 ENTER();
6392
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306393 if (adapter->device_mode == QDF_STA_MODE ||
6394 adapter->device_mode == QDF_P2P_CLIENT_MODE) {
6395 if (!hdd_conn_is_connected(
6396 WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
6397 hdd_err("Not in Connected state!");
6398 return -ENOTSUPP;
6399 }
6400 }
6401
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306402 bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload));
6403 if (bpf_set_offload == NULL) {
Jeff Johnson77848112016-06-29 14:52:06 -07006404 hdd_err("qdf_mem_malloc failed for bpf_set_offload");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306405 return -ENOMEM;
6406 }
6407 qdf_mem_zero(bpf_set_offload, sizeof(*bpf_set_offload));
6408
6409 /* Parse and fetch bpf packet size */
6410 if (!tb[BPF_PACKET_SIZE]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006411 hdd_err("attr bpf packet size failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306412 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306413 goto fail;
6414 }
6415 bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]);
6416
6417 if (!bpf_set_offload->total_length) {
Jeff Johnson77848112016-06-29 14:52:06 -07006418 hdd_notice("BPF reset packet filter received");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306419 goto post_sme;
6420 }
6421
6422 /* Parse and fetch bpf program */
6423 if (!tb[BPF_PROGRAM]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006424 hdd_err("attr bpf program failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306425 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306426 goto fail;
6427 }
6428
6429 prog_len = nla_len(tb[BPF_PROGRAM]);
6430 bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len);
Arun Khandavalli08500812016-07-25 14:58:42 +05306431
6432 if (bpf_set_offload->program == NULL) {
6433 hdd_err("qdf_mem_malloc failed for bpf offload program");
6434 ret = -ENOMEM;
6435 goto fail;
6436 }
6437
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306438 bpf_set_offload->current_length = prog_len;
6439 nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len);
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306440 bpf_set_offload->session_id = adapter->sessionId;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306441
Rajeev Kumar Sirasanagandla62b63032016-08-22 14:56:57 +05306442 hdd_info("BPF set instructions");
6443 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO,
6444 bpf_set_offload->program, prog_len);
6445
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306446 /* Parse and fetch filter Id */
6447 if (!tb[BPF_FILTER_ID]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006448 hdd_err("attr filter id failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306449 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306450 goto fail;
6451 }
6452 bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]);
6453
6454 /* Parse and fetch current offset */
6455 if (!tb[BPF_CURRENT_OFFSET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006456 hdd_err("attr current offset failed");
Arun Khandavalli08500812016-07-25 14:58:42 +05306457 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306458 goto fail;
6459 }
6460 bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]);
6461
6462post_sme:
Jeff Johnson77848112016-06-29 14:52:06 -07006463 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 +05306464 bpf_set_offload->session_id,
6465 bpf_set_offload->version,
6466 bpf_set_offload->filter_id,
6467 bpf_set_offload->total_length,
6468 bpf_set_offload->current_length,
6469 bpf_set_offload->current_offset);
6470
6471 status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload);
6472 if (!QDF_IS_STATUS_SUCCESS(status)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006473 hdd_err("sme_set_bpf_instructions failed(err=%d)", status);
Arun Khandavalli08500812016-07-25 14:58:42 +05306474 ret = -EINVAL;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306475 goto fail;
6476 }
6477 EXIT();
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306478
6479fail:
6480 if (bpf_set_offload->current_length)
6481 qdf_mem_free(bpf_set_offload->program);
6482 qdf_mem_free(bpf_set_offload);
Arun Khandavalli08500812016-07-25 14:58:42 +05306483 return ret;
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306484}
6485
6486/**
6487 * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload
6488 * @wiphy: wiphy structure pointer
6489 * @wdev: Wireless device structure pointer
6490 * @data: Pointer to the data received
6491 * @data_len: Length of @data
6492 *
6493 * Return: 0 on success; errno on failure
6494 */
6495static int
6496__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6497 struct wireless_dev *wdev,
6498 const void *data, int data_len)
6499{
6500 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6501 struct net_device *dev = wdev->netdev;
6502 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
6503 struct nlattr *tb[BPF_MAX + 1];
6504 int ret_val, packet_filter_subcmd;
6505
6506 ENTER();
6507
6508 ret_val = wlan_hdd_validate_context(hdd_ctx);
6509 if (ret_val)
6510 return ret_val;
6511
6512 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07006513 hdd_err("Command not allowed in FTM mode");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306514 return -EINVAL;
6515 }
6516
6517 if (!hdd_ctx->bpf_enabled) {
Rajeev Kumardd3bc602016-08-16 14:21:05 -07006518 hdd_err("BPF offload is not supported/enabled");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306519 return -ENOTSUPP;
6520 }
6521
6522 if (nla_parse(tb, BPF_MAX, data, data_len,
6523 wlan_hdd_bpf_offload_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07006524 hdd_err("Invalid ATTR");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306525 return -EINVAL;
6526 }
6527
6528 if (!tb[BPF_SET_RESET]) {
Jeff Johnson77848112016-06-29 14:52:06 -07006529 hdd_err("attr bpf set reset failed");
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306530 return -EINVAL;
6531 }
6532
6533 packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]);
6534
6535 if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER)
6536 return hdd_get_bpf_offload(hdd_ctx);
6537 else
6538 return hdd_set_reset_bpf_offload(hdd_ctx, tb,
Arun Khandavalli3dd06de2016-08-17 10:20:29 +05306539 pAdapter);
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306540}
6541
6542/**
6543 * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload
6544 * @wiphy: wiphy structure pointer
6545 * @wdev: Wireless device structure pointer
6546 * @data: Pointer to the data received
6547 * @data_len: Length of @data
6548 *
6549 * Return: 0 on success; errno on failure
6550 */
6551
6552static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy,
6553 struct wireless_dev *wdev,
6554 const void *data, int data_len)
6555{
6556 int ret;
6557
6558 cds_ssr_protect(__func__);
6559 ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len);
6560 cds_ssr_unprotect(__func__);
6561
6562 return ret;
6563}
6564
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306565/**
6566 * wlan_hdd_set_pre_cac_status() - Set the pre cac status
6567 * @pre_cac_adapter: AP adapter used for pre cac
6568 * @status: Status (true or false)
6569 * @handle: Global handle
6570 *
6571 * Sets the status of pre cac i.e., whether the pre cac is active or not
6572 *
6573 * Return: Zero on success, non-zero on failure
6574 */
6575static int wlan_hdd_set_pre_cac_status(hdd_adapter_t *pre_cac_adapter,
6576 bool status, tHalHandle handle)
6577{
6578 QDF_STATUS ret;
6579
6580 ret = wlan_sap_set_pre_cac_status(
6581 WLAN_HDD_GET_SAP_CTX_PTR(pre_cac_adapter), status, handle);
6582 if (QDF_IS_STATUS_ERROR(ret))
6583 return -EINVAL;
6584
6585 return 0;
6586}
6587
6588/**
6589 * wlan_hdd_set_chan_before_pre_cac() - Save the channel before pre cac
6590 * @ap_adapter: AP adapter
6591 * @chan_before_pre_cac: Channel
6592 *
6593 * Saves the channel which the AP was beaconing on before moving to the pre
6594 * cac channel. If radar is detected on the pre cac channel, this saved
6595 * channel will be used for AP operations.
6596 *
6597 * Return: Zero on success, non-zero on failure
6598 */
6599static int wlan_hdd_set_chan_before_pre_cac(hdd_adapter_t *ap_adapter,
6600 uint8_t chan_before_pre_cac)
6601{
6602 QDF_STATUS ret;
6603
6604 ret = wlan_sap_set_chan_before_pre_cac(
6605 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), chan_before_pre_cac);
6606 if (QDF_IS_STATUS_ERROR(ret))
6607 return -EINVAL;
6608
6609 return 0;
6610}
6611
6612/**
6613 * wlan_hdd_sap_get_nol() - Get SAPs NOL
6614 * @ap_adapter: AP adapter
6615 * @nol: Non-occupancy list
6616 * @nol_len: Length of NOL
6617 *
6618 * Get the NOL for SAP
6619 *
6620 * Return: Zero on success, non-zero on failure
6621 */
6622static int wlan_hdd_sap_get_nol(hdd_adapter_t *ap_adapter, uint8_t *nol,
6623 uint32_t *nol_len)
6624{
6625 QDF_STATUS ret;
6626
6627 ret = wlansap_get_dfs_nol(WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter),
6628 nol, nol_len);
6629 if (QDF_IS_STATUS_ERROR(ret))
6630 return -EINVAL;
6631
6632 return 0;
6633}
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306634
6635/**
6636 * wlan_hdd_validate_and_get_pre_cac_ch() - Validate and get pre cac channel
6637 * @hdd_ctx: HDD context
6638 * @ap_adapter: AP adapter
6639 * @channel: Channel requested by userspace
6640 * @pre_cac_chan: Pointer to the pre CAC channel
6641 *
6642 * Validates the channel provided by userspace. If user provided channel 0,
6643 * a valid outdoor channel must be selected from the regulatory channel.
6644 *
6645 * Return: Zero on success and non zero value on error
6646 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -07006647static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx,
6648 hdd_adapter_t *ap_adapter,
6649 uint8_t channel,
6650 uint8_t *pre_cac_chan)
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306651{
6652 uint32_t i, j;
6653 QDF_STATUS status;
6654 int ret;
6655 uint8_t nol[QDF_MAX_NUM_CHAN];
6656 uint32_t nol_len = 0, weight_len = 0;
6657 bool found;
6658 uint32_t len = WNI_CFG_VALID_CHANNEL_LIST_LEN;
6659 uint8_t channel_list[QDF_MAX_NUM_CHAN] = {0};
6660 uint8_t pcl_weights[QDF_MAX_NUM_CHAN] = {0};
6661
6662 if (0 == channel) {
6663 /* Channel is not obtained from PCL because PCL may not have
6664 * the entire channel list. For example: if SAP is up on
6665 * channel 6 and PCL is queried for the next SAP interface,
6666 * if SCC is preferred, the PCL will contain only the channel
6667 * 6. But, we are in need of a DFS channel. So, going with the
6668 * first channel from the valid channel list.
6669 */
6670 status = cds_get_valid_chans(channel_list, &len);
6671 if (QDF_IS_STATUS_ERROR(status)) {
6672 hdd_err("Failed to get channel list");
6673 return -EINVAL;
6674 }
6675 cds_update_with_safe_channel_list(channel_list, &len,
6676 pcl_weights, weight_len);
6677 ret = wlan_hdd_sap_get_nol(ap_adapter, nol, &nol_len);
6678 for (i = 0; i < len; i++) {
6679 found = false;
6680 for (j = 0; j < nol_len; j++) {
6681 if (channel_list[i] == nol[j]) {
6682 found = true;
6683 break;
6684 }
6685 }
6686 if (found)
6687 continue;
6688 if (CDS_IS_DFS_CH(channel_list[i])) {
6689 *pre_cac_chan = channel_list[i];
6690 break;
6691 }
6692 }
6693 if (*pre_cac_chan == 0) {
6694 hdd_err("unable to find outdoor channel");
6695 return -EINVAL;
6696 }
6697 } else {
6698 /* Only when driver selects a channel, check is done for
6699 * unnsafe and NOL channels. When user provides a fixed channel
6700 * the user is expected to take care of this.
6701 */
6702 if (!sme_is_channel_valid(hdd_ctx->hHal, channel) ||
6703 !CDS_IS_DFS_CH(channel)) {
6704 hdd_err("Invalid channel for pre cac:%d", channel);
6705 return -EINVAL;
6706 } else {
6707 *pre_cac_chan = channel;
6708 }
6709 }
6710 hdd_info("selected pre cac channel:%d", *pre_cac_chan);
6711 return 0;
6712}
6713
6714/**
6715 * wlan_hdd_request_pre_cac() - Start pre CAC in the driver
6716 * @channel: Channel option provided by userspace
6717 *
6718 * Sets the driver to the required hardware mode and start an adapater for
6719 * pre CAC which will mimic an AP.
6720 *
6721 * Return: Zero on success, non-zero value on error
6722 */
6723int wlan_hdd_request_pre_cac(uint8_t channel)
6724{
6725 uint8_t pre_cac_chan = 0;
6726 hdd_context_t *hdd_ctx;
6727 int ret;
6728 hdd_adapter_t *ap_adapter, *pre_cac_adapter;
6729 hdd_ap_ctx_t *hdd_ap_ctx;
6730 QDF_STATUS status;
6731 struct wiphy *wiphy;
6732 struct net_device *dev;
6733 struct cfg80211_chan_def chandef;
6734 enum nl80211_channel_type channel_type;
6735 uint32_t freq;
6736 struct ieee80211_channel *chan;
6737 tHalHandle handle;
6738 bool val;
6739
6740 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
6741 if (0 != wlan_hdd_validate_context(hdd_ctx))
6742 return -EINVAL;
6743
6744 if (cds_get_connection_count() > 1) {
6745 hdd_err("pre cac not allowed in concurrency");
6746 return -EINVAL;
6747 }
6748
6749 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
6750 if (!ap_adapter) {
6751 hdd_err("unable to get SAP adapter");
6752 return -EINVAL;
6753 }
6754
6755 handle = WLAN_HDD_GET_HAL_CTX(ap_adapter);
6756 if (!handle) {
6757 hdd_err("Invalid handle");
6758 return -EINVAL;
6759 }
6760
6761 val = wlan_sap_is_pre_cac_active(handle);
6762 if (val) {
6763 hdd_err("pre cac is already in progress");
6764 return -EINVAL;
6765 }
6766
6767 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
6768 if (!hdd_ap_ctx) {
6769 hdd_err("SAP context is NULL");
6770 return -EINVAL;
6771 }
6772
6773 if (CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
6774 hdd_err("SAP is already on DFS channel:%d",
6775 hdd_ap_ctx->operatingChannel);
6776 return -EINVAL;
6777 }
6778
6779 if (!CDS_IS_CHANNEL_24GHZ(hdd_ap_ctx->operatingChannel)) {
6780 hdd_err("pre CAC alllowed only when SAP is in 2.4GHz:%d",
6781 hdd_ap_ctx->operatingChannel);
6782 return -EINVAL;
6783 }
6784
6785 hdd_info("channel:%d", channel);
6786
6787 ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel,
6788 &pre_cac_chan);
6789 if (ret != 0)
6790 return ret;
6791
6792 /* Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this
6793 * connection update should result in DBS mode
6794 */
6795 status = cds_update_and_wait_for_connection_update(
6796 ap_adapter->sessionId,
6797 pre_cac_chan,
6798 SIR_UPDATE_REASON_PRE_CAC);
6799 if (QDF_IS_STATUS_ERROR(status)) {
6800 hdd_err("error in moving to DBS mode");
6801 return -EINVAL;
6802 }
6803
6804 hdd_debug("starting pre cac SAP adapter");
6805
6806 /* Starting a SAP adapter:
6807 * Instead of opening an adapter, we could just do a SME open session
6808 * for AP type. But, start BSS would still need an adapter.
6809 * So, this option is not taken.
6810 *
6811 * hdd open adapter is going to register this precac interface with
6812 * user space. This interface though exposed to user space will be in
6813 * DOWN state. Consideration was done to avoid this registration to the
6814 * user space. But, as part of SAP operations multiple events are sent
6815 * to user space. Some of these events received from unregistered
6816 * interface was causing crashes. So, retaining the registration.
6817 *
6818 * So, this interface would remain registered and will remain in DOWN
6819 * state for the CAC duration. We will add notes in the feature
6820 * announcement to not use this temporary interface for any activity
6821 * from user space.
6822 */
6823 pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d",
6824 wlan_hdd_get_intf_addr(hdd_ctx),
6825 NET_NAME_UNKNOWN, true);
6826 if (!pre_cac_adapter) {
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306827 hdd_err("error opening the pre cac adapter");
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306828 return -EINVAL;
6829 }
6830
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306831 /*
6832 * This interface is internally created by the driver. So, no interface
6833 * up comes for this interface from user space and hence starting
6834 * the adapter internally.
6835 */
6836 if (hdd_start_adapter(pre_cac_adapter)) {
6837 hdd_err("error starting the pre cac adapter");
6838 goto close_pre_cac_adapter;
6839 }
6840
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306841 hdd_debug("preparing for start ap/bss on the pre cac adapter");
6842
6843 wiphy = hdd_ctx->wiphy;
6844 dev = pre_cac_adapter->dev;
6845
6846 /* Since this is only a dummy interface lets us use the IEs from the
6847 * other active SAP interface. In regular scenarios, these IEs would
6848 * come from the user space entity
6849 */
6850 pre_cac_adapter->sessionCtx.ap.beacon = qdf_mem_malloc(
6851 sizeof(*ap_adapter->sessionCtx.ap.beacon));
6852 if (!pre_cac_adapter->sessionCtx.ap.beacon) {
6853 hdd_err("failed to alloc mem for beacon");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306854 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306855 }
6856 qdf_mem_copy(pre_cac_adapter->sessionCtx.ap.beacon,
6857 ap_adapter->sessionCtx.ap.beacon,
6858 sizeof(*pre_cac_adapter->sessionCtx.ap.beacon));
6859 pre_cac_adapter->sessionCtx.ap.sapConfig.ch_width_orig =
6860 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig;
6861 pre_cac_adapter->sessionCtx.ap.sapConfig.authType =
6862 ap_adapter->sessionCtx.ap.sapConfig.authType;
6863
6864 /* Premise is that on moving from 2.4GHz to 5GHz, the SAP will continue
6865 * to operate on the same bandwidth as that of the 2.4GHz operations.
6866 * Only bandwidths 20MHz/40MHz are possible on 2.4GHz band.
6867 */
6868 switch (ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig) {
6869 case CH_WIDTH_20MHZ:
6870 channel_type = NL80211_CHAN_HT20;
6871 break;
6872 case CH_WIDTH_40MHZ:
6873 if (ap_adapter->sessionCtx.ap.sapConfig.sec_ch >
6874 ap_adapter->sessionCtx.ap.sapConfig.channel)
6875 channel_type = NL80211_CHAN_HT40PLUS;
6876 else
6877 channel_type = NL80211_CHAN_HT40MINUS;
6878 break;
6879 default:
6880 channel_type = NL80211_CHAN_NO_HT;
6881 break;
6882 }
6883
6884 freq = cds_chan_to_freq(pre_cac_chan);
6885 chan = __ieee80211_get_channel(wiphy, freq);
6886 if (!chan) {
6887 hdd_err("channel converion failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306888 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306889 }
6890
6891 cfg80211_chandef_create(&chandef, chan, channel_type);
6892
6893 hdd_debug("orig width:%d channel_type:%d freq:%d",
6894 ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig,
6895 channel_type, freq);
6896
6897 ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type);
6898 if (0 != ret) {
6899 hdd_err("failed to set channel");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306900 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306901 }
6902
6903 status = wlan_hdd_cfg80211_start_bss(pre_cac_adapter, NULL,
6904 PRE_CAC_SSID, qdf_str_len(PRE_CAC_SSID),
6905 eHIDDEN_SSID_NOT_IN_USE, false);
6906 if (QDF_IS_STATUS_ERROR(status)) {
6907 hdd_err("start bss failed");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306908 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306909 }
6910
6911 /*
6912 * The pre cac status is set here. But, it would not be reset explicitly
6913 * anywhere, since after the pre cac success/failure, the pre cac
6914 * adapter itself would be removed.
6915 */
6916 ret = wlan_hdd_set_pre_cac_status(pre_cac_adapter, true, handle);
6917 if (0 != ret) {
6918 hdd_err("failed to set pre cac status");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306919 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306920 }
6921
6922 ret = wlan_hdd_set_chan_before_pre_cac(ap_adapter,
6923 hdd_ap_ctx->operatingChannel);
6924 if (0 != ret) {
6925 hdd_err("failed to set channel before pre cac");
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306926 goto stop_close_pre_cac_adapter;
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306927 }
6928
6929 ap_adapter->pre_cac_chan = pre_cac_chan;
6930
6931 return 0;
6932
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306933stop_close_pre_cac_adapter:
6934 hdd_stop_adapter(hdd_ctx, pre_cac_adapter, true);
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306935 qdf_mem_free(pre_cac_adapter->sessionCtx.ap.beacon);
6936 pre_cac_adapter->sessionCtx.ap.beacon = NULL;
Manishekar Chandrasekarandfdf2a82016-08-24 16:16:16 +05306937close_pre_cac_adapter:
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05306938 hdd_close_adapter(hdd_ctx, pre_cac_adapter, false);
6939 return -EINVAL;
6940}
6941
Arun Khandavalli2476ef52016-04-26 20:19:43 +05306942/**
6943 * hdd_init_bpf_completion() - Initialize the completion event for bpf
6944 *
6945 * Return: None
6946 */
6947void hdd_init_bpf_completion(void)
6948{
6949 init_completion(&bpf_context.completion);
6950}
6951
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05306952static const struct nla_policy
6953wlan_hdd_sap_config_policy[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1] = {
6954 [QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL] = {.type = NLA_U8 },
6955};
6956
Agrawal Ashish65634612016-08-18 13:24:32 +05306957static const struct nla_policy
6958wlan_hdd_set_acs_dfs_config_policy[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1] = {
6959 [QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE] = {.type = NLA_U8 },
6960 [QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT] = {.type = NLA_U8 },
6961};
6962
6963/**
6964 * __wlan_hdd_cfg80211_acs_dfs_mode() - set ACS DFS mode and channel
6965 * @wiphy: Pointer to wireless phy
6966 * @wdev: Pointer to wireless device
6967 * @data: Pointer to data
6968 * @data_len: Length of @data
6969 *
6970 * This function parses the incoming NL vendor command data attributes and
6971 * updates the SAP context about channel_hint and DFS mode.
6972 * If channel_hint is set, SAP will choose that channel
6973 * as operating channel.
6974 *
6975 * If DFS mode is enabled, driver will include DFS channels
6976 * in ACS else driver will skip DFS channels.
6977 *
6978 * Return: 0 on success, negative errno on failure
6979 */
6980static int
6981__wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
6982 struct wireless_dev *wdev,
6983 const void *data, int data_len)
6984{
6985 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
6986 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX + 1];
6987 int ret;
6988 struct acs_dfs_policy *acs_policy;
6989 int mode = DFS_MODE_NONE;
6990 int channel_hint = 0;
6991
6992 ENTER_DEV(wdev->netdev);
6993
6994 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
6995 hdd_err("Command not allowed in FTM mode");
6996 return -EINVAL;
6997 }
6998
6999 ret = wlan_hdd_validate_context(hdd_ctx);
7000 if (0 != ret)
7001 return ret;
7002
7003 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX,
7004 data, data_len,
7005 wlan_hdd_set_acs_dfs_config_policy)) {
7006 hdd_err("invalid attr");
7007 return -EINVAL;
7008 }
7009
7010 acs_policy = &hdd_ctx->acs_policy;
7011 /*
7012 * SCM sends this attribute to restrict SAP from choosing
7013 * DFS channels from ACS.
7014 */
7015 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE])
7016 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE]);
7017
7018 if (!IS_DFS_MODE_VALID(mode)) {
7019 hdd_err("attr acs dfs mode is not valid");
7020 return -EINVAL;
7021 }
7022 acs_policy->acs_dfs_mode = mode;
7023
7024 /*
7025 * SCM sends this attribute to provide an active channel,
7026 * to skip redundant ACS between drivers, and save driver start up time
7027 */
7028 if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT])
7029 channel_hint = nla_get_u8(
7030 tb[QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT]);
7031
7032 if (!IS_CHANNEL_VALID(channel_hint)) {
7033 hdd_err("acs channel is not valid");
7034 return -EINVAL;
7035 }
7036 acs_policy->acs_channel = channel_hint;
7037
7038 return 0;
7039}
7040
7041/**
7042 * wlan_hdd_cfg80211_acs_dfs_mode() - Wrapper to set ACS DFS mode
7043 * @wiphy: wiphy structure pointer
7044 * @wdev: Wireless device structure pointer
7045 * @data: Pointer to the data received
7046 * @data_len: Length of @data
7047 *
7048 * This function parses the incoming NL vendor command data attributes and
7049 * updates the SAP context about channel_hint and DFS mode.
7050 *
7051 * Return: 0 on success; errno on failure
7052 */
7053static int wlan_hdd_cfg80211_acs_dfs_mode(struct wiphy *wiphy,
7054 struct wireless_dev *wdev,
7055 const void *data, int data_len)
7056{
7057 int ret;
7058
7059 cds_ssr_protect(__func__);
7060 ret = __wlan_hdd_cfg80211_acs_dfs_mode(wiphy, wdev, data, data_len);
7061 cds_ssr_unprotect(__func__);
7062
7063 return ret;
7064}
7065
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307066/**
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307067 * wlan_hdd_get_sta_roam_dfs_mode() - get sta roam dfs mode policy
7068 * @mode : cfg80211 dfs mode
7069 *
7070 * Return: return csr sta roam dfs mode else return NONE
7071 */
7072static enum sta_roam_policy_dfs_mode wlan_hdd_get_sta_roam_dfs_mode(
7073 enum dfs_mode mode)
7074{
7075 switch (mode) {
7076 case DFS_MODE_ENABLE:
7077 return CSR_STA_ROAM_POLICY_DFS_ENABLED;
7078 break;
7079 case DFS_MODE_DISABLE:
7080 return CSR_STA_ROAM_POLICY_DFS_DISABLED;
7081 break;
7082 case DFS_MODE_DEPRIORITIZE:
7083 return CSR_STA_ROAM_POLICY_DFS_DEPRIORITIZE;
7084 break;
7085 default:
7086 hdd_err("STA Roam policy dfs mode is NONE");
7087 return CSR_STA_ROAM_POLICY_NONE;
7088 }
7089}
7090
7091static const struct nla_policy
7092wlan_hdd_set_sta_roam_config_policy[
7093QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = {
7094 [QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE] = {.type = NLA_U8 },
7095 [QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL] = {.type = NLA_U8 },
7096};
7097
7098/**
7099 * __wlan_hdd_cfg80211_sta_roam_policy() - Set params to restrict scan channels
7100 * for station connection or roaming.
7101 * @wiphy: Pointer to wireless phy
7102 * @wdev: Pointer to wireless device
7103 * @data: Pointer to data
7104 * @data_len: Length of @data
7105 *
7106 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7107 * channels needs to be skipped in scanning or not.
7108 * If dfs_mode is disabled, driver will not scan DFS channels.
7109 * If skip_unsafe_channels is set, driver will skip unsafe channels
7110 * in Scanning.
7111 *
7112 * Return: 0 on success, negative errno on failure
7113 */
7114static int
7115__wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7116 struct wireless_dev *wdev,
7117 const void *data, int data_len)
7118{
7119 struct net_device *dev = wdev->netdev;
7120 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7121 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7122 struct nlattr *tb[
7123 QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1];
7124 int ret;
7125 enum sta_roam_policy_dfs_mode sta_roam_dfs_mode;
7126 enum dfs_mode mode = DFS_MODE_NONE;
7127 bool skip_unsafe_channels = false;
7128 QDF_STATUS status;
7129
7130 ENTER_DEV(dev);
7131
7132 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7133 hdd_err("Command not allowed in FTM mode");
7134 return -EINVAL;
7135 }
7136
7137 ret = wlan_hdd_validate_context(hdd_ctx);
7138 if (0 != ret)
7139 return ret;
7140 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX,
7141 data, data_len,
7142 wlan_hdd_set_sta_roam_config_policy)) {
7143 hdd_err("invalid attr");
7144 return -EINVAL;
7145 }
7146 if (tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE])
7147 mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_STA_DFS_MODE]);
7148 if (!IS_DFS_MODE_VALID(mode)) {
7149 hdd_err("attr sta roam dfs mode policy is not valid");
7150 return -EINVAL;
7151 }
7152
7153 sta_roam_dfs_mode = wlan_hdd_get_sta_roam_dfs_mode(mode);
7154
7155 if (tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL])
7156 skip_unsafe_channels = nla_get_u8(
7157 tb[QCA_WLAN_VENDOR_ATTR_STA_SKIP_UNSAFE_CHANNEL]);
7158
7159 status = sme_update_sta_roam_policy(hdd_ctx->hHal, sta_roam_dfs_mode,
7160 skip_unsafe_channels, adapter->sessionId);
7161
7162 if (!QDF_IS_STATUS_SUCCESS(status)) {
7163 hdd_err("sme_update_sta_roam_policy (err=%d)", status);
7164 return -EINVAL;
7165 }
7166 return 0;
7167}
7168
7169/**
7170 * wlan_hdd_cfg80211_sta_roam_policy() - Wrapper to restrict scan channels,
7171 * connection and roaming for station.
7172 * @wiphy: wiphy structure pointer
7173 * @wdev: Wireless device structure pointer
7174 * @data: Pointer to the data received
7175 * @data_len: Length of @data
7176 *
7177 * __wlan_hdd_cfg80211_sta_roam_policy will decide if DFS channels or unsafe
7178 * channels needs to be skipped in scanning or not.
7179 * If dfs_mode is disabled, driver will not scan DFS channels.
7180 * If skip_unsafe_channels is set, driver will skip unsafe channels
7181 * in Scanning.
7182 * Return: 0 on success; errno on failure
7183 */
7184static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy,
7185 struct wireless_dev *wdev,
7186 const void *data, int data_len)
7187{
7188 int ret;
7189
7190 cds_ssr_protect(__func__);
7191 ret = __wlan_hdd_cfg80211_sta_roam_policy(wiphy, wdev, data, data_len);
7192 cds_ssr_unprotect(__func__);
7193
7194 return ret;
7195}
7196
Agrawal Ashish467dde42016-09-08 18:44:22 +05307197#ifdef FEATURE_WLAN_CH_AVOID
7198/**
7199 * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7200 * is on unsafe channel.
7201 * @wiphy: wiphy structure pointer
7202 * @wdev: Wireless device structure pointer
7203 * @data: Pointer to the data received
7204 * @data_len: Length of @data
7205 *
7206 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7207 * on any of unsafe channels.
7208 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7209 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7210 *
7211 * Return: 0 on success; errno on failure
7212 */
7213static int
7214__wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7215 struct wireless_dev *wdev,
7216 const void *data, int data_len)
7217{
7218 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7219 int ret;
7220 uint16_t unsafe_channel_count;
7221 int unsafe_channel_index;
7222 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
7223
7224 ENTER_DEV(wdev->netdev);
7225
7226 if (!qdf_ctx) {
7227 cds_err("qdf_ctx is NULL");
7228 return -EINVAL;
7229 }
7230
7231 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7232 hdd_err("Command not allowed in FTM mode");
7233 return -EINVAL;
7234 }
7235
7236 ret = wlan_hdd_validate_context(hdd_ctx);
7237 if (0 != ret)
7238 return ret;
7239 pld_get_wlan_unsafe_channel(qdf_ctx->dev, hdd_ctx->unsafe_channel_list,
7240 &(hdd_ctx->unsafe_channel_count),
7241 sizeof(hdd_ctx->unsafe_channel_list));
7242
7243 unsafe_channel_count = QDF_MIN((uint16_t)hdd_ctx->unsafe_channel_count,
7244 (uint16_t)NUM_CHANNELS);
7245 for (unsafe_channel_index = 0;
7246 unsafe_channel_index < unsafe_channel_count;
7247 unsafe_channel_index++) {
7248 hdd_info("Channel %d is not safe",
7249 hdd_ctx->unsafe_channel_list[unsafe_channel_index]);
7250 }
7251 hdd_unsafe_channel_restart_sap(hdd_ctx);
7252 return 0;
7253}
7254
7255/**
7256 * wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP
7257 * is on unsafe channel.
7258 * @wiphy: wiphy structure pointer
7259 * @wdev: Wireless device structure pointer
7260 * @data: Pointer to the data received
7261 * @data_len: Length of @data
7262 *
7263 * wlan_hdd_cfg80211_avoid_freq do restart the sap if sap is already
7264 * on any of unsafe channels.
7265 * If sap is on any of unsafe channel, hdd_unsafe_channel_restart_sap
7266 * will send WLAN_SVC_LTE_COEX_IND indication to userspace to restart.
7267 *
7268 * Return: 0 on success; errno on failure
7269 */
7270static int wlan_hdd_cfg80211_avoid_freq(struct wiphy *wiphy,
7271 struct wireless_dev *wdev,
7272 const void *data, int data_len)
7273{
7274 int ret;
7275
7276 cds_ssr_protect(__func__);
7277 ret = __wlan_hdd_cfg80211_avoid_freq(wiphy, wdev, data, data_len);
7278 cds_ssr_unprotect(__func__);
7279
7280 return ret;
7281}
7282
7283#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05307284/**
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307285 * __wlan_hdd_cfg80211_sap_configuration_set() - ask driver to restart SAP if
7286 * SAP is on unsafe channel.
7287 * @wiphy: wiphy structure pointer
7288 * @wdev: Wireless device structure pointer
7289 * @data: Pointer to the data received
7290 * @data_len: Length of @data
7291 *
7292 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7293 * driver.
7294 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7295 * will initiate restart of sap.
7296 *
7297 * Return: 0 on success; errno on failure
7298 */
7299static int
7300__wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7301 struct wireless_dev *wdev,
7302 const void *data, int data_len)
7303{
7304 struct net_device *ndev = wdev->netdev;
7305 hdd_adapter_t *hostapd_adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
7306 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7307 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX + 1];
7308 uint8_t config_channel = 0;
7309 hdd_ap_ctx_t *ap_ctx;
7310 int ret;
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307311 QDF_STATUS status;
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307312
7313 ENTER();
7314
7315 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07007316 hdd_err("Command not allowed in FTM mode");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307317 return -EINVAL;
7318 }
7319
7320 ret = wlan_hdd_validate_context(hdd_ctx);
7321 if (0 != ret)
7322 return -EINVAL;
7323
7324 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX,
7325 data, data_len,
7326 wlan_hdd_sap_config_policy)) {
Jeff Johnson77848112016-06-29 14:52:06 -07007327 hdd_err("invalid attr");
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307328 return -EINVAL;
7329 }
7330
7331 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]) {
7332 if (!test_bit(SOFTAP_BSS_STARTED,
7333 &hostapd_adapter->event_flags)) {
7334 hdd_err("SAP is not started yet. Restart sap will be invalid");
7335 return -EINVAL;
7336 }
7337
7338 config_channel =
7339 nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL]);
7340
7341 if (!((IS_24G_CH(config_channel)) ||
7342 (IS_5G_CH(config_channel)))) {
7343 hdd_err("Channel %d is not valid to restart SAP",
7344 config_channel);
7345 return -ENOTSUPP;
7346 }
7347
7348 ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
7349 ap_ctx->sapConfig.channel = config_channel;
7350 ap_ctx->sapConfig.ch_params.ch_width =
7351 ap_ctx->sapConfig.ch_width_orig;
7352
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -07007353 cds_set_channel_params(ap_ctx->sapConfig.channel,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307354 ap_ctx->sapConfig.sec_ch,
7355 &ap_ctx->sapConfig.ch_params);
7356
7357 cds_restart_sap(hostapd_adapter);
7358 }
7359
Manishekar Chandrasekaran1db3abe2016-06-24 03:27:07 +05307360 if (tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]) {
7361 uint32_t freq_len, i;
7362 uint32_t *freq;
7363 uint8_t chans[QDF_MAX_NUM_CHAN];
7364
7365 hdd_debug("setting mandatory freq/chan list");
7366
7367 freq_len = nla_len(
7368 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST])/
7369 sizeof(uint32_t);
7370
7371 if (freq_len > QDF_MAX_NUM_CHAN) {
7372 hdd_err("insufficient space to hold channels");
7373 return -ENOMEM;
7374 }
7375
7376 freq = nla_data(
7377 tb[QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST]);
7378
7379 hdd_debug("freq_len=%d", freq_len);
7380
7381 for (i = 0; i < freq_len; i++) {
7382 chans[i] = ieee80211_frequency_to_channel(freq[i]);
7383 hdd_debug("freq[%d]=%d", i, freq[i]);
7384 }
7385
7386 status = cds_set_sap_mandatory_channels(chans, freq_len);
7387 if (QDF_IS_STATUS_ERROR(status))
7388 return -EINVAL;
7389 }
7390
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05307391 return 0;
7392}
7393
7394/**
7395 * wlan_hdd_cfg80211_sap_configuration_set() - sap configuration vendor command
7396 * @wiphy: wiphy structure pointer
7397 * @wdev: Wireless device structure pointer
7398 * @data: Pointer to the data received
7399 * @data_len: Length of @data
7400 *
7401 * __wlan_hdd_cfg80211_sap_configuration_set function set SAP params to
7402 * driver.
7403 * QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHAN will set sap config channel and
7404 * will initiate restart of sap.
7405 *
7406 * Return: 0 on success; errno on failure
7407 */
7408static int wlan_hdd_cfg80211_sap_configuration_set(struct wiphy *wiphy,
7409 struct wireless_dev *wdev,
7410 const void *data, int data_len)
7411{
7412 int ret;
7413
7414 cds_ssr_protect(__func__);
7415 ret = __wlan_hdd_cfg80211_sap_configuration_set(wiphy,
7416 wdev, data, data_len);
7417 cds_ssr_unprotect(__func__);
7418
7419 return ret;
7420}
7421
Arun Khandavalli2476ef52016-04-26 20:19:43 +05307422#undef BPF_INVALID
7423#undef BPF_SET_RESET
7424#undef BPF_VERSION
7425#undef BPF_ID
7426#undef BPF_PACKET_SIZE
7427#undef BPF_CURRENT_OFFSET
7428#undef BPF_PROGRAM
7429#undef BPF_MAX
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307430
7431/**
7432 * define short names for the global vendor params
7433 * used by wlan_hdd_cfg80211_wakelock_stats_rsp_callback()
7434 */
7435#define PARAM_TOTAL_CMD_EVENT_WAKE \
7436 QCA_WLAN_VENDOR_ATTR_TOTAL_CMD_EVENT_WAKE
7437#define PARAM_CMD_EVENT_WAKE_CNT_PTR \
7438 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_PTR
7439#define PARAM_CMD_EVENT_WAKE_CNT_SZ \
7440 QCA_WLAN_VENDOR_ATTR_CMD_EVENT_WAKE_CNT_SZ
7441#define PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE \
7442 QCA_WLAN_VENDOR_ATTR_TOTAL_DRIVER_FW_LOCAL_WAKE
7443#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR \
7444 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_PTR
7445#define PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ \
7446 QCA_WLAN_VENDOR_ATTR_DRIVER_FW_LOCAL_WAKE_CNT_SZ
7447#define PARAM_TOTAL_RX_DATA_WAKE \
7448 QCA_WLAN_VENDOR_ATTR_TOTAL_RX_DATA_WAKE
7449#define PARAM_RX_UNICAST_CNT \
7450 QCA_WLAN_VENDOR_ATTR_RX_UNICAST_CNT
7451#define PARAM_RX_MULTICAST_CNT \
7452 QCA_WLAN_VENDOR_ATTR_RX_MULTICAST_CNT
7453#define PARAM_RX_BROADCAST_CNT \
7454 QCA_WLAN_VENDOR_ATTR_RX_BROADCAST_CNT
7455#define PARAM_ICMP_PKT \
7456 QCA_WLAN_VENDOR_ATTR_ICMP_PKT
7457#define PARAM_ICMP6_PKT \
7458 QCA_WLAN_VENDOR_ATTR_ICMP6_PKT
7459#define PARAM_ICMP6_RA \
7460 QCA_WLAN_VENDOR_ATTR_ICMP6_RA
7461#define PARAM_ICMP6_NA \
7462 QCA_WLAN_VENDOR_ATTR_ICMP6_NA
7463#define PARAM_ICMP6_NS \
7464 QCA_WLAN_VENDOR_ATTR_ICMP6_NS
7465#define PARAM_ICMP4_RX_MULTICAST_CNT \
7466 QCA_WLAN_VENDOR_ATTR_ICMP4_RX_MULTICAST_CNT
7467#define PARAM_ICMP6_RX_MULTICAST_CNT \
7468 QCA_WLAN_VENDOR_ATTR_ICMP6_RX_MULTICAST_CNT
7469#define PARAM_OTHER_RX_MULTICAST_CNT \
7470 QCA_WLAN_VENDOR_ATTR_OTHER_RX_MULTICAST_CNT
7471
7472
7473/**
7474 * hdd_send_wakelock_stats() - API to send wakelock stats
7475 * @ctx: context to be passed to callback
7476 * @data: data passed to callback
7477 *
7478 * This function is used to send wake lock stats to HAL layer
7479 *
7480 * Return: 0 on success, error number otherwise.
7481 */
7482static uint32_t hdd_send_wakelock_stats(hdd_context_t *hdd_ctx,
7483 const struct sir_wake_lock_stats *data)
7484{
7485 struct sk_buff *skb;
7486 uint32_t nl_buf_len;
7487 uint32_t total_rx_data_wake, rx_multicast_cnt;
7488 uint32_t ipv6_rx_multicast_addr_cnt;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307489 uint32_t icmpv6_cnt;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307490
7491 ENTER();
7492
7493 nl_buf_len = NLMSG_HDRLEN;
7494 nl_buf_len +=
7495 QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX *
7496 (NLMSG_HDRLEN + sizeof(uint32_t));
7497
7498 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7499
7500 if (!skb) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007501 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307502 return -ENOMEM;
7503 }
7504
Jeff Johnson64943bd2016-08-23 13:14:06 -07007505 hdd_info("wow_ucast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307506 data->wow_ucast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007507 hdd_info("wow_bcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307508 data->wow_bcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007509 hdd_info("wow_ipv4_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307510 data->wow_ipv4_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007511 hdd_info("wow_ipv6_mcast_wake_up_count %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307512 data->wow_ipv6_mcast_wake_up_count);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007513 hdd_info("wow_ipv6_mcast_ra_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307514 data->wow_ipv6_mcast_ra_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007515 hdd_info("wow_ipv6_mcast_ns_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307516 data->wow_ipv6_mcast_ns_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007517 hdd_info("wow_ipv6_mcast_na_stats %d",
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307518 data->wow_ipv6_mcast_na_stats);
Jeff Johnson64943bd2016-08-23 13:14:06 -07007519 hdd_info("wow_icmpv4_count %d", data->wow_icmpv4_count);
7520 hdd_info("wow_icmpv6_count %d",
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307521 data->wow_icmpv6_count);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307522
7523 ipv6_rx_multicast_addr_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307524 data->wow_ipv6_mcast_wake_up_count;
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307525
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307526 icmpv6_cnt =
Himanshu Agarwal4574e282016-08-10 15:22:45 +05307527 data->wow_icmpv6_count;
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307528
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307529 rx_multicast_cnt =
7530 data->wow_ipv4_mcast_wake_up_count +
7531 ipv6_rx_multicast_addr_cnt;
7532
7533 total_rx_data_wake =
7534 data->wow_ucast_wake_up_count +
7535 data->wow_bcast_wake_up_count +
7536 rx_multicast_cnt;
7537
7538 if (nla_put_u32(skb, PARAM_TOTAL_CMD_EVENT_WAKE, 0) ||
7539 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_PTR, 0) ||
7540 nla_put_u32(skb, PARAM_CMD_EVENT_WAKE_CNT_SZ, 0) ||
7541 nla_put_u32(skb, PARAM_TOTAL_DRIVER_FW_LOCAL_WAKE, 0) ||
7542 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_PTR, 0) ||
7543 nla_put_u32(skb, PARAM_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 0) ||
7544 nla_put_u32(skb, PARAM_TOTAL_RX_DATA_WAKE,
7545 total_rx_data_wake) ||
7546 nla_put_u32(skb, PARAM_RX_UNICAST_CNT,
7547 data->wow_ucast_wake_up_count) ||
7548 nla_put_u32(skb, PARAM_RX_MULTICAST_CNT,
7549 rx_multicast_cnt) ||
7550 nla_put_u32(skb, PARAM_RX_BROADCAST_CNT,
7551 data->wow_bcast_wake_up_count) ||
Sreelakshmi Konamkie1cd51f2016-08-19 16:58:24 +05307552 nla_put_u32(skb, PARAM_ICMP_PKT,
7553 data->wow_icmpv4_count) ||
7554 nla_put_u32(skb, PARAM_ICMP6_PKT,
7555 icmpv6_cnt) ||
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307556 nla_put_u32(skb, PARAM_ICMP6_RA,
7557 data->wow_ipv6_mcast_ra_stats) ||
7558 nla_put_u32(skb, PARAM_ICMP6_NA,
7559 data->wow_ipv6_mcast_na_stats) ||
7560 nla_put_u32(skb, PARAM_ICMP6_NS,
7561 data->wow_ipv6_mcast_ns_stats) ||
7562 nla_put_u32(skb, PARAM_ICMP4_RX_MULTICAST_CNT,
7563 data->wow_ipv4_mcast_wake_up_count) ||
7564 nla_put_u32(skb, PARAM_ICMP6_RX_MULTICAST_CNT,
7565 ipv6_rx_multicast_addr_cnt) ||
7566 nla_put_u32(skb, PARAM_OTHER_RX_MULTICAST_CNT, 0)) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007567 hdd_err("nla put fail");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307568 goto nla_put_failure;
7569 }
7570
7571 cfg80211_vendor_cmd_reply(skb);
7572
7573 EXIT();
7574 return 0;
7575
7576nla_put_failure:
7577 kfree_skb(skb);
7578 return -EINVAL;
7579}
7580
7581/**
7582 * __wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7583 * @wiphy: wiphy pointer
7584 * @wdev: pointer to struct wireless_dev
7585 * @data: pointer to incoming NL vendor data
7586 * @data_len: length of @data
7587 *
7588 * This function parses the incoming NL vendor command data attributes and
7589 * invokes the SME Api and blocks on a completion variable.
7590 * WMA copies required data and invokes callback
7591 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7592 *
7593 * Return: 0 on success; error number otherwise.
7594 */
7595static int __wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7596 struct wireless_dev *wdev,
7597 const void *data,
7598 int data_len)
7599{
7600 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7601 int status, ret;
7602 struct sir_wake_lock_stats wake_lock_stats;
7603 QDF_STATUS qdf_status;
7604
7605 ENTER();
7606
7607 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007608 hdd_err("Command not allowed in FTM mode");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307609 return -EINVAL;
7610 }
7611
7612 status = wlan_hdd_validate_context(hdd_ctx);
7613 if (0 != status)
7614 return -EINVAL;
7615
7616 qdf_status = wma_get_wakelock_stats(&wake_lock_stats);
7617 if (qdf_status != QDF_STATUS_SUCCESS) {
Jeff Johnson64943bd2016-08-23 13:14:06 -07007618 hdd_err("failed to get wakelock stats(err=%d)", qdf_status);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307619 return -EINVAL;
7620 }
7621
7622 ret = hdd_send_wakelock_stats(hdd_ctx,
7623 &wake_lock_stats);
7624 if (ret)
Jeff Johnson64943bd2016-08-23 13:14:06 -07007625 hdd_err("Failed to post wake lock stats");
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307626
7627 EXIT();
7628 return ret;
7629}
7630
7631/**
7632 * wlan_hdd_cfg80211_get_wakelock_stats() - gets wake lock stats
7633 * @wiphy: wiphy pointer
7634 * @wdev: pointer to struct wireless_dev
7635 * @data: pointer to incoming NL vendor data
7636 * @data_len: length of @data
7637 *
7638 * This function parses the incoming NL vendor command data attributes and
7639 * invokes the SME Api and blocks on a completion variable.
7640 * WMA copies required data and invokes callback
7641 * wlan_hdd_cfg80211_wakelock_stats_rsp_callback to send wake lock stats.
7642 *
7643 * Return: 0 on success; error number otherwise.
7644 */
7645static int wlan_hdd_cfg80211_get_wakelock_stats(struct wiphy *wiphy,
7646 struct wireless_dev *wdev,
7647 const void *data, int data_len)
7648{
7649 int ret;
7650
7651 cds_ssr_protect(__func__);
7652 ret = __wlan_hdd_cfg80211_get_wakelock_stats(wiphy, wdev, data,
7653 data_len);
Jeff Johnsonf3a64e62016-10-12 17:17:34 -07007654 cds_ssr_unprotect(__func__);
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05307655
7656 return ret;
7657}
7658
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307659/**
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05307660 * __wlan_hdd_cfg80211_get_bus_size() - Get WMI Bus size
7661 * @wiphy: wiphy structure pointer
7662 * @wdev: Wireless device structure pointer
7663 * @data: Pointer to the data received
7664 * @data_len: Length of @data
7665 *
7666 * This function reads wmi max bus size and fill in the skb with
7667 * NL attributes and send up the NL event.
7668 * Return: 0 on success; errno on failure
7669 */
7670static int
7671__wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7672 struct wireless_dev *wdev,
7673 const void *data, int data_len)
7674{
7675 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7676 int ret_val;
7677 struct sk_buff *skb;
7678 uint32_t nl_buf_len;
7679
7680 ENTER();
7681
7682 ret_val = wlan_hdd_validate_context(hdd_ctx);
7683 if (ret_val)
7684 return ret_val;
7685
7686 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7687 hdd_err("Command not allowed in FTM mode");
7688 return -EINVAL;
7689 }
7690
7691 hdd_info("WMI Max Bus size: %d", hdd_ctx->wmi_max_len);
7692
7693 nl_buf_len = NLMSG_HDRLEN;
7694 nl_buf_len += (sizeof(hdd_ctx->wmi_max_len) + NLA_HDRLEN);
7695
7696 skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
7697 if (!skb) {
7698 hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
7699 return -ENOMEM;
7700 }
7701
7702 if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE,
7703 hdd_ctx->wmi_max_len)) {
7704 hdd_err("nla put failure");
7705 goto nla_put_failure;
7706 }
7707
7708 cfg80211_vendor_cmd_reply(skb);
7709
7710 EXIT();
7711
7712 return 0;
7713
7714nla_put_failure:
7715 kfree_skb(skb);
7716 return -EINVAL;
7717}
7718
7719/**
7720 * wlan_hdd_cfg80211_get_bus_size() - SSR Wrapper to Get Bus size
7721 * @wiphy: wiphy structure pointer
7722 * @wdev: Wireless device structure pointer
7723 * @data: Pointer to the data received
7724 * @data_len: Length of @data
7725 *
7726 * Return: 0 on success; errno on failure
7727 */
7728static int wlan_hdd_cfg80211_get_bus_size(struct wiphy *wiphy,
7729 struct wireless_dev *wdev,
7730 const void *data, int data_len)
7731{
7732 int ret;
7733
7734 cds_ssr_protect(__func__);
7735 ret = __wlan_hdd_cfg80211_get_bus_size(wiphy, wdev, data, data_len);
7736 cds_ssr_unprotect(__func__);
7737
7738 return ret;
7739}
7740
7741/**
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05307742 *__wlan_hdd_cfg80211_setband() - set band
7743 * @wiphy: Pointer to wireless phy
7744 * @wdev: Pointer to wireless device
7745 * @data: Pointer to data
7746 * @data_len: Length of @data
7747 *
7748 * Return: 0 on success, negative errno on failure
7749 */
7750static int __wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7751 struct wireless_dev *wdev,
7752 const void *data, int data_len)
7753{
7754 struct net_device *dev = wdev->netdev;
7755 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7756 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7757 int ret;
7758 static const struct nla_policy policy[QCA_WLAN_VENDOR_ATTR_MAX + 1]
7759 = {[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE] = { .type = NLA_U32 } };
7760
7761 ENTER();
7762
7763 ret = wlan_hdd_validate_context(hdd_ctx);
7764 if (ret)
7765 return ret;
7766
7767 if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len, policy)) {
7768 hdd_err(FL("Invalid ATTR"));
7769 return -EINVAL;
7770 }
7771
7772 if (!tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]) {
7773 hdd_err(FL("attr SETBAND_VALUE failed"));
7774 return -EINVAL;
7775 }
7776
7777 ret = hdd_set_band(dev,
7778 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE]));
7779
7780 EXIT();
7781 return ret;
7782}
7783
7784/**
7785 * wlan_hdd_cfg80211_setband() - Wrapper to setband
7786 * @wiphy: wiphy structure pointer
7787 * @wdev: Wireless device structure pointer
7788 * @data: Pointer to the data received
7789 * @data_len: Length of @data
7790 *
7791 * Return: 0 on success; errno on failure
7792 */
7793static int wlan_hdd_cfg80211_setband(struct wiphy *wiphy,
7794 struct wireless_dev *wdev,
7795 const void *data, int data_len)
7796{
7797 int ret;
7798
7799 cds_ssr_protect(__func__);
7800 ret = __wlan_hdd_cfg80211_setband(wiphy, wdev, data, data_len);
7801 cds_ssr_unprotect(__func__);
7802
7803 return ret;
7804}
7805
Mukul Sharma69c44cd2016-09-12 18:33:57 +05307806static const struct
7807nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
7808 [QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = {.type = NLA_U32},
7809 [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {.type = NLA_BINARY,
7810 .len = QDF_MAC_ADDR_SIZE},
7811};
7812
7813/**
7814 * __wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7815 * @wiphy: Pointer to wireless phy
7816 * @wdev: Pointer to wireless device
7817 * @data: Pointer to data
7818 * @data_len: Length of @data
7819 *
7820 * This function is used to enable/disable roaming using vendor commands
7821 *
7822 * Return: 0 on success, negative errno on failure
7823 */
7824static int __wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7825 struct wireless_dev *wdev,
7826 const void *data, int data_len)
7827{
7828 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
7829 struct net_device *dev = wdev->netdev;
7830 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
7831 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX + 1];
7832 uint32_t is_fast_roam_enabled;
7833 int ret;
7834
7835 ENTER_DEV(dev);
7836
7837 ret = wlan_hdd_validate_context(hdd_ctx);
7838 if (0 != ret)
7839 return ret;
7840
7841 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
7842 hdd_err("Command not allowed in FTM mode");
7843 return -EINVAL;
7844 }
7845
7846 ret = nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MAX, data, data_len,
7847 qca_wlan_vendor_attr);
7848 if (ret) {
7849 hdd_err("Invalid ATTR");
7850 return -EINVAL;
7851 }
7852
7853 /* Parse and fetch Enable flag */
7854 if (!tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]) {
7855 hdd_err("attr enable failed");
7856 return -EINVAL;
7857 }
7858
7859 is_fast_roam_enabled = nla_get_u32(
7860 tb[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY]);
7861 hdd_notice("isFastRoamEnabled %d", is_fast_roam_enabled);
7862
7863 /* Update roaming */
7864 ret = sme_config_fast_roaming(hdd_ctx->hHal, adapter->sessionId,
7865 is_fast_roam_enabled);
7866 if (ret)
7867 hdd_err("sme_config_fast_roaming failed");
7868 EXIT();
7869 return ret;
7870}
7871
7872/**
7873 * wlan_hdd_cfg80211_set_fast_roaming() - enable/disable roaming
7874 * @wiphy: Pointer to wireless phy
7875 * @wdev: Pointer to wireless device
7876 * @data: Pointer to data
7877 * @data_len: Length of @data
7878 *
7879 * Wrapper function of __wlan_hdd_cfg80211_set_fast_roaming()
7880 *
7881 * Return: 0 on success, negative errno on failure
7882 */
7883static int wlan_hdd_cfg80211_set_fast_roaming(struct wiphy *wiphy,
7884 struct wireless_dev *wdev,
7885 const void *data, int data_len)
7886{
7887 int ret;
7888
7889 cds_ssr_protect(__func__);
7890 ret = __wlan_hdd_cfg80211_set_fast_roaming(wiphy, wdev, data, data_len);
7891 cds_ssr_unprotect(__func__);
7892
7893 return ret;
7894}
7895
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007896const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
7897 {
7898 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7899 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY,
7900 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
Srinivas Dasari947abd72016-09-02 12:11:33 +05307901 WIPHY_VENDOR_CMD_NEED_NETDEV,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08007902 .doit = is_driver_dfs_capable
7903 },
7904
7905#ifdef WLAN_FEATURE_NAN
7906 {
7907 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7908 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NAN,
7909 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7910 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7911 .doit = wlan_hdd_cfg80211_nan_request
7912 },
7913#endif
7914
7915#ifdef WLAN_FEATURE_STATS_EXT
7916 {
7917 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7918 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STATS_EXT,
7919 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7920 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7921 .doit = wlan_hdd_cfg80211_stats_ext_request
7922 },
7923#endif
7924#ifdef FEATURE_WLAN_EXTSCAN
7925 {
7926 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7927 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_START,
7928 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7929 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7930 .doit = wlan_hdd_cfg80211_extscan_start
7931 },
7932 {
7933 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7934 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_STOP,
7935 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7936 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7937 .doit = wlan_hdd_cfg80211_extscan_stop
7938 },
7939 {
7940 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7941 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_VALID_CHANNELS,
7942 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
7943 .doit = wlan_hdd_cfg80211_extscan_get_valid_channels
7944 },
7945 {
7946 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7947 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CAPABILITIES,
7948 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7949 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7950 .doit = wlan_hdd_cfg80211_extscan_get_capabilities
7951 },
7952 {
7953 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7954 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_GET_CACHED_RESULTS,
7955 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7956 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7957 .doit = wlan_hdd_cfg80211_extscan_get_cached_results
7958 },
7959 {
7960 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7961 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_BSSID_HOTLIST,
7962 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7963 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7964 .doit = wlan_hdd_cfg80211_extscan_set_bssid_hotlist
7965 },
7966 {
7967 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7968 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_BSSID_HOTLIST,
7969 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7970 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
7971 .doit = wlan_hdd_cfg80211_extscan_reset_bssid_hotlist
7972 },
7973 {
7974 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7975 .info.subcmd =
7976 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SIGNIFICANT_CHANGE,
7977 .flags =
7978 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
7979 WIPHY_VENDOR_CMD_NEED_RUNNING,
7980 .doit = wlan_hdd_cfg80211_extscan_set_significant_change
7981 },
7982 {
7983 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7984 .info.subcmd =
7985 QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SIGNIFICANT_CHANGE,
7986 .flags =
7987 WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV |
7988 WIPHY_VENDOR_CMD_NEED_RUNNING,
7989 .doit = wlan_hdd_cfg80211_extscan_reset_significant_change
7990 },
7991 {
7992 .info.vendor_id = QCA_NL80211_VENDOR_ID,
7993 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_LIST,
7994 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
7995 WIPHY_VENDOR_CMD_NEED_NETDEV |
7996 WIPHY_VENDOR_CMD_NEED_RUNNING,
7997 .doit = wlan_hdd_cfg80211_set_epno_list
7998 },
7999#endif /* FEATURE_WLAN_EXTSCAN */
8000
8001#ifdef WLAN_FEATURE_LINK_LAYER_STATS
8002 {
8003 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8004 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR,
8005 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8006 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8007 .doit = wlan_hdd_cfg80211_ll_stats_clear
8008 },
8009
8010 {
8011 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8012 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET,
8013 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8014 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8015 .doit = wlan_hdd_cfg80211_ll_stats_set
8016 },
8017
8018 {
8019 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8020 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET,
8021 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8022 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8023 .doit = wlan_hdd_cfg80211_ll_stats_get
8024 },
8025#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
8026#ifdef FEATURE_WLAN_TDLS
8027 {
8028 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8029 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE,
8030 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8031 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8032 .doit = wlan_hdd_cfg80211_exttdls_enable
8033 },
8034 {
8035 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8036 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE,
8037 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8038 WIPHY_VENDOR_CMD_NEED_NETDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
8039 .doit = wlan_hdd_cfg80211_exttdls_disable
8040 },
8041 {
8042 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8043 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS,
8044 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8045 .doit = wlan_hdd_cfg80211_exttdls_get_status
8046 },
8047#endif
8048 {
8049 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8050 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES,
8051 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8052 .doit = wlan_hdd_cfg80211_get_supported_features
8053 },
8054 {
8055 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8056 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI,
8057 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
8058 .doit = wlan_hdd_cfg80211_set_scanning_mac_oui
8059 },
8060 {
8061 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8062 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX,
8063 .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
Chandrasekaran, Manishekar6e9aa1b2015-12-02 18:04:00 +05308064 .doit = wlan_hdd_cfg80211_get_concurrency_matrix
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008065 },
8066 {
8067 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8068 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG,
8069 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8070 WIPHY_VENDOR_CMD_NEED_NETDEV,
8071 .doit = wlan_hdd_cfg80211_disable_dfs_chan_scan
8072 },
Manikandan Mohan80dea792016-04-28 16:36:48 -07008073 {
8074 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8075 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WISA,
8076 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8077 WIPHY_VENDOR_CMD_NEED_NETDEV,
8078 .doit = wlan_hdd_cfg80211_handle_wisa_cmd
8079 },
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008080 {
8081 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Anurag Chouhan96919482016-07-13 16:36:57 +05308082 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_STATION,
8083 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8084 WIPHY_VENDOR_CMD_NEED_NETDEV |
8085 WIPHY_VENDOR_CMD_NEED_RUNNING,
8086 .doit = hdd_cfg80211_get_station_cmd
8087 },
8088 {
8089 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008090 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DO_ACS,
8091 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8092 WIPHY_VENDOR_CMD_NEED_NETDEV |
8093 WIPHY_VENDOR_CMD_NEED_RUNNING,
8094 .doit = wlan_hdd_cfg80211_do_acs
8095 },
8096
8097 {
8098 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8099 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES,
8100 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8101 WIPHY_VENDOR_CMD_NEED_NETDEV,
8102 .doit = wlan_hdd_cfg80211_get_features
8103 },
8104#ifdef WLAN_FEATURE_ROAM_OFFLOAD
8105 {
8106 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8107 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY,
8108 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8109 WIPHY_VENDOR_CMD_NEED_NETDEV |
8110 WIPHY_VENDOR_CMD_NEED_RUNNING,
8111 .doit = wlan_hdd_cfg80211_keymgmt_set_key
8112 },
8113#endif
8114#ifdef FEATURE_WLAN_EXTSCAN
8115 {
8116 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8117 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_SET_PASSPOINT_LIST,
8118 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8119 WIPHY_VENDOR_CMD_NEED_NETDEV |
8120 WIPHY_VENDOR_CMD_NEED_RUNNING,
8121 .doit = wlan_hdd_cfg80211_set_passpoint_list
8122 },
8123 {
8124 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8125 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_PNO_RESET_PASSPOINT_LIST,
8126 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8127 WIPHY_VENDOR_CMD_NEED_NETDEV |
8128 WIPHY_VENDOR_CMD_NEED_RUNNING,
8129 .doit = wlan_hdd_cfg80211_reset_passpoint_list
8130 },
8131 {
8132 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8133 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_SET_SSID_HOTLIST,
8134 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8135 WIPHY_VENDOR_CMD_NEED_NETDEV |
8136 WIPHY_VENDOR_CMD_NEED_RUNNING,
8137 .doit = wlan_hdd_cfg80211_extscan_set_ssid_hotlist
8138 },
8139 {
8140 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8141 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_EXTSCAN_RESET_SSID_HOTLIST,
8142 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8143 WIPHY_VENDOR_CMD_NEED_NETDEV |
8144 WIPHY_VENDOR_CMD_NEED_RUNNING,
8145 .doit = wlan_hdd_cfg80211_extscan_reset_ssid_hotlist
8146 },
8147#endif /* FEATURE_WLAN_EXTSCAN */
8148 {
8149 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8150 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO,
8151 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8152 WIPHY_VENDOR_CMD_NEED_NETDEV,
8153 .doit = wlan_hdd_cfg80211_get_wifi_info
8154 },
8155 {
8156 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8157 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION,
8158 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8159 WIPHY_VENDOR_CMD_NEED_NETDEV |
8160 WIPHY_VENDOR_CMD_NEED_RUNNING,
8161 .doit = wlan_hdd_cfg80211_wifi_configuration_set
8162 },
8163 {
8164 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8165 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAM,
8166 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8167 WIPHY_VENDOR_CMD_NEED_NETDEV,
8168 .doit = wlan_hdd_cfg80211_set_ext_roam_params
8169 },
8170 {
8171 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8172 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START,
8173 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8174 WIPHY_VENDOR_CMD_NEED_NETDEV,
8175 .doit = wlan_hdd_cfg80211_wifi_logger_start
8176 },
8177 {
8178 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8179 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA,
8180 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8181 WIPHY_VENDOR_CMD_NEED_NETDEV,
8182 .doit = wlan_hdd_cfg80211_wifi_logger_get_ring_data
8183 },
8184 {
8185 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8186 .info.subcmd =
8187 QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST,
8188 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8189 WIPHY_VENDOR_CMD_NEED_NETDEV |
8190 WIPHY_VENDOR_CMD_NEED_RUNNING,
8191 .doit = wlan_hdd_cfg80211_get_preferred_freq_list
8192 },
8193 {
8194 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8195 .info.subcmd =
8196 QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL,
8197 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8198 WIPHY_VENDOR_CMD_NEED_NETDEV |
8199 WIPHY_VENDOR_CMD_NEED_RUNNING,
8200 .doit = wlan_hdd_cfg80211_set_probable_oper_channel
8201 },
Manikandan Mohan5356c2b2016-04-03 15:51:35 -07008202#ifdef WLAN_FEATURE_TSF
8203 {
8204 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8205 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TSF,
8206 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8207 WIPHY_VENDOR_CMD_NEED_NETDEV |
8208 WIPHY_VENDOR_CMD_NEED_RUNNING,
8209 .doit = wlan_hdd_cfg80211_handle_tsf_cmd
8210 },
8211#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008212#ifdef FEATURE_WLAN_TDLS
8213 {
8214 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8215 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES,
8216 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8217 WIPHY_VENDOR_CMD_NEED_NETDEV |
8218 WIPHY_VENDOR_CMD_NEED_RUNNING,
8219 .doit = wlan_hdd_cfg80211_get_tdls_capabilities
8220 },
8221#endif
8222#ifdef WLAN_FEATURE_OFFLOAD_PACKETS
8223 {
8224 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8225 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
8226 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8227 WIPHY_VENDOR_CMD_NEED_NETDEV |
8228 WIPHY_VENDOR_CMD_NEED_RUNNING,
8229 .doit = wlan_hdd_cfg80211_offloaded_packets
8230 },
8231#endif
8232 {
8233 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8234 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
8235 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8236 WIPHY_VENDOR_CMD_NEED_NETDEV |
8237 WIPHY_VENDOR_CMD_NEED_RUNNING,
8238 .doit = wlan_hdd_cfg80211_monitor_rssi
8239 },
8240 {
8241 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Sravan Kumar Kairamfece87f2016-07-26 14:58:28 +05308242 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
8243 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8244 WIPHY_VENDOR_CMD_NEED_NETDEV |
8245 WIPHY_VENDOR_CMD_NEED_RUNNING,
8246 .doit = wlan_hdd_cfg80211_set_ns_offload
8247 },
8248 {
8249 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008250 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET,
8251 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8252 WIPHY_VENDOR_CMD_NEED_NETDEV |
8253 WIPHY_VENDOR_CMD_NEED_RUNNING,
8254 .doit = wlan_hdd_cfg80211_get_logger_supp_feature
8255 },
8256#ifdef WLAN_FEATURE_MEMDUMP
8257 {
8258 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8259 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP,
8260 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8261 WIPHY_VENDOR_CMD_NEED_NETDEV |
8262 WIPHY_VENDOR_CMD_NEED_RUNNING,
8263 .doit = wlan_hdd_cfg80211_get_fw_mem_dump
8264 },
8265#endif /* WLAN_FEATURE_MEMDUMP */
8266 {
8267 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8268 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN,
8269 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8270 WIPHY_VENDOR_CMD_NEED_NETDEV |
8271 WIPHY_VENDOR_CMD_NEED_RUNNING,
8272 .doit = wlan_hdd_cfg80211_vendor_scan
8273 },
8274
8275 /* OCB commands */
8276 {
8277 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8278 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG,
8279 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8280 WIPHY_VENDOR_CMD_NEED_NETDEV |
8281 WIPHY_VENDOR_CMD_NEED_RUNNING,
8282 .doit = wlan_hdd_cfg80211_ocb_set_config
8283 },
8284 {
8285 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8286 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME,
8287 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8288 WIPHY_VENDOR_CMD_NEED_NETDEV |
8289 WIPHY_VENDOR_CMD_NEED_RUNNING,
8290 .doit = wlan_hdd_cfg80211_ocb_set_utc_time
8291 },
8292 {
8293 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8294 .info.subcmd =
8295 QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT,
8296 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8297 WIPHY_VENDOR_CMD_NEED_NETDEV |
8298 WIPHY_VENDOR_CMD_NEED_RUNNING,
8299 .doit = wlan_hdd_cfg80211_ocb_start_timing_advert
8300 },
8301 {
8302 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8303 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT,
8304 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8305 WIPHY_VENDOR_CMD_NEED_NETDEV |
8306 WIPHY_VENDOR_CMD_NEED_RUNNING,
8307 .doit = wlan_hdd_cfg80211_ocb_stop_timing_advert
8308 },
8309 {
8310 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8311 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER,
8312 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8313 WIPHY_VENDOR_CMD_NEED_NETDEV |
8314 WIPHY_VENDOR_CMD_NEED_RUNNING,
8315 .doit = wlan_hdd_cfg80211_ocb_get_tsf_timer
8316 },
8317 {
8318 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8319 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS,
8320 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8321 WIPHY_VENDOR_CMD_NEED_NETDEV |
8322 WIPHY_VENDOR_CMD_NEED_RUNNING,
8323 .doit = wlan_hdd_cfg80211_dcc_get_stats
8324 },
8325 {
8326 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8327 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS,
8328 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8329 WIPHY_VENDOR_CMD_NEED_NETDEV |
8330 WIPHY_VENDOR_CMD_NEED_RUNNING,
8331 .doit = wlan_hdd_cfg80211_dcc_clear_stats
8332 },
8333 {
8334 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8335 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL,
8336 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8337 WIPHY_VENDOR_CMD_NEED_NETDEV |
8338 WIPHY_VENDOR_CMD_NEED_RUNNING,
8339 .doit = wlan_hdd_cfg80211_dcc_update_ndl
8340 },
Kanchanapally, Vidyullathae3062812015-05-22 17:28:57 +05308341 {
8342 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8343 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES,
8344 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8345 WIPHY_VENDOR_CMD_NEED_NETDEV |
8346 WIPHY_VENDOR_CMD_NEED_RUNNING,
8347 .doit = wlan_hdd_cfg80211_get_link_properties
8348 },
Peng Xu278d0122015-09-24 16:34:17 -07008349 {
Peng Xud2220962016-07-11 17:59:17 -07008350 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu278d0122015-09-24 16:34:17 -07008351 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_OTA_TEST,
8352 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8353 WIPHY_VENDOR_CMD_NEED_NETDEV |
8354 WIPHY_VENDOR_CMD_NEED_RUNNING,
8355 .doit = wlan_hdd_cfg80211_set_ota_test
8356 },
Ravi Joshideb5a8d2015-11-09 19:11:43 -08008357#ifdef FEATURE_LFR_SUBNET_DETECTION
8358 {
8359 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8360 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
8361 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8362 WIPHY_VENDOR_CMD_NEED_NETDEV |
8363 WIPHY_VENDOR_CMD_NEED_RUNNING,
8364 .doit = wlan_hdd_cfg80211_set_gateway_params
8365 },
8366#endif /* FEATURE_LFR_SUBNET_DETECTION */
Peng Xu4d67c8f2015-10-16 16:02:26 -07008367 {
Peng Xud2220962016-07-11 17:59:17 -07008368 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu4d67c8f2015-10-16 16:02:26 -07008369 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE,
8370 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8371 WIPHY_VENDOR_CMD_NEED_NETDEV |
8372 WIPHY_VENDOR_CMD_NEED_RUNNING,
8373 .doit = wlan_hdd_cfg80211_txpower_scale
8374 },
8375 {
8376 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8377 .info.subcmd =
8378 QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE_DECR_DB,
8379 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8380 WIPHY_VENDOR_CMD_NEED_NETDEV |
8381 WIPHY_VENDOR_CMD_NEED_RUNNING,
8382 .doit = wlan_hdd_cfg80211_txpower_scale_decr_db
8383 },
Arun Khandavalli2476ef52016-04-26 20:19:43 +05308384 {
8385 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8386 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
8387 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8388 WIPHY_VENDOR_CMD_NEED_NETDEV |
8389 WIPHY_VENDOR_CMD_NEED_RUNNING,
8390 .doit = wlan_hdd_cfg80211_bpf_offload
8391 },
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308392 {
8393 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish65634612016-08-18 13:24:32 +05308394 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY,
8395 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8396 WIPHY_VENDOR_CMD_NEED_NETDEV |
8397 WIPHY_VENDOR_CMD_NEED_RUNNING,
8398 .doit = wlan_hdd_cfg80211_acs_dfs_mode
8399 },
8400 {
8401 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308402 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_STA_CONNECT_ROAM_POLICY,
8403 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8404 WIPHY_VENDOR_CMD_NEED_NETDEV |
8405 WIPHY_VENDOR_CMD_NEED_RUNNING,
8406 .doit = wlan_hdd_cfg80211_sta_roam_policy
8407 },
Agrawal Ashish467dde42016-09-08 18:44:22 +05308408#ifdef FEATURE_WLAN_CH_AVOID
8409 {
8410 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8411 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY,
8412 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8413 WIPHY_VENDOR_CMD_NEED_NETDEV |
8414 WIPHY_VENDOR_CMD_NEED_RUNNING,
8415 .doit = wlan_hdd_cfg80211_avoid_freq
8416 },
8417#endif
Agrawal Ashish21ba2572016-09-03 16:40:10 +05308418 {
8419 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Agrawal Ashishc9ddbab2016-05-25 12:04:47 +05308420 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG,
8421 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8422 WIPHY_VENDOR_CMD_NEED_NETDEV |
8423 WIPHY_VENDOR_CMD_NEED_RUNNING,
8424 .doit = wlan_hdd_cfg80211_sap_configuration_set
8425 },
Peng Xu8fdaa492016-06-22 10:20:47 -07008426 {
Peng Xu4225c152016-07-14 21:18:14 -07008427 .info.vendor_id = QCA_NL80211_VENDOR_ID,
Peng Xu8fdaa492016-06-22 10:20:47 -07008428 .info.subcmd =
8429 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START,
8430 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8431 WIPHY_VENDOR_CMD_NEED_NETDEV |
8432 WIPHY_VENDOR_CMD_NEED_RUNNING,
8433 .doit = wlan_hdd_cfg80211_p2p_lo_start
8434 },
8435 {
8436 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8437 .info.subcmd =
8438 QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP,
8439 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8440 WIPHY_VENDOR_CMD_NEED_NETDEV |
8441 WIPHY_VENDOR_CMD_NEED_RUNNING,
8442 .doit = wlan_hdd_cfg80211_p2p_lo_stop
8443 },
Manishekar Chandrasekaran9e8c7be2016-08-03 14:57:14 +05308444 {
8445 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8446 .info.subcmd =
8447 QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH,
8448 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8449 WIPHY_VENDOR_CMD_NEED_NETDEV |
8450 WIPHY_VENDOR_CMD_NEED_RUNNING,
8451 .doit = wlan_hdd_cfg80211_conditional_chan_switch
8452 },
Deepak Dhamdhere5cdce842016-05-31 10:39:12 -07008453#ifdef WLAN_FEATURE_NAN_DATAPATH
8454 {
8455 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8456 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_NDP,
8457 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8458 WIPHY_VENDOR_CMD_NEED_NETDEV |
8459 WIPHY_VENDOR_CMD_NEED_RUNNING,
8460 .doit = wlan_hdd_cfg80211_process_ndp_cmd
8461 },
8462#endif
Padma, Santhosh Kumar5e33beb2016-08-08 19:07:06 +05308463 {
8464 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8465 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS,
8466 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8467 WIPHY_VENDOR_CMD_NEED_NETDEV |
8468 WIPHY_VENDOR_CMD_NEED_RUNNING,
8469 .doit = wlan_hdd_cfg80211_get_wakelock_stats
8470 },
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308471 {
Rajeev Kumar Sirasanagandla47873002016-09-09 13:46:09 +05308472 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8473 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE,
8474 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8475 WIPHY_VENDOR_CMD_NEED_NETDEV |
8476 WIPHY_VENDOR_CMD_NEED_RUNNING,
8477 .doit = wlan_hdd_cfg80211_get_bus_size
8478 },
8479 {
Srinivas Dasari510e7fe2016-04-28 11:51:30 +05308480 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SETBAND,
8481 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8482 WIPHY_VENDOR_CMD_NEED_NETDEV |
8483 WIPHY_VENDOR_CMD_NEED_RUNNING,
8484 .doit = wlan_hdd_cfg80211_setband
Mukul Sharma69c44cd2016-09-12 18:33:57 +05308485 },
8486 {
8487 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8488 .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ROAMING,
8489 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8490 WIPHY_VENDOR_CMD_NEED_NETDEV |
8491 WIPHY_VENDOR_CMD_NEED_RUNNING,
8492 .doit = wlan_hdd_cfg80211_set_fast_roaming
Padma, Santhosh Kumard7cc0792016-06-28 18:54:12 +05308493 },
8494#ifdef WLAN_FEATURE_DISA
8495 {
8496 .info.vendor_id = QCA_NL80211_VENDOR_ID,
8497 .info.subcmd =
8498 QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST,
8499 .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
8500 WIPHY_VENDOR_CMD_NEED_NETDEV |
8501 WIPHY_VENDOR_CMD_NEED_RUNNING,
8502 .doit = wlan_hdd_cfg80211_encrypt_decrypt_msg
8503 },
8504#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008505};
8506
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008507/**
8508 * hdd_cfg80211_wiphy_alloc() - Allocate wiphy context
8509 * @priv_size: Size of the hdd context.
8510 *
8511 * Allocate wiphy context and hdd context.
8512 *
8513 * Return: hdd context on success and NULL on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008514 */
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008515hdd_context_t *hdd_cfg80211_wiphy_alloc(int priv_size)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008516{
8517 struct wiphy *wiphy;
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008518 hdd_context_t *hdd_ctx;
8519
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008520 ENTER();
8521
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008522 wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size);
8523
8524 if (!wiphy) {
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008525 hdd_err("wiphy init failed!\n");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008526 return NULL;
8527 }
8528
Prashanth Bhattac2a16f62015-12-03 15:06:15 -08008529 hdd_ctx = wiphy_priv(wiphy);
8530
8531 hdd_ctx->wiphy = wiphy;
8532
8533 return hdd_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008534}
8535
8536/*
8537 * FUNCTION: wlan_hdd_cfg80211_update_band
8538 * This function is called from the supplicant through a
8539 * private ioctl to change the band value
8540 */
8541int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand)
8542{
8543 int i, j;
Amar Singhala297bfa2015-10-15 15:07:29 -07008544 enum channel_state channelEnabledState;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008545
8546 ENTER();
8547
8548 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8549
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008550 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008551 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008552
8553 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8554 struct ieee80211_supported_band *band = wiphy->bands[i];
8555
8556 channelEnabledState =
8557 cds_get_channel_state(band->channels[j].
8558 hw_value);
8559
8560 if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) {
8561 /* 5G only */
8562#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8563 /* Enable Social channels for P2P */
8564 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8565 (band->channels[j].center_freq)
8566 && CHANNEL_STATE_ENABLE ==
8567 channelEnabledState)
8568 band->channels[j].flags &=
8569 ~IEEE80211_CHAN_DISABLED;
8570 else
8571#endif
8572 band->channels[j].flags |=
8573 IEEE80211_CHAN_DISABLED;
8574 continue;
8575 } else if (IEEE80211_BAND_5GHZ == i &&
8576 eCSR_BAND_24 == eBand) {
8577 /* 2G only */
8578 band->channels[j].flags |=
8579 IEEE80211_CHAN_DISABLED;
8580 continue;
8581 }
8582
Amar Singhal6842e8f2016-02-23 16:30:32 -08008583 if (CHANNEL_STATE_DISABLE != channelEnabledState)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008584 band->channels[j].flags &=
8585 ~IEEE80211_CHAN_DISABLED;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008586 }
8587 }
8588 return 0;
8589}
8590
8591/*
8592 * FUNCTION: wlan_hdd_cfg80211_init
8593 * This function is called by hdd_wlan_startup()
8594 * during initialization.
8595 * This function is used to initialize and register wiphy structure.
8596 */
8597int wlan_hdd_cfg80211_init(struct device *dev,
8598 struct wiphy *wiphy, struct hdd_config *pCfg)
8599{
8600 int i, j;
8601 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8602
8603 ENTER();
8604
8605 /* Now bind the underlying wlan device with wiphy */
8606 set_wiphy_dev(wiphy, dev);
8607
8608 wiphy->mgmt_stypes = wlan_hdd_txrx_stypes;
8609
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008610#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
8611 wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008612 wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008613#else
8614 wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS;
Amar Singhal01098f72015-10-08 11:55:32 -07008615 wiphy->country_ie_pref |= NL80211_COUNTRY_IE_IGNORE_CORE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008616#endif
8617
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008618 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME
8619 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
8620 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
8621#ifdef FEATURE_WLAN_STA_4ADDR_SCHEME
8622 | WIPHY_FLAG_4ADDR_STATION
8623#endif
8624 | WIPHY_FLAG_OFFCHAN_TX;
8625
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008626#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
8627 wiphy->wowlan = &wowlan_support_cfg80211_init;
8628#else
8629 wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT;
8630 wiphy->wowlan.n_patterns = WOWL_MAX_PTRNS_ALLOWED;
8631 wiphy->wowlan.pattern_min_len = 1;
8632 wiphy->wowlan.pattern_max_len = WOWL_PTRN_MAX_SIZE;
8633#endif
8634
Deepak Dhamdherea2df6bb2015-10-29 15:11:06 -07008635 if (pCfg->isFastTransitionEnabled || pCfg->isFastRoamIniFeatureEnabled
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008636#ifdef FEATURE_WLAN_ESE
8637 || pCfg->isEseIniFeatureEnabled
8638#endif
8639 ) {
8640 wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
8641 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008642#ifdef FEATURE_WLAN_TDLS
8643 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS
8644 | WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
8645#endif
8646
8647 wiphy->features |= NL80211_FEATURE_HT_IBSS;
8648
Naveen Rawatc77e6e72016-08-05 15:19:03 -07008649#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
8650 wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
8651#endif
8652
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008653#ifdef FEATURE_WLAN_SCAN_PNO
8654 if (pCfg->configPNOScanSupport) {
8655 wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8656 wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS;
8657 wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS;
8658 wiphy->max_sched_scan_ie_len = SIR_MAC_MAX_IE_LENGTH;
Ryan Hsub736bc52016-06-15 16:58:24 -07008659#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) || defined(WITH_BACKPORTS)
8660 wiphy->max_sched_scan_plans = SIR_PNO_MAX_PLAN_REQUEST;
8661#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008662 }
8663#endif /*FEATURE_WLAN_SCAN_PNO */
8664
8665#if defined QCA_WIFI_FTM
Anurag Chouhan6d760662016-02-20 16:05:43 +05308666 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008667#endif
8668
8669 /* even with WIPHY_FLAG_CUSTOM_REGULATORY,
8670 driver can still register regulatory callback and
8671 it will get regulatory settings in wiphy->band[], but
8672 driver need to determine what to do with both
8673 regulatory settings */
8674
8675 wiphy->reg_notifier = hdd_reg_notifier;
8676
8677#if defined QCA_WIFI_FTM
8678}
8679#endif
8680
8681 wiphy->max_scan_ssids = MAX_SCAN_SSID;
8682
8683 wiphy->max_scan_ie_len = SIR_MAC_MAX_ADD_IE_LENGTH;
8684
8685 wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS;
8686
Arun Khandavallifae92942016-08-01 13:31:08 +05308687 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)
8688 | BIT(NL80211_IFTYPE_ADHOC)
8689 | BIT(NL80211_IFTYPE_P2P_CLIENT)
8690 | BIT(NL80211_IFTYPE_P2P_GO)
8691 | BIT(NL80211_IFTYPE_AP)
8692 | BIT(NL80211_IFTYPE_MONITOR);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008693
Arun Khandavallifae92942016-08-01 13:31:08 +05308694 if (pCfg->advertiseConcurrentOperation) {
8695 if (pCfg->enableMCC) {
8696 int i;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -07008697
Arun Khandavallifae92942016-08-01 13:31:08 +05308698 for (i = 0;
8699 i < ARRAY_SIZE(wlan_hdd_iface_combination);
8700 i++) {
8701 if (!pCfg->allowMCCGODiffBI)
8702 wlan_hdd_iface_combination[i].
8703 beacon_int_infra_match = true;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008704 }
8705 }
8706 wiphy->n_iface_combinations =
Arun Khandavallifae92942016-08-01 13:31:08 +05308707 ARRAY_SIZE(wlan_hdd_iface_combination);
8708 wiphy->iface_combinations = wlan_hdd_iface_combination;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008709 }
8710
8711 /* Before registering we need to update the ht capabilitied based
8712 * on ini values*/
8713 if (!pCfg->ShortGI20MhzEnable) {
8714 wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
8715 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008716 }
8717
8718 if (!pCfg->ShortGI40MhzEnable) {
8719 wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
8720 }
8721
8722 if (!pCfg->nChannelBondingMode5GHz) {
8723 wlan_hdd_band_5_ghz.ht_cap.cap &=
8724 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
8725 }
8726
Abhishek Singhf512bf32016-05-04 16:47:46 +05308727 /*
8728 * In case of static linked driver at the time of driver unload,
8729 * module exit doesn't happens. Module cleanup helps in cleaning
8730 * of static memory.
8731 * If driver load happens statically, at the time of driver unload,
8732 * wiphy flags don't get reset because of static memory.
8733 * It's better not to store channel in static memory.
8734 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008735 wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_ghz;
Abhishek Singhf512bf32016-05-04 16:47:46 +05308736 wiphy->bands[IEEE80211_BAND_2GHZ]->channels =
8737 qdf_mem_malloc(sizeof(hdd_channels_2_4_ghz));
8738 if (wiphy->bands[IEEE80211_BAND_2GHZ]->channels == NULL) {
8739 hdd_err("Not enough memory to allocate channels");
8740 return -ENOMEM;
8741 }
8742 qdf_mem_copy(wiphy->bands[IEEE80211_BAND_2GHZ]->channels,
8743 &hdd_channels_2_4_ghz[0],
8744 sizeof(hdd_channels_2_4_ghz));
Selvaraj, Sridharcd3cc702016-07-31 15:37:07 +05308745 if ((hdd_is_5g_supported(pHddCtx)) &&
8746 ((eHDD_DOT11_MODE_11b != pCfg->dot11Mode) &&
8747 (eHDD_DOT11_MODE_11g != pCfg->dot11Mode) &&
8748 (eHDD_DOT11_MODE_11b_ONLY != pCfg->dot11Mode) &&
8749 (eHDD_DOT11_MODE_11g_ONLY != pCfg->dot11Mode))) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008750 wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_ghz;
Abhishek Singhf512bf32016-05-04 16:47:46 +05308751 wiphy->bands[IEEE80211_BAND_5GHZ]->channels =
8752 qdf_mem_malloc(sizeof(hdd_channels_5_ghz));
8753 if (wiphy->bands[IEEE80211_BAND_5GHZ]->channels == NULL) {
8754 hdd_err("Not enough memory to allocate channels");
8755 qdf_mem_free(wiphy->
8756 bands[IEEE80211_BAND_2GHZ]->channels);
8757 wiphy->bands[IEEE80211_BAND_2GHZ]->channels = NULL;
8758 return -ENOMEM;
8759 }
8760 qdf_mem_copy(wiphy->bands[IEEE80211_BAND_5GHZ]->channels,
8761 &hdd_channels_5_ghz[0],
8762 sizeof(hdd_channels_5_ghz));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008763 }
8764
8765 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8766
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -08008767 if (NULL == wiphy->bands[i])
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008768 continue;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008769
8770 for (j = 0; j < wiphy->bands[i]->n_channels; j++) {
8771 struct ieee80211_supported_band *band = wiphy->bands[i];
8772
8773 if (IEEE80211_BAND_2GHZ == i &&
8774 eCSR_BAND_5G == pCfg->nBandCapability) {
8775 /* 5G only */
8776#ifdef WLAN_ENABLE_SOCIAL_CHANNELS_5G_ONLY
8777 /* Enable social channels for P2P */
8778 if (WLAN_HDD_IS_SOCIAL_CHANNEL
8779 (band->channels[j].center_freq))
8780 band->channels[j].flags &=
8781 ~IEEE80211_CHAN_DISABLED;
8782 else
8783#endif
8784 band->channels[j].flags |=
8785 IEEE80211_CHAN_DISABLED;
8786 continue;
8787 } else if (IEEE80211_BAND_5GHZ == i &&
8788 eCSR_BAND_24 == pCfg->nBandCapability) {
8789 /* 2G only */
8790 band->channels[j].flags |=
8791 IEEE80211_CHAN_DISABLED;
8792 continue;
8793 }
8794 }
8795 }
8796 /*Initialise the supported cipher suite details */
8797 wiphy->cipher_suites = hdd_cipher_suites;
8798 wiphy->n_cipher_suites = ARRAY_SIZE(hdd_cipher_suites);
8799
8800 /*signal strength in mBm (100*dBm) */
8801 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
8802 wiphy->max_remain_on_channel_duration = MAX_REMAIN_ON_CHANNEL_DURATION;
8803
Anurag Chouhan6d760662016-02-20 16:05:43 +05308804 if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008805 wiphy->n_vendor_commands =
8806 ARRAY_SIZE(hdd_wiphy_vendor_commands);
8807 wiphy->vendor_commands = hdd_wiphy_vendor_commands;
8808
8809 wiphy->vendor_events = wlan_hdd_cfg80211_vendor_events;
8810 wiphy->n_vendor_events =
8811 ARRAY_SIZE(wlan_hdd_cfg80211_vendor_events);
8812 }
8813
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008814 if (pCfg->enableDFSMasterCap) {
8815 wiphy->flags |= WIPHY_FLAG_DFS_OFFLOAD;
8816 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008817
8818 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8819
8820#ifdef QCA_HT_2040_COEX
8821 wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
8822#endif
8823
Abhishek Singh1bdb1572015-10-16 16:24:19 +05308824 hdd_add_channel_switch_support(&wiphy->flags);
8825
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008826 EXIT();
8827 return 0;
8828}
8829
Abhishek Singhf512bf32016-05-04 16:47:46 +05308830/**
8831 * wlan_hdd_cfg80211_deinit - Deinit cfg80211
8832 * @ wiphy: the wiphy to validate against
8833 *
8834 * this function deinit cfg80211 and cleanup the
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308835 * memory allocated in wlan_hdd_cfg80211_init also
8836 * reset the global reg params.
Abhishek Singhf512bf32016-05-04 16:47:46 +05308837 *
8838 * Return: void
8839 */
8840void wlan_hdd_cfg80211_deinit(struct wiphy *wiphy)
8841{
8842 int i;
8843
8844 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
8845 if (NULL != wiphy->bands[i] &&
8846 (NULL != wiphy->bands[i]->channels)) {
8847 qdf_mem_free(wiphy->bands[i]->channels);
8848 wiphy->bands[i]->channels = NULL;
8849 }
8850 }
Abhishek Singh3e6172f2016-05-04 16:56:48 +05308851 hdd_reset_global_reg_params();
Abhishek Singhf512bf32016-05-04 16:47:46 +05308852}
8853
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008854/*
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05308855 * In this function, wiphy structure is updated after QDF
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008856 * initialization. In wlan_hdd_cfg80211_init, only the
8857 * default values will be initialized. The final initialization
8858 * of all required members can be done here.
8859 */
8860void wlan_hdd_update_wiphy(struct wiphy *wiphy, struct hdd_config *pCfg)
8861{
8862 wiphy->max_ap_assoc_sta = pCfg->maxNumberOfPeers;
8863}
8864
8865/* In this function we are registering wiphy. */
8866int wlan_hdd_cfg80211_register(struct wiphy *wiphy)
8867{
8868 ENTER();
8869 /* Register our wiphy dev with cfg80211 */
8870 if (0 > wiphy_register(wiphy)) {
8871 /* print error */
Jeff Johnson77848112016-06-29 14:52:06 -07008872 hdd_err("wiphy register failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008873 return -EIO;
8874 }
8875
8876 EXIT();
8877 return 0;
8878}
8879
8880/*
8881 HDD function to update wiphy capability based on target offload status.
8882
8883 wlan_hdd_cfg80211_init() does initialization of all wiphy related
8884 capability even before downloading firmware to the target. In discrete
8885 case, host will get know certain offload capability (say sched_scan
8886 caps) only after downloading firmware to the target and target boots up.
8887 This function is used to override setting done in wlan_hdd_cfg80211_init()
8888 based on target capability.
8889 */
8890void wlan_hdd_cfg80211_update_wiphy_caps(struct wiphy *wiphy)
8891{
8892#ifdef FEATURE_WLAN_SCAN_PNO
8893 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
8894 struct hdd_config *pCfg = pHddCtx->config;
8895
8896 /* wlan_hdd_cfg80211_init() sets sched_scan caps already in wiphy before
8897 * control comes here. Here just we need to clear it if firmware doesn't
8898 * have PNO support. */
8899 if (!pCfg->PnoOffload) {
8900 wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8901 wiphy->max_sched_scan_ssids = 0;
8902 wiphy->max_match_sets = 0;
8903 wiphy->max_sched_scan_ie_len = 0;
8904 }
8905#endif
8906}
8907
8908/* This function registers for all frame which supplicant is interested in */
8909void wlan_hdd_cfg80211_register_frames(hdd_adapter_t *pAdapter)
8910{
8911 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
8912 /* Register for all P2P action, public action etc frames */
8913 uint16_t type = (SIR_MAC_MGMT_FRAME << 2) | (SIR_MAC_MGMT_ACTION << 4);
8914
8915 ENTER();
8916
Abhishek Singh7996eb72015-12-30 17:24:02 +05308917 /* Register frame indication call back */
8918 sme_register_mgmt_frame_ind_callback(hHal, hdd_indicate_mgmt_frame);
8919
Selvaraj, Sridhar4577a9b2016-09-04 15:17:07 +05308920 /* Register for p2p ack indication */
8921 sme_register_p2p_ack_ind_callback(hHal, hdd_send_action_cnf_cb);
8922
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08008923 /* Right now we are registering these frame when driver is getting
8924 initialized. Once we will move to 2.6.37 kernel, in which we have
8925 frame register ops, we will move this code as a part of that */
8926 /* GAS Initial Request */
8927 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8928 (uint8_t *) GAS_INITIAL_REQ,
8929 GAS_INITIAL_REQ_SIZE);
8930
8931 /* GAS Initial Response */
8932 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8933 (uint8_t *) GAS_INITIAL_RSP,
8934 GAS_INITIAL_RSP_SIZE);
8935
8936 /* GAS Comeback Request */
8937 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8938 (uint8_t *) GAS_COMEBACK_REQ,
8939 GAS_COMEBACK_REQ_SIZE);
8940
8941 /* GAS Comeback Response */
8942 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8943 (uint8_t *) GAS_COMEBACK_RSP,
8944 GAS_COMEBACK_RSP_SIZE);
8945
8946 /* P2P Public Action */
8947 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8948 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
8949 P2P_PUBLIC_ACTION_FRAME_SIZE);
8950
8951 /* P2P Action */
8952 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8953 (uint8_t *) P2P_ACTION_FRAME,
8954 P2P_ACTION_FRAME_SIZE);
8955
8956 /* WNM BSS Transition Request frame */
8957 sme_register_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8958 (uint8_t *) WNM_BSS_ACTION_FRAME,
8959 WNM_BSS_ACTION_FRAME_SIZE);
8960
8961 /* WNM-Notification */
8962 sme_register_mgmt_frame(hHal, pAdapter->sessionId, type,
8963 (uint8_t *) WNM_NOTIFICATION_FRAME,
8964 WNM_NOTIFICATION_FRAME_SIZE);
8965}
8966
8967void wlan_hdd_cfg80211_deregister_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
8975 /* Right now we are registering these frame when driver is getting
8976 initialized. Once we will move to 2.6.37 kernel, in which we have
8977 frame register ops, we will move this code as a part of that */
8978 /* GAS Initial Request */
8979
8980 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8981 (uint8_t *) GAS_INITIAL_REQ,
8982 GAS_INITIAL_REQ_SIZE);
8983
8984 /* GAS Initial Response */
8985 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8986 (uint8_t *) GAS_INITIAL_RSP,
8987 GAS_INITIAL_RSP_SIZE);
8988
8989 /* GAS Comeback Request */
8990 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8991 (uint8_t *) GAS_COMEBACK_REQ,
8992 GAS_COMEBACK_REQ_SIZE);
8993
8994 /* GAS Comeback Response */
8995 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
8996 (uint8_t *) GAS_COMEBACK_RSP,
8997 GAS_COMEBACK_RSP_SIZE);
8998
8999 /* P2P Public Action */
9000 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9001 (uint8_t *) P2P_PUBLIC_ACTION_FRAME,
9002 P2P_PUBLIC_ACTION_FRAME_SIZE);
9003
9004 /* P2P Action */
9005 sme_deregister_mgmt_frame(hHal, SME_SESSION_ID_ANY, type,
9006 (uint8_t *) P2P_ACTION_FRAME,
9007 P2P_ACTION_FRAME_SIZE);
9008
9009 /* WNM-Notification */
9010 sme_deregister_mgmt_frame(hHal, pAdapter->sessionId, type,
9011 (uint8_t *) WNM_NOTIFICATION_FRAME,
9012 WNM_NOTIFICATION_FRAME_SIZE);
9013}
9014
9015#ifdef FEATURE_WLAN_WAPI
9016void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t *pAdapter, uint8_t key_index,
9017 const uint8_t *mac_addr, const uint8_t *key,
9018 int key_Len)
9019{
9020 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9021 tCsrRoamSetKey setKey;
9022 bool isConnected = true;
9023 int status = 0;
9024 uint32_t roamId = 0xFF;
9025 uint8_t *pKeyPtr = NULL;
9026 int n = 0;
9027
Jeff Johnson46b40792016-06-29 14:03:14 -07009028 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009029 hdd_device_mode_to_string(pAdapter->device_mode),
9030 pAdapter->device_mode);
9031
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309032 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009033 setKey.keyId = key_index; /* Store Key ID */
9034 setKey.encType = eCSR_ENCRYPT_TYPE_WPI; /* SET WAPI Encryption */
9035 setKey.keyDirection = eSIR_TX_RX; /* Key Directionn both TX and RX */
9036 setKey.paeRole = 0; /* the PAE role */
9037 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
Anurag Chouhanc5548422016-02-24 18:33:27 +05309038 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009039 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309040 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009041 }
9042 setKey.keyLength = key_Len;
9043 pKeyPtr = setKey.Key;
9044 memcpy(pKeyPtr, key, key_Len);
9045
Jeff Johnson46b40792016-06-29 14:03:14 -07009046 hdd_notice("WAPI KEY LENGTH:0x%04x", key_Len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009047 for (n = 0; n < key_Len; n++)
Jeff Johnson46b40792016-06-29 14:03:14 -07009048 hdd_notice("WAPI KEY Data[%d]:%02x ",
9049 n, setKey.Key[n]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009050
9051 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
9052 if (isConnected) {
9053 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
9054 pAdapter->sessionId, &setKey, &roamId);
9055 }
9056 if (status != 0) {
Jeff Johnson46b40792016-06-29 14:03:14 -07009057 hdd_err("sme_roam_set_key returned ERROR status= %d",
9058 status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009059 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE;
9060 }
9061}
9062#endif /* FEATURE_WLAN_WAPI */
9063
9064uint8_t *wlan_hdd_cfg80211_get_ie_ptr(const uint8_t *ies_ptr, int length,
9065 uint8_t eid)
9066{
9067 int left = length;
9068 uint8_t *ptr = (uint8_t *)ies_ptr;
9069 uint8_t elem_id, elem_len;
9070
9071 while (left >= 2) {
9072 elem_id = ptr[0];
9073 elem_len = ptr[1];
9074 left -= 2;
9075 if (elem_len > left) {
Jeff Johnson77848112016-06-29 14:52:06 -07009076 hdd_alert("Invalid IEs eid = %d elem_len=%d left=%d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009077 eid, elem_len, left);
9078 return NULL;
9079 }
9080 if (elem_id == eid) {
9081 return ptr;
9082 }
9083
9084 left -= elem_len;
9085 ptr += (elem_len + 2);
9086 }
9087 return NULL;
9088}
9089
9090/*
9091 * FUNCTION: wlan_hdd_validate_operation_channel
9092 * called by wlan_hdd_cfg80211_start_bss() and
9093 * wlan_hdd_set_channel()
9094 * This function validates whether given channel is part of valid
9095 * channel list.
9096 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309097QDF_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009098 int channel)
9099{
9100
9101 uint32_t num_ch = 0;
9102 u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN];
9103 u32 indx = 0;
9104 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
9105 uint8_t fValidChannel = false, count = 0;
9106 struct hdd_config *hdd_pConfig_ini = (WLAN_HDD_GET_CTX(pAdapter))->config;
9107
9108 num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN;
9109
9110 if (hdd_pConfig_ini->sapAllowAllChannel) {
9111 /* Validate the channel */
Amar Singhalb8d4f152016-02-10 10:21:43 -08009112 for (count = CHAN_ENUM_1; count <= CHAN_ENUM_165; count++) {
Amar Singhal7a1726a2015-10-14 16:28:11 -07009113 if (channel == CDS_CHANNEL_NUM(count)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009114 fValidChannel = true;
9115 break;
9116 }
9117 }
9118 if (fValidChannel != true) {
Jeff Johnson77848112016-06-29 14:52:06 -07009119 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309120 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009121 }
9122 } else {
9123 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
9124 valid_ch, &num_ch)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009125 hdd_err("failed to get valid channel list");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309126 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009127 }
9128 for (indx = 0; indx < num_ch; indx++) {
9129 if (channel == valid_ch[indx]) {
9130 break;
9131 }
9132 }
9133
9134 if (indx >= num_ch) {
Jeff Johnson77848112016-06-29 14:52:06 -07009135 hdd_err("Invalid Channel [%d]", channel);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309136 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009137 }
9138 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309139 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009140
9141}
9142
9143#ifdef DHCP_SERVER_OFFLOAD
9144static void wlan_hdd_set_dhcp_server_offload(hdd_adapter_t *pHostapdAdapter)
9145{
9146 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
9147 tpSirDhcpSrvOffloadInfo pDhcpSrvInfo;
9148 uint8_t numEntries = 0;
9149 uint8_t srv_ip[IPADDR_NUM_ENTRIES];
9150 uint8_t num;
9151 uint32_t temp;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309152 pDhcpSrvInfo = qdf_mem_malloc(sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009153 if (NULL == pDhcpSrvInfo) {
Jeff Johnson77848112016-06-29 14:52:06 -07009154 hdd_err("could not allocate tDhcpSrvOffloadInfo!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009155 return;
9156 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309157 qdf_mem_zero(pDhcpSrvInfo, sizeof(*pDhcpSrvInfo));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009158 pDhcpSrvInfo->vdev_id = pHostapdAdapter->sessionId;
9159 pDhcpSrvInfo->dhcpSrvOffloadEnabled = true;
9160 pDhcpSrvInfo->dhcpClientNum = pHddCtx->config->dhcpMaxNumClients;
9161 hdd_string_to_u8_array(pHddCtx->config->dhcpServerIP,
9162 srv_ip, &numEntries, IPADDR_NUM_ENTRIES);
9163 if (numEntries != IPADDR_NUM_ENTRIES) {
Jeff Johnson77848112016-06-29 14:52:06 -07009164 hdd_err("incorrect IP address (%s) assigned for DHCP server!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009165 goto end;
9166 }
9167 if ((srv_ip[0] >= 224) && (srv_ip[0] <= 239)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009168 hdd_err("invalid IP address (%s)! It could NOT be multicast IP address!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009169 goto end;
9170 }
9171 if (srv_ip[IPADDR_NUM_ENTRIES - 1] >= 100) {
Jeff Johnson77848112016-06-29 14:52:06 -07009172 hdd_err("invalid IP address (%s)! The last field must be less than 100!", pHddCtx->config->dhcpServerIP);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009173 goto end;
9174 }
9175 for (num = 0; num < numEntries; num++) {
9176 temp = srv_ip[num];
9177 pDhcpSrvInfo->dhcpSrvIP |= (temp << (8 * num));
9178 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309179 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009180 sme_set_dhcp_srv_offload(pHddCtx->hHal, pDhcpSrvInfo)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009181 hdd_err("sme_setDHCPSrvOffload fail!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009182 goto end;
9183 }
Jeff Johnson77848112016-06-29 14:52:06 -07009184 hdd_info("enable DHCP Server offload successfully!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009185end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309186 qdf_mem_free(pDhcpSrvInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009187 return;
9188}
9189#endif /* DHCP_SERVER_OFFLOAD */
9190
9191static int __wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9192 struct net_device *dev,
9193 struct bss_parameters *params)
9194{
9195 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9196 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9197 int ret = 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309198 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009199
9200 ENTER();
9201
Anurag Chouhan6d760662016-02-20 16:05:43 +05309202 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009203 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009204 return -EINVAL;
9205 }
9206
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309207 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009208 TRACE_CODE_HDD_CFG80211_CHANGE_BSS,
9209 pAdapter->sessionId, params->ap_isolate));
Jeff Johnson77848112016-06-29 14:52:06 -07009210 hdd_notice("Device_mode %s(%d), ap_isolate = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009211 hdd_device_mode_to_string(pAdapter->device_mode),
9212 pAdapter->device_mode, params->ap_isolate);
9213
9214 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9215 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309216 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009217 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009218
Krunal Sonib4326f22016-03-10 13:05:51 -08009219 if (!(pAdapter->device_mode == QDF_SAP_MODE ||
9220 pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009221 return -EOPNOTSUPP;
9222 }
9223
9224 /* ap_isolate == -1 means that in change bss, upper layer doesn't
9225 * want to update this parameter */
9226 if (-1 != params->ap_isolate) {
9227 pAdapter->sessionCtx.ap.apDisableIntraBssFwd =
9228 !!params->ap_isolate;
9229
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309230 qdf_ret_status = sme_ap_disable_intra_bss_fwd(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009231 pAdapter->sessionId,
9232 pAdapter->sessionCtx.
9233 ap.
9234 apDisableIntraBssFwd);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309235 if (!QDF_IS_STATUS_SUCCESS(qdf_ret_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009236 ret = -EINVAL;
9237 }
9238 }
9239
9240 EXIT();
9241 return ret;
9242}
9243
Krunal Soni8c37e322016-02-03 16:08:37 -08009244/**
9245 * wlan_hdd_change_client_iface_to_new_mode() - to change iface to provided mode
9246 * @ndev: pointer to net device provided by supplicant
9247 * @type: type of the interface, upper layer wanted to change
9248 *
9249 * Upper layer provides the new interface mode that needs to be changed
9250 * for given net device
9251 *
9252 * Return: success or failure in terms of integer value
9253 */
9254static int wlan_hdd_change_client_iface_to_new_mode(struct net_device *ndev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009255 enum nl80211_iftype type)
9256{
Krunal Soni8c37e322016-02-03 16:08:37 -08009257 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9258 hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
9259 struct hdd_config *config = hdd_ctx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009260 hdd_wext_state_t *wext;
9261 struct wireless_dev *wdev;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309262 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009263
9264 ENTER();
9265
Krunal Soni8c37e322016-02-03 16:08:37 -08009266 if (test_bit(ACS_IN_PROGRESS, &hdd_ctx->g_event_flags)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009267 hdd_notice("ACS is in progress, don't change iface!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009268 return 0;
9269 }
9270
9271 wdev = ndev->ieee80211_ptr;
Krunal Soni8c37e322016-02-03 16:08:37 -08009272 hdd_stop_adapter(hdd_ctx, adapter, true);
9273 hdd_deinit_adapter(hdd_ctx, adapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009274 wdev->iftype = type;
9275 /*Check for sub-string p2p to confirm its a p2p interface */
9276 if (NULL != strnstr(ndev->name, "p2p", 3)) {
Krunal Soni8c37e322016-02-03 16:08:37 -08009277 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009278 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009279 QDF_P2P_DEVICE_MODE : QDF_P2P_CLIENT_MODE;
Krunal Soni8c37e322016-02-03 16:08:37 -08009280 } else if (type == NL80211_IFTYPE_ADHOC) {
Krunal Sonib4326f22016-03-10 13:05:51 -08009281 adapter->device_mode = QDF_IBSS_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009282 } else {
Krunal Soni8c37e322016-02-03 16:08:37 -08009283 adapter->device_mode =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009284 (type == NL80211_IFTYPE_STATION) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009285 QDF_STA_MODE : QDF_P2P_CLIENT_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009286 }
Krunal Soni8c37e322016-02-03 16:08:37 -08009287 memset(&adapter->sessionCtx, 0, sizeof(adapter->sessionCtx));
9288 hdd_set_station_ops(adapter->dev);
Krunal Soni8c37e322016-02-03 16:08:37 -08009289 wext = WLAN_HDD_GET_WEXT_STATE_PTR(adapter);
9290 wext->roamProfile.pAddIEScan = adapter->scan_info.scanAddIE.addIEdata;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009291 wext->roamProfile.nAddIEScanLength =
Krunal Soni8c37e322016-02-03 16:08:37 -08009292 adapter->scan_info.scanAddIE.length;
9293 if (type == NL80211_IFTYPE_ADHOC) {
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309294 status = hdd_init_station_mode(adapter);
Krunal Soni8c37e322016-02-03 16:08:37 -08009295 wext->roamProfile.BSSType = eCSR_BSS_TYPE_START_IBSS;
9296 wext->roamProfile.phyMode =
9297 hdd_cfg_xlate_to_csr_phy_mode(config->dot11Mode);
9298 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009299 EXIT();
9300 return status;
9301}
9302
9303static int wlan_hdd_cfg80211_change_bss(struct wiphy *wiphy,
9304 struct net_device *dev,
9305 struct bss_parameters *params)
9306{
9307 int ret;
9308
9309 cds_ssr_protect(__func__);
9310 ret = __wlan_hdd_cfg80211_change_bss(wiphy, dev, params);
9311 cds_ssr_unprotect(__func__);
9312
9313 return ret;
9314}
9315
9316/* FUNCTION: wlan_hdd_change_country_code_cd
9317 * to wait for contry code completion
9318 */
9319void *wlan_hdd_change_country_code_cb(void *pAdapter)
9320{
9321 hdd_adapter_t *call_back_pAdapter = pAdapter;
9322 complete(&call_back_pAdapter->change_country_code);
9323 return NULL;
9324}
9325
Rajeev Kumar98edb772016-01-19 12:42:19 -08009326/**
9327 * __wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9328 * @wiphy: Pointer to the wiphy structure
9329 * @ndev: Pointer to the net device
9330 * @type: Interface type
9331 * @flags: Flags for change interface
9332 * @params: Pointer to change interface parameters
9333 *
9334 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009335 */
9336static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9337 struct net_device *ndev,
9338 enum nl80211_iftype type,
9339 u32 *flags,
9340 struct vif_params *params)
9341{
9342 struct wireless_dev *wdev;
9343 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9344 hdd_context_t *pHddCtx;
9345 tCsrRoamProfile *pRoamProfile = NULL;
9346 eCsrRoamBssType LastBSSType;
9347 struct hdd_config *pConfig = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309348 QDF_STATUS vstatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009349 int status;
9350
9351 ENTER();
9352
Anurag Chouhan6d760662016-02-20 16:05:43 +05309353 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson77848112016-06-29 14:52:06 -07009354 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009355 return -EINVAL;
9356 }
9357
9358 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9359 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309360 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009361 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009362
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309363 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009364 TRACE_CODE_HDD_CFG80211_CHANGE_IFACE,
9365 pAdapter->sessionId, type));
9366
Jeff Johnson77848112016-06-29 14:52:06 -07009367 hdd_notice("Device_mode = %d, IFTYPE = 0x%x",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009368 pAdapter->device_mode, type);
9369
Arun Khandavallifae92942016-08-01 13:31:08 +05309370 status = hdd_wlan_start_modules(pHddCtx, pAdapter, false);
9371 if (status) {
9372 hdd_err("Failed to start modules");
9373 return -EINVAL;
9374 }
9375
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009376 if (!cds_allow_concurrency(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009377 wlan_hdd_convert_nl_iftype_to_hdd_type(type),
9378 0, HW_MODE_20_MHZ)) {
Jeff Johnson77848112016-06-29 14:52:06 -07009379 hdd_debug("This concurrency combination is not allowed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009380 return -EINVAL;
9381 }
9382
9383 pConfig = pHddCtx->config;
9384 wdev = ndev->ieee80211_ptr;
9385
9386 /* Reset the current device mode bit mask */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009387 cds_clear_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009388
9389 hdd_tdls_notify_mode_change(pAdapter, pHddCtx);
9390
Krunal Sonib4326f22016-03-10 13:05:51 -08009391 if ((pAdapter->device_mode == QDF_STA_MODE) ||
9392 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) ||
9393 (pAdapter->device_mode == QDF_P2P_DEVICE_MODE) ||
9394 (pAdapter->device_mode == QDF_IBSS_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009395 hdd_wext_state_t *pWextState =
9396 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
9397
9398 pRoamProfile = &pWextState->roamProfile;
9399 LastBSSType = pRoamProfile->BSSType;
9400
9401 switch (type) {
9402 case NL80211_IFTYPE_STATION:
9403 case NL80211_IFTYPE_P2P_CLIENT:
Krunal Soni8c37e322016-02-03 16:08:37 -08009404 case NL80211_IFTYPE_ADHOC:
9405 if (type == NL80211_IFTYPE_ADHOC) {
9406 wlan_hdd_tdls_exit(pAdapter);
9407 hdd_deregister_tx_flow_control(pAdapter);
Jeff Johnson77848112016-06-29 14:52:06 -07009408 hdd_notice("Setting interface Type to ADHOC");
Krunal Soni8c37e322016-02-03 16:08:37 -08009409 }
9410 vstatus = wlan_hdd_change_client_iface_to_new_mode(ndev,
9411 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309412 if (vstatus != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009413 return -EINVAL;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309414 if (hdd_start_adapter(pAdapter)) {
9415 hdd_err("Failed to start adapter :%d",
9416 pAdapter->device_mode);
9417 return -EINVAL;
9418 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009419 goto done;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009420 case NL80211_IFTYPE_AP:
9421 case NL80211_IFTYPE_P2P_GO:
9422 {
Jeff Johnson77848112016-06-29 14:52:06 -07009423 hdd_info("Setting interface Type to %s",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009424 (type ==
9425 NL80211_IFTYPE_AP) ? "SoftAP" :
9426 "P2pGo");
9427
9428 /* Cancel any remain on channel for GO mode */
9429 if (NL80211_IFTYPE_P2P_GO == type) {
9430 wlan_hdd_cancel_existing_remain_on_channel
9431 (pAdapter);
9432 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009433
Arun Khandavallifae92942016-08-01 13:31:08 +05309434 hdd_stop_adapter(pHddCtx, pAdapter, true);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009435 /* De-init the adapter */
9436 hdd_deinit_adapter(pHddCtx, pAdapter, true);
9437 memset(&pAdapter->sessionCtx, 0,
9438 sizeof(pAdapter->sessionCtx));
9439 pAdapter->device_mode =
9440 (type ==
Krunal Sonib4326f22016-03-10 13:05:51 -08009441 NL80211_IFTYPE_AP) ? QDF_SAP_MODE :
9442 QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009443
9444 /*
9445 * Fw will take care incase of concurrency
9446 */
9447
Krunal Sonib4326f22016-03-10 13:05:51 -08009448 if ((QDF_SAP_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009449 && (pConfig->apRandomBssidEnabled)) {
9450 /* To meet Android requirements create a randomized
9451 MAC address of the form 02:1A:11:Fx:xx:xx */
9452 get_random_bytes(&ndev->dev_addr[3], 3);
9453 ndev->dev_addr[0] = 0x02;
9454 ndev->dev_addr[1] = 0x1A;
9455 ndev->dev_addr[2] = 0x11;
9456 ndev->dev_addr[3] |= 0xF0;
9457 memcpy(pAdapter->macAddressCurrent.
9458 bytes, ndev->dev_addr,
Anurag Chouhan6d760662016-02-20 16:05:43 +05309459 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009460 pr_info("wlan: Generated HotSpot BSSID "
9461 MAC_ADDRESS_STR "\n",
9462 MAC_ADDR_ARRAY(ndev->dev_addr));
9463 }
9464
9465 hdd_set_ap_ops(pAdapter->dev);
9466
Arun Khandavallifae92942016-08-01 13:31:08 +05309467 if (hdd_start_adapter(pAdapter)) {
9468 hdd_err("Error initializing the ap mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009469 return -EINVAL;
9470 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009471 /* Interface type changed update in wiphy structure */
9472 if (wdev) {
9473 wdev->iftype = type;
9474 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009475 hdd_err("Wireless dev is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009476 return -EINVAL;
9477 }
9478 goto done;
9479 }
9480
9481 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009482 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009483 type);
9484 return -EOPNOTSUPP;
9485 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009486 } else if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9487 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009488 switch (type) {
9489 case NL80211_IFTYPE_STATION:
9490 case NL80211_IFTYPE_P2P_CLIENT:
9491 case NL80211_IFTYPE_ADHOC:
Krunal Soni8c37e322016-02-03 16:08:37 -08009492 status = wlan_hdd_change_client_iface_to_new_mode(ndev,
9493 type);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309494 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009495 return status;
Arun Khandavallib2f6c262016-08-18 19:07:19 +05309496 if (hdd_start_adapter(pAdapter)) {
9497 hdd_err("Failed to start adapter :%d",
9498 pAdapter->device_mode);
9499 return -EINVAL;
9500 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009501 goto done;
9502
9503 case NL80211_IFTYPE_AP:
9504 case NL80211_IFTYPE_P2P_GO:
9505 wdev->iftype = type;
9506 pAdapter->device_mode = (type == NL80211_IFTYPE_AP) ?
Krunal Sonib4326f22016-03-10 13:05:51 -08009507 QDF_SAP_MODE : QDF_P2P_GO_MODE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009508 goto done;
9509
9510 default:
Jeff Johnson77848112016-06-29 14:52:06 -07009511 hdd_err("Unsupported interface type(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009512 type);
9513 return -EOPNOTSUPP;
9514 }
9515 } else {
Jeff Johnson77848112016-06-29 14:52:06 -07009516 hdd_err("Unsupported device mode(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009517 pAdapter->device_mode);
9518 return -EOPNOTSUPP;
9519 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009520done:
9521 /* Set bitmask based on updated value */
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -08009522 cds_set_concurrency_mode(pAdapter->device_mode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009523
Jeff Johnson2ae6f712016-09-23 15:08:48 -07009524 hdd_lpass_notify_mode_change(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009525
9526 EXIT();
9527 return 0;
9528}
9529
Rajeev Kumar98edb772016-01-19 12:42:19 -08009530/**
9531 * wlan_hdd_cfg80211_change_iface() - change interface cfg80211 op
9532 * @wiphy: Pointer to the wiphy structure
9533 * @ndev: Pointer to the net device
9534 * @type: Interface type
9535 * @flags: Flags for change interface
9536 * @params: Pointer to change interface parameters
9537 *
9538 * Return: 0 for success, error number on failure.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009539 */
9540static int wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
9541 struct net_device *ndev,
9542 enum nl80211_iftype type,
9543 u32 *flags,
9544 struct vif_params *params)
9545{
9546 int ret;
9547
9548 cds_ssr_protect(__func__);
9549 ret =
9550 __wlan_hdd_cfg80211_change_iface(wiphy, ndev, type, flags, params);
9551 cds_ssr_unprotect(__func__);
9552
9553 return ret;
9554}
9555
9556#ifdef FEATURE_WLAN_TDLS
9557static bool wlan_hdd_is_duplicate_channel(uint8_t *arr,
9558 int index, uint8_t match)
9559{
9560 int i;
9561 for (i = 0; i < index; i++) {
9562 if (arr[i] == match)
9563 return true;
9564 }
9565 return false;
9566}
9567#endif
9568
9569/**
9570 * __wlan_hdd_change_station() - change station
9571 * @wiphy: Pointer to the wiphy structure
9572 * @dev: Pointer to the net device.
9573 * @mac: bssid
9574 * @params: Pointer to station parameters
9575 *
9576 * Return: 0 for success, error number on failure.
9577 */
9578#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9579static int __wlan_hdd_change_station(struct wiphy *wiphy,
9580 struct net_device *dev,
9581 const uint8_t *mac,
9582 struct station_parameters *params)
9583#else
9584static int __wlan_hdd_change_station(struct wiphy *wiphy,
9585 struct net_device *dev,
9586 uint8_t *mac,
9587 struct station_parameters *params)
9588#endif
9589{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309590 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009591 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
9592 hdd_context_t *pHddCtx;
9593 hdd_station_ctx_t *pHddStaCtx;
Anurag Chouhan6d760662016-02-20 16:05:43 +05309594 struct qdf_mac_addr STAMacAddress;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009595#ifdef FEATURE_WLAN_TDLS
9596 tCsrStaParams StaParams = { 0 };
9597 uint8_t isBufSta = 0;
9598 uint8_t isOffChannelSupported = 0;
Nitesh Shah99934ac2016-09-05 15:54:08 +05309599 bool is_qos_wmm_sta = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009600#endif
9601 int ret;
9602
9603 ENTER();
9604
Anurag Chouhan6d760662016-02-20 16:05:43 +05309605 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009606 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009607 return -EINVAL;
9608 }
9609
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309610 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009611 TRACE_CODE_HDD_CHANGE_STATION,
9612 pAdapter->sessionId, params->listen_interval));
9613
9614 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9615 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309616 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009617 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009618
9619 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
9620
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309621 qdf_mem_copy(STAMacAddress.bytes, mac, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009622
Krunal Sonib4326f22016-03-10 13:05:51 -08009623 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
9624 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009625 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
9626 status =
9627 hdd_softap_change_sta_state(pAdapter,
9628 &STAMacAddress,
Dhanashri Atreb08959a2016-03-01 17:28:03 -08009629 OL_TXRX_PEER_STATE_AUTH);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009630
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309631 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009632 hdd_notice("Not able to change TL state to AUTHENTICATED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009633 return -EINVAL;
9634 }
9635 }
Krunal Sonib4326f22016-03-10 13:05:51 -08009636 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
9637 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009638#ifdef FEATURE_WLAN_TDLS
9639 if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
Naveen Rawat64e477e2016-05-20 10:34:56 -07009640
9641 if (cds_is_sub_20_mhz_enabled()) {
9642 hdd_err("TDLS not allowed with sub 20 MHz");
9643 return -EINVAL;
9644 }
9645
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009646 StaParams.capability = params->capability;
9647 StaParams.uapsd_queues = params->uapsd_queues;
9648 StaParams.max_sp = params->max_sp;
9649
9650 /* Convert (first channel , number of channels) tuple to
9651 * the total list of channels. This goes with the assumption
9652 * that if the first channel is < 14, then the next channels
9653 * are an incremental of 1 else an incremental of 4 till the number
9654 * of channels.
9655 */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009656 hdd_notice("params->supported_channels_len: %d", params->supported_channels_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009657 if (0 != params->supported_channels_len) {
9658 int i = 0, j = 0, k = 0, no_of_channels = 0;
9659 int num_unique_channels;
9660 int next;
9661 for (i = 0;
9662 i < params->supported_channels_len
9663 && j < SIR_MAC_MAX_SUPP_CHANNELS; i += 2) {
9664 int wifi_chan_index;
9665 if (!wlan_hdd_is_duplicate_channel
9666 (StaParams.supported_channels, j,
9667 params->supported_channels[i])) {
9668 StaParams.
9669 supported_channels[j] =
9670 params->
9671 supported_channels[i];
9672 } else {
9673 continue;
9674 }
9675 wifi_chan_index =
9676 ((StaParams.supported_channels[j] <=
9677 HDD_CHANNEL_14) ? 1 : 4);
9678 no_of_channels =
9679 params->supported_channels[i + 1];
9680
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009681 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 -08009682 StaParams.
9683 supported_channels[j],
9684 wifi_chan_index,
9685 no_of_channels);
9686 for (k = 1; k <= no_of_channels &&
9687 j < SIR_MAC_MAX_SUPP_CHANNELS - 1;
9688 k++) {
9689 next =
9690 StaParams.
9691 supported_channels[j] +
9692 wifi_chan_index;
9693 if (!wlan_hdd_is_duplicate_channel(StaParams.supported_channels, j + 1, next)) {
9694 StaParams.
9695 supported_channels[j
9696 +
9697 1]
9698 = next;
9699 } else {
9700 continue;
9701 }
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009702 hdd_notice("i: %d, j: %d, k: %d, StaParams.supported_channels[%d]: %d", i, j, k,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009703 j + 1,
9704 StaParams.
9705 supported_channels[j +
9706 1]);
9707 j += 1;
9708 }
9709 }
9710 num_unique_channels = j + 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009711 hdd_notice("Unique Channel List");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009712 for (i = 0; i < num_unique_channels; i++) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009713 hdd_notice("StaParams.supported_channels[%d]: %d,", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009714 StaParams.
9715 supported_channels[i]);
9716 }
9717 if (MAX_CHANNEL < num_unique_channels)
9718 num_unique_channels = MAX_CHANNEL;
9719 StaParams.supported_channels_len =
9720 num_unique_channels;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009721 hdd_notice("After removing duplcates StaParams.supported_channels_len: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009722 StaParams.supported_channels_len);
9723 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309724 qdf_mem_copy(StaParams.supported_oper_classes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009725 params->supported_oper_classes,
9726 params->supported_oper_classes_len);
9727 StaParams.supported_oper_classes_len =
9728 params->supported_oper_classes_len;
9729
9730 if (0 != params->ext_capab_len)
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309731 qdf_mem_copy(StaParams.extn_capability,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009732 params->ext_capab,
9733 sizeof(StaParams.extn_capability));
9734
9735 if (NULL != params->ht_capa) {
9736 StaParams.htcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309737 qdf_mem_copy(&StaParams.HTCap, params->ht_capa,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009738 sizeof(tSirHTCap));
9739 }
9740
9741 StaParams.supported_rates_len =
9742 params->supported_rates_len;
9743
9744 /* Note : The Maximum sizeof supported_rates sent by the Supplicant is 32.
9745 * The supported_rates array , for all the structures propogating till Add Sta
9746 * to the firmware has to be modified , if the supplicant (ieee80211) is
9747 * modified to send more rates.
9748 */
9749
9750 /* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
9751 */
9752 if (StaParams.supported_rates_len >
9753 SIR_MAC_MAX_SUPP_RATES)
9754 StaParams.supported_rates_len =
9755 SIR_MAC_MAX_SUPP_RATES;
9756
9757 if (0 != StaParams.supported_rates_len) {
9758 int i = 0;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309759 qdf_mem_copy(StaParams.supported_rates,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009760 params->supported_rates,
9761 StaParams.supported_rates_len);
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009762 hdd_notice("Supported Rates with Length %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009763 StaParams.supported_rates_len);
9764 for (i = 0; i < StaParams.supported_rates_len;
9765 i++)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009766 hdd_notice("[%d]: %0x", i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009767 StaParams.supported_rates[i]);
9768 }
9769
9770 if (NULL != params->vht_capa) {
9771 StaParams.vhtcap_present = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309772 qdf_mem_copy(&StaParams.VHTCap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009773 params->vht_capa,
9774 sizeof(tSirVHTCap));
9775 }
9776
9777 if (0 != params->ext_capab_len) {
9778 /*Define A Macro : TODO Sunil */
9779 if ((1 << 4) & StaParams.extn_capability[3]) {
9780 isBufSta = 1;
9781 }
9782 /* TDLS Channel Switching Support */
9783 if ((1 << 6) & StaParams.extn_capability[3]) {
9784 isOffChannelSupported = 1;
9785 }
9786 }
9787
Nitesh Shah99934ac2016-09-05 15:54:08 +05309788 if (pHddCtx->config->fEnableTDLSWmmMode &&
Nitesh Shahd8ff6322016-09-05 15:55:21 +05309789 (params->ht_capa || params->vht_capa ||
9790 (params->sta_flags_set & BIT(NL80211_STA_FLAG_WME))))
Nitesh Shah99934ac2016-09-05 15:54:08 +05309791 is_qos_wmm_sta = true;
9792
9793 hdd_notice("%s: TDLS Peer is QOS capable"
9794 " is_qos_wmm_sta= %d HTcapPresent = %d",
9795 __func__, is_qos_wmm_sta,
9796 StaParams.htcap_present);
9797
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009798 status = wlan_hdd_tdls_set_peer_caps(pAdapter, mac,
Nitesh Shah99934ac2016-09-05 15:54:08 +05309799 &StaParams,
9800 isBufSta,
9801 isOffChannelSupported,
9802 is_qos_wmm_sta);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309803 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009804 hdd_err("wlan_hdd_tdls_set_peer_caps failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009805 return -EINVAL;
9806 }
9807
9808 status =
9809 wlan_hdd_tdls_add_station(wiphy, dev, mac, 1,
9810 &StaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05309811 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009812 hdd_err("wlan_hdd_tdls_add_station failed!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009813 return -EINVAL;
9814 }
9815 }
9816#endif
9817 }
9818 EXIT();
9819 return ret;
9820}
9821
9822/**
9823 * wlan_hdd_change_station() - cfg80211 change station handler function
9824 * @wiphy: Pointer to the wiphy structure
9825 * @dev: Pointer to the net device.
9826 * @mac: bssid
9827 * @params: Pointer to station parameters
9828 *
9829 * This is the cfg80211 change station handler function which invokes
9830 * the internal function @__wlan_hdd_change_station with
9831 * SSR protection.
9832 *
9833 * Return: 0 for success, error number on failure.
9834 */
9835#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) || defined(WITH_BACKPORTS)
9836static int wlan_hdd_change_station(struct wiphy *wiphy,
9837 struct net_device *dev,
9838 const u8 *mac,
9839 struct station_parameters *params)
9840#else
9841static int wlan_hdd_change_station(struct wiphy *wiphy,
9842 struct net_device *dev,
9843 u8 *mac,
9844 struct station_parameters *params)
9845#endif
9846{
9847 int ret;
9848
9849 cds_ssr_protect(__func__);
9850 ret = __wlan_hdd_change_station(wiphy, dev, mac, params);
9851 cds_ssr_unprotect(__func__);
9852
9853 return ret;
9854}
9855
9856/*
9857 * FUNCTION: __wlan_hdd_cfg80211_add_key
9858 * This function is used to initialize the key information
9859 */
9860static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
9861 struct net_device *ndev,
9862 u8 key_index, bool pairwise,
9863 const u8 *mac_addr,
9864 struct key_params *params)
9865{
9866 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
9867 tCsrRoamSetKey setKey;
9868 int status;
9869 uint32_t roamId = 0xFF;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009870 hdd_hostapd_state_t *pHostapdState;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +05309871 QDF_STATUS qdf_ret_status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009872 hdd_context_t *pHddCtx;
9873 hdd_ap_ctx_t *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
9874
9875 ENTER();
9876
Anurag Chouhan6d760662016-02-20 16:05:43 +05309877 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009878 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009879 return -EINVAL;
9880 }
9881
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05309882 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009883 TRACE_CODE_HDD_CFG80211_ADD_KEY,
9884 pAdapter->sessionId, params->key_len));
9885 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
9886 status = wlan_hdd_validate_context(pHddCtx);
9887
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +05309888 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009889 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009890
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009891 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009892 hdd_device_mode_to_string(pAdapter->device_mode),
9893 pAdapter->device_mode);
9894
9895 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009896 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009897
9898 return -EINVAL;
9899 }
9900
9901 if (CSR_MAX_KEY_LEN < params->key_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009902 hdd_err("Invalid key length %d", params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009903
9904 return -EINVAL;
9905 }
9906
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009907 hdd_notice("called with key index = %d & key length %d", key_index, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009908
9909 /*extract key idx, key len and key */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309910 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009911 setKey.keyId = key_index;
9912 setKey.keyLength = params->key_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309913 qdf_mem_copy(&setKey.Key[0], params->key, params->key_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009914
9915 switch (params->cipher) {
9916 case WLAN_CIPHER_SUITE_WEP40:
9917 setKey.encType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
9918 break;
9919
9920 case WLAN_CIPHER_SUITE_WEP104:
9921 setKey.encType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY;
9922 break;
9923
9924 case WLAN_CIPHER_SUITE_TKIP:
9925 {
9926 u8 *pKey = &setKey.Key[0];
9927 setKey.encType = eCSR_ENCRYPT_TYPE_TKIP;
9928
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309929 qdf_mem_zero(pKey, CSR_MAX_KEY_LEN);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009930
9931 /*Supplicant sends the 32bytes key in this order
9932
9933 |--------------|----------|----------|
9934 | Tk1 |TX-MIC | RX Mic |
9935 |||--------------|----------|----------|
9936 <---16bytes---><--8bytes--><--8bytes-->
9937
9938 */
9939 /*Sme expects the 32 bytes key to be in the below order
9940
9941 |--------------|----------|----------|
9942 | Tk1 |RX-MIC | TX Mic |
9943 |||--------------|----------|----------|
9944 <---16bytes---><--8bytes--><--8bytes-->
9945 */
9946 /* Copy the Temporal Key 1 (TK1) */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309947 qdf_mem_copy(pKey, params->key, 16);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009948
9949 /*Copy the rx mic first */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309950 qdf_mem_copy(&pKey[16], &params->key[24], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009951
9952 /*Copy the tx mic */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309953 qdf_mem_copy(&pKey[24], &params->key[16], 8);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009954
9955 break;
9956 }
9957
9958 case WLAN_CIPHER_SUITE_CCMP:
9959 setKey.encType = eCSR_ENCRYPT_TYPE_AES;
9960 break;
9961
9962#ifdef FEATURE_WLAN_WAPI
9963 case WLAN_CIPHER_SUITE_SMS4:
9964 {
Anurag Chouhan600c3a02016-03-01 10:33:54 +05309965 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009966 wlan_hdd_cfg80211_set_key_wapi(pAdapter, key_index,
9967 mac_addr, params->key,
9968 params->key_len);
9969 return 0;
9970 }
9971#endif
9972
9973#ifdef FEATURE_WLAN_ESE
9974 case WLAN_CIPHER_SUITE_KRK:
9975 setKey.encType = eCSR_ENCRYPT_TYPE_KRK;
9976 break;
9977#ifdef WLAN_FEATURE_ROAM_OFFLOAD
9978 case WLAN_CIPHER_SUITE_BTK:
9979 setKey.encType = eCSR_ENCRYPT_TYPE_BTK;
9980 break;
9981#endif
9982#endif
9983
9984#ifdef WLAN_FEATURE_11W
9985 case WLAN_CIPHER_SUITE_AES_CMAC:
9986 setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC;
9987 break;
9988#endif
9989
9990 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009991 hdd_err("unsupported cipher type %u", params->cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009992 return -EOPNOTSUPP;
9993 }
9994
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009995 hdd_info("encryption type %d", setKey.encType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08009996
9997 if (!pairwise) {
9998 /* set group key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -07009999 hdd_notice("%s- %d: setting Broadcast key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010000 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010001 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010002 } else {
10003 /* set pairwise key */
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010004 hdd_notice("%s- %d: setting pairwise key", __func__, __LINE__);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010005 setKey.keyDirection = eSIR_TX_RX;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010006 qdf_mem_copy(setKey.peerMac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010007 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010008 if ((QDF_IBSS_MODE == pAdapter->device_mode) && !pairwise) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010009 /* if a key is already installed, block all subsequent ones */
10010 if (pAdapter->sessionCtx.station.ibss_enc_key_installed) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010011 hdd_info("IBSS key installed already");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010012 return 0;
10013 }
10014
10015 setKey.keyDirection = eSIR_TX_RX;
10016 /*Set the group key */
10017 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10018 pAdapter->sessionId, &setKey, &roamId);
10019
10020 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010021 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010022 return -EINVAL;
10023 }
10024 /*Save the keys here and call sme_roam_set_key for setting
10025 the PTK after peer joins the IBSS network */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010026 qdf_mem_copy(&pAdapter->sessionCtx.station.ibss_enc_key,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010027 &setKey, sizeof(tCsrRoamSetKey));
10028
10029 pAdapter->sessionCtx.station.ibss_enc_key_installed = 1;
10030 return status;
10031 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010032 if ((pAdapter->device_mode == QDF_SAP_MODE) ||
10033 (pAdapter->device_mode == QDF_P2P_GO_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010034 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
10035 if (pHostapdState->bssState == BSS_START) {
Dustin Brown6ba30a12016-09-13 13:59:43 -070010036 status = wlansap_set_key_sta(
10037 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), &setKey);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010038 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010039 hdd_err("[%4d] wlansap_set_key_sta returned ERROR status= %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010040 __LINE__, status);
10041 }
10042 }
10043
10044 /* Save the key in ap ctx for use on START_BASS and restart */
10045 if (pairwise ||
10046 eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == setKey.encType ||
10047 eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == setKey.encType)
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010048 qdf_mem_copy(&ap_ctx->wepKey[key_index], &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010049 sizeof(tCsrRoamSetKey));
10050 else
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010051 qdf_mem_copy(&ap_ctx->groupKey, &setKey,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010052 sizeof(tCsrRoamSetKey));
10053
Krunal Sonib4326f22016-03-10 13:05:51 -080010054 } else if ((pAdapter->device_mode == QDF_STA_MODE) ||
10055 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010056 hdd_wext_state_t *pWextState =
10057 WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10058 hdd_station_ctx_t *pHddStaCtx =
10059 WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10060
10061 if (!pairwise) {
10062 /* set group key */
10063 if (pHddStaCtx->roam_info.deferKeyComplete) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010064 hdd_notice("%s- %d: Perform Set key Complete",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010065 __func__, __LINE__);
10066 hdd_perform_roam_set_key_complete(pAdapter);
10067 }
10068 }
10069
10070 pWextState->roamProfile.Keys.KeyLength[key_index] =
10071 (u8) params->key_len;
10072
10073 pWextState->roamProfile.Keys.defaultIndex = key_index;
10074
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010075 qdf_mem_copy(&pWextState->roamProfile.Keys.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010076 KeyMaterial[key_index][0], params->key,
10077 params->key_len);
10078
10079 pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY;
10080
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010081 hdd_info("Set key for peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010082 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10083 setKey.keyDirection);
10084
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010085 /* The supplicant may attempt to set the PTK once pre-authentication
10086 is done. Save the key in the UMAC and include it in the ADD BSS
10087 request */
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010088 qdf_ret_status = sme_ft_update_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010089 pAdapter->sessionId, &setKey);
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010090 if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_SUCCESS) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010091 hdd_info("Update PreAuth Key success");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010092 return 0;
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010093 } else if (qdf_ret_status == QDF_STATUS_FT_PREAUTH_KEY_FAILED) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010094 hdd_err("Update PreAuth Key failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010095 return -EINVAL;
10096 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010097
10098 /* issue set key request to SME */
10099 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10100 pAdapter->sessionId, &setKey, &roamId);
10101
10102 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010103 hdd_err("sme_roam_set_key failed, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010104 pHddStaCtx->roam_info.roamingState =
10105 HDD_ROAM_STATE_NONE;
10106 return -EINVAL;
10107 }
10108
10109 /* in case of IBSS as there was no information available about WEP keys during
10110 * IBSS join, group key intialized with NULL key, so re-initialize group key
10111 * with correct value*/
10112 if ((eCSR_BSS_TYPE_START_IBSS ==
10113 pWextState->roamProfile.BSSType)
10114 &&
10115 !((IW_AUTH_KEY_MGMT_802_1X ==
10116 (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X))
10117 && (eCSR_AUTH_TYPE_OPEN_SYSTEM ==
10118 pHddStaCtx->conn_info.authType)
10119 )
10120 && ((WLAN_CIPHER_SUITE_WEP40 == params->cipher)
10121 || (WLAN_CIPHER_SUITE_WEP104 == params->cipher)
10122 )
10123 ) {
10124 setKey.keyDirection = eSIR_RX_ONLY;
Anurag Chouhanc5548422016-02-24 18:33:27 +053010125 qdf_set_macaddr_broadcast(&setKey.peerMac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010126
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010127 hdd_info("Set key peerMac "MAC_ADDRESS_STR" direction %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010128 MAC_ADDR_ARRAY(setKey.peerMac.bytes),
10129 setKey.keyDirection);
10130
10131 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10132 pAdapter->sessionId, &setKey,
10133 &roamId);
10134
10135 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010136 hdd_err("sme_roam_set_key failed for group key (IBSS), returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010137 pHddStaCtx->roam_info.roamingState =
10138 HDD_ROAM_STATE_NONE;
10139 return -EINVAL;
10140 }
10141 }
10142 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010143 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010144 return 0;
10145}
10146
10147static int wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
10148 struct net_device *ndev,
10149 u8 key_index, bool pairwise,
10150 const u8 *mac_addr,
10151 struct key_params *params)
10152{
10153 int ret;
10154 cds_ssr_protect(__func__);
10155 ret = __wlan_hdd_cfg80211_add_key(wiphy, ndev, key_index, pairwise,
10156 mac_addr, params);
10157 cds_ssr_unprotect(__func__);
10158
10159 return ret;
10160}
10161
10162/*
10163 * FUNCTION: __wlan_hdd_cfg80211_get_key
10164 * This function is used to get the key information
10165 */
10166static int __wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10167 struct net_device *ndev,
10168 u8 key_index, bool pairwise,
10169 const u8 *mac_addr, void *cookie,
10170 void (*callback)(void *cookie,
10171 struct key_params *)
10172 )
10173{
10174 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10175 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10176 tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile);
10177 struct key_params params;
10178
10179 ENTER();
10180
Anurag Chouhan6d760662016-02-20 16:05:43 +053010181 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010182 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010183 return -EINVAL;
10184 }
10185
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010186 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010187 hdd_device_mode_to_string(pAdapter->device_mode),
10188 pAdapter->device_mode);
10189
10190 memset(&params, 0, sizeof(params));
10191
10192 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010193 hdd_err("invalid key index %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010194 key_index);
10195 return -EINVAL;
10196 }
10197
10198 switch (pRoamProfile->EncryptionType.encryptionType[0]) {
10199 case eCSR_ENCRYPT_TYPE_NONE:
10200 params.cipher = IW_AUTH_CIPHER_NONE;
10201 break;
10202
10203 case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
10204 case eCSR_ENCRYPT_TYPE_WEP40:
10205 params.cipher = WLAN_CIPHER_SUITE_WEP40;
10206 break;
10207
10208 case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
10209 case eCSR_ENCRYPT_TYPE_WEP104:
10210 params.cipher = WLAN_CIPHER_SUITE_WEP104;
10211 break;
10212
10213 case eCSR_ENCRYPT_TYPE_TKIP:
10214 params.cipher = WLAN_CIPHER_SUITE_TKIP;
10215 break;
10216
10217 case eCSR_ENCRYPT_TYPE_AES:
10218 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
10219 break;
10220
10221 default:
10222 params.cipher = IW_AUTH_CIPHER_NONE;
10223 break;
10224 }
10225
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010226 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010227 TRACE_CODE_HDD_CFG80211_GET_KEY,
10228 pAdapter->sessionId, params.cipher));
10229
10230 params.key_len = pRoamProfile->Keys.KeyLength[key_index];
10231 params.seq_len = 0;
10232 params.seq = NULL;
10233 params.key = &pRoamProfile->Keys.KeyMaterial[key_index][0];
10234 callback(cookie, &params);
10235
10236 EXIT();
10237 return 0;
10238}
10239
10240static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
10241 struct net_device *ndev,
10242 u8 key_index, bool pairwise,
10243 const u8 *mac_addr, void *cookie,
10244 void (*callback)(void *cookie,
10245 struct key_params *)
10246 )
10247{
10248 int ret;
10249
10250 cds_ssr_protect(__func__);
10251 ret = __wlan_hdd_cfg80211_get_key(wiphy, ndev, key_index, pairwise,
10252 mac_addr, cookie, callback);
10253 cds_ssr_unprotect(__func__);
10254
10255 return ret;
10256}
10257
10258/**
10259 * __wlan_hdd_cfg80211_del_key() - Delete the encryption key for station
10260 * @wiphy: wiphy interface context
10261 * @ndev: pointer to net device
10262 * @key_index: Key index used in 802.11 frames
10263 * @unicast: true if it is unicast key
10264 * @multicast: true if it is multicast key
10265 *
10266 * This function is required for cfg80211_ops API.
10267 * It is used to delete the key information
10268 * Underlying hardware implementation does not have API to delete the
10269 * encryption key. It is automatically deleted when the peer is
10270 * removed. Hence this function currently does nothing.
10271 * Future implementation may interprete delete key operation to
10272 * replacing the key with a random junk value, effectively making it
10273 * useless.
10274 *
10275 * Return: status code, always 0.
10276 */
10277
10278static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10279 struct net_device *ndev,
10280 u8 key_index,
10281 bool pairwise, const u8 *mac_addr)
10282{
10283 EXIT();
10284 return 0;
10285}
10286
10287/**
10288 * wlan_hdd_cfg80211_del_key() - cfg80211 delete key handler function
10289 * @wiphy: Pointer to wiphy structure.
10290 * @dev: Pointer to net_device structure.
10291 * @key_index: key index
10292 * @pairwise: pairwise
10293 * @mac_addr: mac address
10294 *
10295 * This is the cfg80211 delete key handler function which invokes
10296 * the internal function @__wlan_hdd_cfg80211_del_key with
10297 * SSR protection.
10298 *
10299 * Return: 0 for success, error number on failure.
10300 */
10301static int wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
10302 struct net_device *dev,
10303 u8 key_index,
10304 bool pairwise, const u8 *mac_addr)
10305{
10306 int ret;
10307
10308 cds_ssr_protect(__func__);
10309 ret = __wlan_hdd_cfg80211_del_key(wiphy, dev, key_index,
10310 pairwise, mac_addr);
10311 cds_ssr_unprotect(__func__);
10312
10313 return ret;
10314}
10315
10316/*
10317 * FUNCTION: __wlan_hdd_cfg80211_set_default_key
10318 * This function is used to set the default tx key index
10319 */
10320static int __wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10321 struct net_device *ndev,
10322 u8 key_index,
10323 bool unicast, bool multicast)
10324{
10325 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
10326 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
10327 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
10328 hdd_context_t *pHddCtx;
10329 int status;
10330
10331 ENTER();
10332
Anurag Chouhan6d760662016-02-20 16:05:43 +053010333 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010334 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010335 return -EINVAL;
10336 }
10337
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010338 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010339 TRACE_CODE_HDD_CFG80211_SET_DEFAULT_KEY,
10340 pAdapter->sessionId, key_index));
10341
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010342 hdd_notice("Device_mode %s(%d) key_index = %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010343 hdd_device_mode_to_string(pAdapter->device_mode),
10344 pAdapter->device_mode, key_index);
10345
10346 if (CSR_MAX_NUM_KEY <= key_index) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010347 hdd_err("Invalid key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010348 return -EINVAL;
10349 }
10350
10351 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10352 status = wlan_hdd_validate_context(pHddCtx);
10353
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010354 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010355 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010356
Krunal Sonib4326f22016-03-10 13:05:51 -080010357 if ((pAdapter->device_mode == QDF_STA_MODE) ||
10358 (pAdapter->device_mode == QDF_P2P_CLIENT_MODE)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010359 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10360 pHddStaCtx->conn_info.ucEncryptionType) &&
10361 (eCSR_ENCRYPT_TYPE_AES !=
10362 pHddStaCtx->conn_info.ucEncryptionType)) {
10363 /* If default key index is not same as previous one,
10364 * then update the default key index */
10365
10366 tCsrRoamSetKey setKey;
10367 uint32_t roamId = 0xFF;
10368 tCsrKeys *Keys = &pWextState->roamProfile.Keys;
10369
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010370 hdd_info("Default tx key index %d", key_index);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010371
10372 Keys->defaultIndex = (u8) key_index;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010373 qdf_mem_zero(&setKey, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010374 setKey.keyId = key_index;
10375 setKey.keyLength = Keys->KeyLength[key_index];
10376
Anurag Chouhan600c3a02016-03-01 10:33:54 +053010377 qdf_mem_copy(&setKey.Key[0],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010378 &Keys->KeyMaterial[key_index][0],
10379 Keys->KeyLength[key_index]);
10380
10381 setKey.keyDirection = eSIR_TX_RX;
10382
Anurag Chouhanc5548422016-02-24 18:33:27 +053010383 qdf_copy_macaddr(&setKey.peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010384 &pHddStaCtx->conn_info.bssId);
10385
10386 if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN &&
10387 pWextState->roamProfile.EncryptionType.
10388 encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104) {
10389 /* In the case of dynamic wep supplicant hardcodes DWEP type
10390 * to eCSR_ENCRYPT_TYPE_WEP104 even though ap is configured for
10391 * WEP-40 encryption. In this canse the key length is 5 but the
10392 * encryption type is 104 hence checking the key langht(5) and
10393 * encryption type(104) and switching encryption type to 40*/
10394 pWextState->roamProfile.EncryptionType.
10395 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10396 pWextState->roamProfile.mcEncryptionType.
10397 encryptionType[0] = eCSR_ENCRYPT_TYPE_WEP40;
10398 }
10399
10400 setKey.encType =
10401 pWextState->roamProfile.EncryptionType.
10402 encryptionType[0];
10403
10404 /* Issue set key request */
10405 status = sme_roam_set_key(WLAN_HDD_GET_HAL_CTX(pAdapter),
10406 pAdapter->sessionId, &setKey,
10407 &roamId);
10408
10409 if (0 != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010410 hdd_err("sme_roam_set_key failed, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010411 status);
10412 return -EINVAL;
10413 }
10414 }
Krunal Sonib4326f22016-03-10 13:05:51 -080010415 } else if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010416 /* In SoftAp mode setting key direction for default mode */
10417 if ((eCSR_ENCRYPT_TYPE_TKIP !=
10418 pWextState->roamProfile.EncryptionType.encryptionType[0])
10419 && (eCSR_ENCRYPT_TYPE_AES !=
10420 pWextState->roamProfile.EncryptionType.
10421 encryptionType[0])) {
10422 /* Saving key direction for default key index to TX default */
10423 hdd_ap_ctx_t *pAPCtx =
10424 WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
10425 pAPCtx->wepKey[key_index].keyDirection =
10426 eSIR_TX_DEFAULT;
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010427 hdd_info("WEP default key index set to SAP context %d",
Masti, Narayanraddiab712a72016-08-04 11:59:11 +053010428 key_index);
Kondabattini, Ganesh702d90e2016-09-03 01:54:22 +053010429 pAPCtx->wep_def_key_idx = key_index;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010430 }
10431 }
10432
10433 EXIT();
10434 return status;
10435}
10436
10437static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
10438 struct net_device *ndev,
10439 u8 key_index,
10440 bool unicast, bool multicast)
10441{
10442 int ret;
10443 cds_ssr_protect(__func__);
10444 ret =
10445 __wlan_hdd_cfg80211_set_default_key(wiphy, ndev, key_index, unicast,
10446 multicast);
10447 cds_ssr_unprotect(__func__);
10448
10449 return ret;
10450}
10451
Abhishek Singhc9941602016-08-09 16:06:22 +053010452/*
10453 * wlan_hdd_cfg80211_get_bss :to get the bss from kernel cache.
10454 * @wiphy: wiphy pointer
10455 * @channel: channel of the BSS
10456 * @bssid: Bssid of BSS
10457 * @ssid: Ssid of the BSS
10458 * @ssid_len: ssid length
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010459 *
Abhishek Singhc9941602016-08-09 16:06:22 +053010460 * Return: bss found in kernel cache
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010461 */
Abhishek Singhc9941602016-08-09 16:06:22 +053010462#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010463static
Abhishek Singhc9941602016-08-09 16:06:22 +053010464struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10465 struct ieee80211_channel *channel, const u8 *bssid,
10466 const u8 *ssid, size_t ssid_len)
10467{
10468 return cfg80211_get_bss(wiphy, channel, bssid,
10469 ssid,
10470 ssid_len,
10471 WLAN_CAPABILITY_ESS,
10472 WLAN_CAPABILITY_ESS);
10473}
10474#else
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070010475static
Abhishek Singhc9941602016-08-09 16:06:22 +053010476struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
10477 struct ieee80211_channel *channel, const u8 *bssid,
10478 const u8 *ssid, size_t ssid_len)
10479{
10480 return cfg80211_get_bss(wiphy, channel, bssid,
10481 ssid,
10482 ssid_len,
10483 IEEE80211_BSS_TYPE_ESS,
10484 IEEE80211_PRIVACY_ANY);
10485}
10486#endif
10487
10488
10489/*
10490 * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
10491 * interface that BSS might have been lost.
10492 * @pAdapter: adaptor
10493 * @bssid: bssid which might have been lost
10494 *
10495 * Return: bss which is unlinked from kernel cache
10496 */
10497struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
10498 hdd_adapter_t *pAdapter, tSirMacAddr bssid)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010499{
10500 struct net_device *dev = pAdapter->dev;
10501 struct wireless_dev *wdev = dev->ieee80211_ptr;
10502 struct wiphy *wiphy = wdev->wiphy;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010503 struct cfg80211_bss *bss = NULL;
10504
Abhishek Singhc9941602016-08-09 16:06:22 +053010505 bss = wlan_hdd_cfg80211_get_bss(wiphy, NULL, bssid,
10506 NULL, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010507 if (bss == NULL) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010508 hdd_err("BSS not present");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010509 } else {
Abhishek Singhc9941602016-08-09 16:06:22 +053010510 hdd_info("cfg80211_unlink_bss called for BSSID "
10511 MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010512 cfg80211_unlink_bss(wiphy, bss);
10513 }
10514 return bss;
10515}
10516
Abhishek Singhc9941602016-08-09 16:06:22 +053010517
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010518/**
10519 * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
10520 * @pAdapter: Pointer to adapter
10521 * @bss_desc: Pointer to bss descriptor
10522 *
10523 * This function is used to inform the BSS details to nl80211 interface.
10524 *
10525 * Return: struct cfg80211_bss pointer
10526 */
Selvaraj, Sridharfe696d22016-08-03 21:34:51 +053010527struct cfg80211_bss *wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter,
10528 tSirBssDescription *bss_desc)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010529{
10530 /*
10531 * cfg80211_inform_bss() is not updating ie field of bss entry, if entry
10532 * already exists in bss data base of cfg80211 for that particular BSS
10533 * ID. Using cfg80211_inform_bss_frame to update the bss entry instead
10534 * of cfg80211_inform_bss, But this call expects mgmt packet as input.
10535 * As of now there is no possibility to get the mgmt(probe response)
10536 * frame from PE, converting bss_desc to ieee80211_mgmt(probe response)
10537 * and passing to cfg80211_inform_bss_frame.
10538 */
10539 struct net_device *dev = pAdapter->dev;
10540 struct wireless_dev *wdev = dev->ieee80211_ptr;
10541 struct wiphy *wiphy = wdev->wiphy;
10542 int chan_no = bss_desc->channelId;
10543#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10544 qcom_ie_age *qie_age = NULL;
10545 int ie_length =
10546 GET_IE_LEN_IN_BSS_DESC(bss_desc->length) + sizeof(qcom_ie_age);
10547#else
10548 int ie_length = GET_IE_LEN_IN_BSS_DESC(bss_desc->length);
10549#endif
10550 const char *ie =
10551 ((ie_length != 0) ? (const char *)&bss_desc->ieFields : NULL);
10552 unsigned int freq;
10553 struct ieee80211_channel *chan;
10554 struct ieee80211_mgmt *mgmt = NULL;
10555 struct cfg80211_bss *bss_status = NULL;
10556 size_t frame_len = sizeof(struct ieee80211_mgmt) + ie_length;
10557 int rssi = 0;
10558 hdd_context_t *pHddCtx;
10559 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010560 struct timespec ts;
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010561 struct hdd_config *cfg_param;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010562
10563 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10564 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010565 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010566 return NULL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010567
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010568 cfg_param = pHddCtx->config;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010569 mgmt = kzalloc((sizeof(struct ieee80211_mgmt) + ie_length), GFP_KERNEL);
10570 if (!mgmt) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010571 hdd_err("memory allocation failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010572 return NULL;
10573 }
10574
10575 memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN);
10576
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010577 /* Android does not want the timestamp from the frame.
10578 Instead it wants a monotonic increasing value */
Yuanyuan Liu2e03b412016-04-06 14:36:15 -070010579 get_monotonic_boottime(&ts);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010580 mgmt->u.probe_resp.timestamp =
10581 ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010582
10583 mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval;
10584 mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo;
10585
10586#ifdef WLAN_ENABLE_AGEIE_ON_SCAN_RESULTS
10587 /* GPS Requirement: need age ie per entry. Using vendor specific. */
10588 /* Assuming this is the last IE, copy at the end */
10589 ie_length -= sizeof(qcom_ie_age);
10590 qie_age = (qcom_ie_age *) (mgmt->u.probe_resp.variable + ie_length);
10591 qie_age->element_id = QCOM_VENDOR_IE_ID;
10592 qie_age->len = QCOM_VENDOR_IE_AGE_LEN;
10593 qie_age->oui_1 = QCOM_OUI1;
10594 qie_age->oui_2 = QCOM_OUI2;
10595 qie_age->oui_3 = QCOM_OUI3;
10596 qie_age->type = QCOM_VENDOR_IE_AGE_TYPE;
10597 qie_age->age =
Anurag Chouhan210db072016-02-22 18:42:15 +053010598 qdf_mc_timer_get_system_ticks() - bss_desc->nReceivedTime;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010599 qie_age->tsf_delta = bss_desc->tsf_delta;
Krishna Kumaar Natarajana4e12242016-04-01 18:44:39 -070010600 memcpy(&qie_age->beacon_tsf, bss_desc->timeStamp,
10601 sizeof(qie_age->beacon_tsf));
Krishna Kumaar Natarajan89a99d42016-08-04 15:44:38 -070010602 memcpy(&qie_age->seq_ctrl, &bss_desc->seq_ctrl,
10603 sizeof(qie_age->seq_ctrl));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010604#endif
10605
10606 memcpy(mgmt->u.probe_resp.variable, ie, ie_length);
10607 if (bss_desc->fProbeRsp) {
10608 mgmt->frame_control |=
10609 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
10610 } else {
10611 mgmt->frame_control |=
10612 (u16) (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
10613 }
10614
10615 if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz) &&
10616 (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL)) {
10617 freq =
10618 ieee80211_channel_to_frequency(chan_no,
10619 IEEE80211_BAND_2GHZ);
10620 } else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_ghz))
10621 && (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL)) {
10622 freq =
10623 ieee80211_channel_to_frequency(chan_no,
10624 IEEE80211_BAND_5GHZ);
10625 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010626 hdd_err("Invalid chan_no %d", chan_no);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010627 kfree(mgmt);
10628 return NULL;
10629 }
10630
10631 chan = __ieee80211_get_channel(wiphy, freq);
10632 /* When the band is changed on the fly using the GUI, three things are done
10633 * 1. scan abort
10634 * 2. flush scan results from cache
10635 * 3. update the band with the new band user specified (refer to the
10636 * hdd_set_band_helper function) as part of the scan abort, message will be
10637 * queued to PE and we proceed with flushing and changinh the band.
10638 * PE will stop the scanning further and report back the results what ever
10639 * it had till now by calling the call back function.
10640 * if the time between update band and scandone call back is sufficient
10641 * enough the band change reflects in SME, SME validates the channels
10642 * and discards the channels correponding to previous band and calls back
10643 * with zero bss results. but if the time between band update and scan done
10644 * callback is very small then band change will not reflect in SME and SME
10645 * reports to HDD all the channels correponding to previous band.this is due
10646 * to race condition.but those channels are invalid to the new band and so
10647 * this function __ieee80211_get_channel will return NULL.Each time we
10648 * report scan result with this pointer null warning kernel trace is printed.
10649 * if the scan results contain large number of APs continuosly kernel
10650 * warning trace is printed and it will lead to apps watch dog bark.
10651 * So drop the bss and continue to next bss.
10652 */
10653 if (chan == NULL) {
Deepthi Gowri084c24d2016-09-01 15:55:09 +053010654 hdd_err("chan pointer is NULL, chan_no: %d freq: %d",
10655 chan_no, freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010656 kfree(mgmt);
10657 return NULL;
10658 }
10659
Deepak Dhamdhere68929ec2015-08-05 15:16:35 -070010660 /* Based on .ini configuration, raw rssi can be reported for bss.
10661 * Raw rssi is typically used for estimating power.
10662 */
10663
10664 rssi = (cfg_param->inform_bss_rssi_raw) ? bss_desc->rssi_raw :
10665 bss_desc->rssi;
10666
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010667 /* Supplicant takes the signal strength in terms of mBm(100*dBm) */
Anurag Chouhan6d760662016-02-20 16:05:43 +053010668 rssi = QDF_MIN(rssi, 0) * 100;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010669
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010670 hdd_notice("BSSID: " MAC_ADDRESS_STR " Channel:%d RSSI:%d TSF %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010671 MAC_ADDR_ARRAY(mgmt->bssid), chan->center_freq,
Sandeep Puligilla394da5d2016-05-06 01:26:29 -070010672 (int)(rssi / 100),
10673 bss_desc->timeStamp[0]);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010674
10675 bss_status =
10676 cfg80211_inform_bss_frame(wiphy, chan, mgmt, frame_len, rssi,
10677 GFP_KERNEL);
10678 kfree(mgmt);
10679 return bss_status;
10680}
10681
10682/**
10683 * wlan_hdd_cfg80211_update_bss_db() - update bss database of CF80211
10684 * @pAdapter: Pointer to adapter
10685 * @pRoamInfo: Pointer to roam info
10686 *
10687 * This function is used to update the BSS data base of CFG8011
10688 *
10689 * Return: struct cfg80211_bss pointer
10690 */
10691struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_db(hdd_adapter_t *pAdapter,
10692 tCsrRoamInfo *pRoamInfo)
10693{
10694 tCsrRoamConnectedProfile roamProfile;
10695 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10696 struct cfg80211_bss *bss = NULL;
10697
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010698 memset(&roamProfile, 0, sizeof(tCsrRoamConnectedProfile));
10699 sme_roam_get_connect_profile(hHal, pAdapter->sessionId, &roamProfile);
10700
10701 if (NULL != roamProfile.pBssDesc) {
10702 bss = wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10703 roamProfile.pBssDesc);
10704
10705 if (NULL == bss)
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010706 hdd_notice("wlan_hdd_cfg80211_inform_bss_frame returned NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010707
Naveen Rawatdf0a7e72016-01-06 18:35:53 -080010708 sme_roam_free_connect_profile(&roamProfile);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010709 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010710 hdd_err("roamProfile.pBssDesc is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010711 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010712 return bss;
10713}
10714/**
10715 * wlan_hdd_cfg80211_update_bss() - update bss
10716 * @wiphy: Pointer to wiphy
10717 * @pAdapter: Pointer to adapter
10718 * @scan_time: scan request timestamp
10719 *
10720 * Return: zero if success, non-zero otherwise
10721 */
10722int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
10723 hdd_adapter_t *pAdapter,
10724 uint32_t scan_time)
10725{
10726 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
10727 tCsrScanResultInfo *pScanResult;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010728 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010729 tScanResultHandle pResult;
10730 struct cfg80211_bss *bss_status = NULL;
10731 hdd_context_t *pHddCtx;
10732 int ret;
10733
10734 ENTER();
10735
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053010736 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010737 TRACE_CODE_HDD_CFG80211_UPDATE_BSS,
10738 NO_SESSION, pAdapter->sessionId));
10739
10740 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
10741 ret = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053010742 if (0 != ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010743 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010744
10745 /* start getting scan results and populate cgf80211 BSS database */
10746 status = sme_scan_get_result(hHal, pAdapter->sessionId, NULL, &pResult);
10747
10748 /* no scan results */
10749 if (NULL == pResult) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010750 hdd_err("No scan result Status %d", status);
Kapil Gupta0ed58dc2016-04-22 15:35:26 +053010751 return -EAGAIN;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010752 }
10753
10754 pScanResult = sme_scan_result_get_first(hHal, pResult);
10755
10756 while (pScanResult) {
10757 /*
10758 * - cfg80211_inform_bss() is not updating ie field of bss
10759 * entry if entry already exists in bss data base of cfg80211
10760 * for that particular BSS ID. Using cfg80211_inform_bss_frame
10761 * to update thebss entry instead of cfg80211_inform_bss,
10762 * But this call expects mgmt packet as input. As of now
10763 * there is no possibility to get the mgmt(probe response)
10764 * frame from PE, converting bss_desc to
10765 * ieee80211_mgmt(probe response) and passing to c
10766 * fg80211_inform_bss_frame.
10767 * - Update BSS only if beacon timestamp is later than
10768 * scan request timestamp.
10769 */
10770 if ((scan_time == 0) ||
10771 (scan_time <
10772 pScanResult->BssDescriptor.nReceivedTime)) {
10773 bss_status =
10774 wlan_hdd_cfg80211_inform_bss_frame(pAdapter,
10775 &pScanResult->BssDescriptor);
10776
10777 if (NULL == bss_status) {
10778 hdd_info("NULL returned by cfg80211_inform_bss_frame");
10779 } else {
10780 cfg80211_put_bss(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010781 wiphy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010782 bss_status);
10783 }
10784 } else {
10785 hdd_info("BSSID: " MAC_ADDRESS_STR " Skipped",
10786 MAC_ADDR_ARRAY(pScanResult->BssDescriptor.bssId));
10787 }
10788 pScanResult = sme_scan_result_get_next(hHal, pResult);
10789 }
10790
10791 sme_scan_result_purge(hHal, pResult);
10792 /*
10793 * For SAP mode, scan is invoked by hostapd during SAP start
10794 * if hostapd is restarted, we need to flush previous scan
10795 * result so that it will reflect environment change
10796 */
Krunal Sonib4326f22016-03-10 13:05:51 -080010797 if (pAdapter->device_mode == QDF_SAP_MODE
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010798#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
10799 && pHddCtx->skip_acs_scan_status != eSAP_SKIP_ACS_SCAN
10800#endif
10801 )
10802 sme_scan_flush_result(hHal);
10803
10804 EXIT();
10805 return 0;
10806}
10807
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010808/**
10809 * wlan_hdd_cfg80211_pmksa_candidate_notify() - notify a new PMSKA candidate
10810 * @pAdapter: Pointer to adapter
10811 * @pRoamInfo: Pointer to roam info
10812 * @index: Index
10813 * @preauth: Preauth flag
10814 *
10815 * This function is used to notify the supplicant of a new PMKSA candidate.
10816 *
10817 * Return: 0 for success, non-zero for failure
10818 */
10819int wlan_hdd_cfg80211_pmksa_candidate_notify(hdd_adapter_t *pAdapter,
10820 tCsrRoamInfo *pRoamInfo,
10821 int index, bool preauth)
10822{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010823 struct net_device *dev = pAdapter->dev;
10824 hdd_context_t *pHddCtx = (hdd_context_t *) pAdapter->pHddCtx;
10825
10826 ENTER();
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010827 hdd_notice("is going to notify supplicant of:");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010828
10829 if (NULL == pRoamInfo) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010830 hdd_alert("pRoamInfo is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010831 return -EINVAL;
10832 }
10833
10834 if (true == hdd_is_okc_mode_enabled(pHddCtx)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010835 hdd_notice(MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010836 MAC_ADDR_ARRAY(pRoamInfo->bssid.bytes));
10837 cfg80211_pmksa_candidate_notify(dev, index,
10838 pRoamInfo->bssid.bytes,
10839 preauth, GFP_KERNEL);
10840 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010841 return 0;
10842}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010843
10844#ifdef FEATURE_WLAN_LFR_METRICS
10845/**
10846 * wlan_hdd_cfg80211_roam_metrics_preauth() - roam metrics preauth
10847 * @pAdapter: Pointer to adapter
10848 * @pRoamInfo: Pointer to roam info
10849 *
10850 * 802.11r/LFR metrics reporting function to report preauth initiation
10851 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010852 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010853 */
10854#define MAX_LFR_METRICS_EVENT_LENGTH 100
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010855QDF_STATUS wlan_hdd_cfg80211_roam_metrics_preauth(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010856 tCsrRoamInfo *pRoamInfo)
10857{
10858 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10859 union iwreq_data wrqu;
10860
10861 ENTER();
10862
10863 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010864 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010865 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010866 }
10867
10868 /* create the event */
10869 memset(&wrqu, 0, sizeof(wrqu));
10870 memset(metrics_notification, 0, sizeof(metrics_notification));
10871
10872 wrqu.data.pointer = metrics_notification;
10873 wrqu.data.length = scnprintf(metrics_notification,
10874 sizeof(metrics_notification),
10875 "QCOM: LFR_PREAUTH_INIT " MAC_ADDRESS_STR,
10876 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10877
10878 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10879 metrics_notification);
10880
10881 EXIT();
10882
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010883 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010884}
10885
10886/**
10887 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
10888 * @pAdapter: Pointer to adapter
10889 * @pRoamInfo: Pointer to roam info
10890 * @preauth_status: Preauth status
10891 *
10892 * 802.11r/LFR metrics reporting function to report handover initiation
10893 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010894 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010895 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010896QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010897wlan_hdd_cfg80211_roam_metrics_preauth_status(hdd_adapter_t *pAdapter,
10898 tCsrRoamInfo *pRoamInfo,
10899 bool preauth_status)
10900{
10901 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10902 union iwreq_data wrqu;
10903
10904 ENTER();
10905
10906 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010907 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010908 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010909 }
10910
10911 /* create the event */
10912 memset(&wrqu, 0, sizeof(wrqu));
10913 memset(metrics_notification, 0, sizeof(metrics_notification));
10914
10915 scnprintf(metrics_notification, sizeof(metrics_notification),
10916 "QCOM: LFR_PREAUTH_STATUS " MAC_ADDRESS_STR,
10917 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10918
10919 if (1 == preauth_status)
10920 strlcat(metrics_notification, " true",
10921 sizeof(metrics_notification));
10922 else
10923 strlcat(metrics_notification, " false",
10924 sizeof(metrics_notification));
10925
10926 wrqu.data.pointer = metrics_notification;
10927 wrqu.data.length = strlen(metrics_notification);
10928
10929 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10930 metrics_notification);
10931
10932 EXIT();
10933
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010934 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010935}
10936
10937/**
10938 * wlan_hdd_cfg80211_roam_metrics_handover() - roam metrics hand over
10939 * @pAdapter: Pointer to adapter
10940 * @pRoamInfo: Pointer to roam info
10941 *
10942 * 802.11r/LFR metrics reporting function to report handover initiation
10943 *
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053010944 * Return: QDF status
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010945 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010946QDF_STATUS wlan_hdd_cfg80211_roam_metrics_handover(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010947 tCsrRoamInfo *pRoamInfo)
10948{
10949 unsigned char metrics_notification[MAX_LFR_METRICS_EVENT_LENGTH + 1];
10950 union iwreq_data wrqu;
10951
10952 ENTER();
10953
10954 if (NULL == pAdapter) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070010955 hdd_err("pAdapter is NULL!");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010956 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010957 }
10958
10959 /* create the event */
10960 memset(&wrqu, 0, sizeof(wrqu));
10961 memset(metrics_notification, 0, sizeof(metrics_notification));
10962
10963 wrqu.data.pointer = metrics_notification;
10964 wrqu.data.length = scnprintf(metrics_notification,
10965 sizeof(metrics_notification),
10966 "QCOM: LFR_PREAUTH_HANDOVER "
10967 MAC_ADDRESS_STR,
10968 MAC_ADDR_ARRAY(pRoamInfo->bssid));
10969
10970 wireless_send_event(pAdapter->dev, IWEVCUSTOM, &wrqu,
10971 metrics_notification);
10972
10973 EXIT();
10974
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053010975 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010976}
10977#endif
10978
10979/**
10980 * hdd_select_cbmode() - select channel bonding mode
10981 * @pAdapter: Pointer to adapter
10982 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010983 * @ch_params: channel info struct to populate
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010984 *
10985 * Return: none
10986 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010987void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel,
10988 struct ch_params_s *ch_params)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080010989{
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010990 hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010991 struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070010992 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070010993
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070010994 /*
10995 * CDS api expects secondary channel for calculating
10996 * the channel params
10997 */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070010998 if ((ch_params->ch_width == CH_WIDTH_40MHZ) &&
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070010999 (CDS_IS_CHANNEL_24GHZ(operationChannel))) {
11000 if (operationChannel >= 1 && operationChannel <= 5)
11001 sec_ch = operationChannel + 4;
11002 else if (operationChannel >= 6 && operationChannel <= 13)
11003 sec_ch = operationChannel - 4;
11004 }
11005
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011006 /* This call decides required channel bonding mode */
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011007 cds_set_channel_params(operationChannel, sec_ch, ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011008
11009 if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) {
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011010 eHddDot11Mode hdd_dot11_mode;
11011 uint8_t iniDot11Mode =
11012 (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode;
11013
11014 hdd_notice("Dot11Mode is %u", iniDot11Mode);
11015 switch (iniDot11Mode) {
11016 case eHDD_DOT11_MODE_AUTO:
11017 case eHDD_DOT11_MODE_11ac:
11018 case eHDD_DOT11_MODE_11ac_ONLY:
11019 if (sme_is_feature_supported_by_fw(DOT11AC))
11020 hdd_dot11_mode = eHDD_DOT11_MODE_11ac;
11021 else
11022 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11023 break;
11024 case eHDD_DOT11_MODE_11n:
11025 case eHDD_DOT11_MODE_11n_ONLY:
11026 hdd_dot11_mode = eHDD_DOT11_MODE_11n;
11027 break;
11028 default:
11029 hdd_dot11_mode = iniDot11Mode;
11030 break;
11031 }
11032 ch_info->channel_width = ch_params->ch_width;
11033 ch_info->phy_mode =
11034 hdd_cfg_xlate_to_csr_phy_mode(hdd_dot11_mode);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011035 ch_info->channel = operationChannel;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011036 ch_info->cb_mode = ch_params->ch_width;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070011037 hdd_info("ch_info width %d, phymode %d channel %d",
11038 ch_info->channel_width, ch_info->phy_mode,
11039 ch_info->channel);
11040 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011041}
11042
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011043/**
11044 * wlan_hdd_handle_sap_sta_dfs_conc() - to handle SAP STA DFS conc
11045 * @adapter: STA adapter
11046 * @roam_profile: STA roam profile
11047 *
11048 * This routine will move SAP from dfs to non-dfs, if sta is coming up.
11049 *
11050 * Return: false if sta-sap conc is not allowed, else return true
11051 */
11052static bool wlan_hdd_handle_sap_sta_dfs_conc(hdd_adapter_t *adapter,
11053 tCsrRoamProfile *roam_profile)
11054{
11055 hdd_context_t *hdd_ctx;
11056 hdd_adapter_t *ap_adapter;
11057 hdd_ap_ctx_t *hdd_ap_ctx;
11058 hdd_hostapd_state_t *hostapd_state;
11059 uint8_t channel = 0;
11060 QDF_STATUS status;
11061
11062 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
11063 if (!hdd_ctx) {
11064 hdd_err("HDD context is NULL");
11065 return true;
11066 }
11067
11068 ap_adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
11069 /* probably no sap running, no handling required */
11070 if (ap_adapter == NULL)
11071 return true;
11072
11073 /*
11074 * sap is not in started state, so it is fine to go ahead with sta.
11075 * if sap is currently doing CAC then don't allow sta to go further.
11076 */
11077 if (!test_bit(SOFTAP_BSS_STARTED, &(ap_adapter)->event_flags) &&
11078 (hdd_ctx->dev_dfs_cac_status != DFS_CAC_IN_PROGRESS))
11079 return true;
11080
11081 if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS) {
11082 hdd_err("Concurrent SAP is in CAC state, STA is not allowed");
11083 return false;
11084 }
11085
11086 /*
11087 * log and return error, if we allow STA to go through, we don't
11088 * know what is going to happen better stop sta connection
11089 */
11090 hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(ap_adapter);
11091 if (NULL == hdd_ap_ctx) {
11092 hdd_err("AP context not found");
11093 return false;
11094 }
11095
11096 /* sap is on non-dfs channel, nothing to handle */
11097 if (!CDS_IS_DFS_CH(hdd_ap_ctx->operatingChannel)) {
11098 hdd_info("sap is on non-dfs channel, sta is allowed");
11099 return true;
11100 }
11101 /*
11102 * find out by looking in to scan cache where sta is going to
Nitesh Shah59774522016-09-16 15:14:21 +053011103 * connect by passing its roam_profile.
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011104 */
11105 status = cds_get_channel_from_scan_result(adapter,
11106 roam_profile, &channel);
11107
Nitesh Shah59774522016-09-16 15:14:21 +053011108 /*
11109 * If the STA's channel is 2.4 GHz, then set pcl with only 2.4 GHz
11110 * channels for roaming case.
11111 */
11112 if (CDS_IS_CHANNEL_24GHZ(channel)) {
11113 hdd_info("sap is on dfs, new sta conn on 2.4 is allowed");
11114 return true;
11115 }
11116
11117 /*
11118 * If channel is 0 or DFS then better to call pcl and find out the
11119 * best channel. If channel is non-dfs 5 GHz then better move SAP
11120 * to STA's channel to make scc, so we have room for 3port MCC
11121 * scenario.
11122 */
11123 if ((0 == channel) || CDS_IS_DFS_CH(channel))
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011124 channel = cds_get_nondfs_preferred_channel(CDS_SAP_MODE,
11125 true);
11126
11127 hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
11128 qdf_event_reset(&hostapd_state->qdf_event);
11129 status = wlansap_set_channel_change_with_csa(
11130 WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
11131 hdd_ap_ctx->sapConfig.ch_width_orig);
11132
11133 if (QDF_STATUS_SUCCESS != status) {
11134 hdd_err("Set channel with CSA IE failed, can't allow STA");
11135 return false;
11136 }
11137
11138 /*
11139 * wait here for SAP to finish the channel switch. When channel
11140 * switch happens, SAP sends few beacons with CSA_IE. After
11141 * successfully Transmission of those beacons, it will move its
11142 * state from started to disconnected and move to new channel.
11143 * once it moves to new channel, sap again moves its state
11144 * machine from disconnected to started and set this event.
11145 * wait for 10 secs to finish this.
11146 */
11147 status = qdf_wait_single_event(&hostapd_state->qdf_event, 10000);
11148 if (!QDF_IS_STATUS_SUCCESS(status)) {
11149 hdd_err("wait for qdf_event failed, STA not allowed!!");
11150 return false;
11151 }
11152
11153 return true;
11154}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011155
Krunal Soni31949422016-07-29 17:17:53 -070011156/**
11157 * wlan_hdd_cfg80211_connect_start() - to start the association process
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011158 * @pAdapter: Pointer to adapter
Krunal Soni31949422016-07-29 17:17:53 -070011159 * @ssid: Pointer to ssid
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011160 * @ssid_len: Length of ssid
11161 * @bssid: Pointer to bssid
Krunal Soni31949422016-07-29 17:17:53 -070011162 * @bssid_hint: Pointer to bssid hint
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011163 * @operatingChannel: Operating channel
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011164 * @ch_width: channel width. this is needed only for IBSS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011165 *
11166 * This function is used to start the association process
11167 *
11168 * Return: 0 for success, non-zero for failure
11169 */
Krunal Soni31949422016-07-29 17:17:53 -070011170static int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011171 const u8 *ssid, size_t ssid_len,
Krunal Soni31949422016-07-29 17:17:53 -070011172 const u8 *bssid, const u8 *bssid_hint,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011173 u8 operatingChannel,
11174 enum nl80211_chan_width ch_width)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011175{
11176 int status = 0;
11177 hdd_wext_state_t *pWextState;
11178 hdd_context_t *pHddCtx;
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011179 hdd_station_ctx_t *hdd_sta_ctx;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011180 uint32_t roamId;
11181 tCsrRoamProfile *pRoamProfile;
11182 eCsrAuthType RSNAuthType;
11183 tSmeConfigParams *sme_config;
Nitesh Shah044fd672016-10-13 18:53:25 +053011184 uint8_t channel = 0;
11185 struct sir_hw_mode_params hw_mode;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011186
11187 ENTER();
11188
11189 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11190 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan5de8d172016-07-13 14:44:28 +053011191 hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011192
11193 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053011194 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011195 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011196
11197 if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011198 hdd_err("wrong SSID len");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011199 return -EINVAL;
11200 }
11201
11202 pRoamProfile = &pWextState->roamProfile;
Anurag Chouhand939d3d2016-07-20 17:45:48 +053011203 qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
11204 sizeof(hdd_sta_ctx->conn_info.conn_flag));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011205
11206 if (pRoamProfile) {
11207 hdd_station_ctx_t *pHddStaCtx;
11208 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11209
11210 if (HDD_WMM_USER_MODE_NO_QOS ==
11211 (WLAN_HDD_GET_CTX(pAdapter))->config->WmmMode) {
11212 /*QoS not enabled in cfg file */
11213 pRoamProfile->uapsd_mask = 0;
11214 } else {
11215 /*QoS enabled, update uapsd mask from cfg file */
11216 pRoamProfile->uapsd_mask =
11217 (WLAN_HDD_GET_CTX(pAdapter))->config->UapsdMask;
11218 }
11219
11220 pRoamProfile->SSIDs.numOfSSIDs = 1;
11221 pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011222 qdf_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011223 sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId));
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011224 qdf_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId),
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011225 ssid, ssid_len);
11226
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011227 pRoamProfile->do_not_roam = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011228 if (bssid) {
11229 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Sreelakshmi Konamkibda5bbf2016-09-12 18:38:10 +053011230 pRoamProfile->do_not_roam = true;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011231 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011232 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011233 /*
11234 * Save BSSID in seperate variable as
11235 * pRoamProfile's BSSID is getting zeroed out in the
11236 * association process. In case of join failure
11237 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011238 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011239 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011240 bssid, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011241 hdd_info("bssid is given by upper layer %pM", bssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011242 } else if (bssid_hint) {
11243 pRoamProfile->BSSIDs.numOfBSSIDs = 1;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011244 qdf_mem_copy((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011245 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni31949422016-07-29 17:17:53 -070011246 /*
11247 * Save BSSID in a separate variable as
11248 * pRoamProfile's BSSID is getting zeroed out in the
11249 * association process. In case of join failure
11250 * we should send valid BSSID to supplicant
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011251 */
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011252 qdf_mem_copy((void *)(pWextState->req_bssId.bytes),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011253 bssid_hint, QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011254 hdd_info("bssid_hint is given by upper layer %pM",
11255 bssid_hint);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011256 } else {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011257 qdf_mem_zero((void *)(pRoamProfile->BSSIDs.bssid),
Anurag Chouhan6d760662016-02-20 16:05:43 +053011258 QDF_MAC_ADDR_SIZE);
Krunal Soni35b404c2016-07-14 23:36:00 -070011259 hdd_info("no bssid given by upper layer");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011260 }
11261
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011262 hdd_notice("Connect to SSID: %.*s operating Channel: %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011263 pRoamProfile->SSIDs.SSIDList->SSID.length,
11264 pRoamProfile->SSIDs.SSIDList->SSID.ssId,
11265 operatingChannel);
11266
11267 if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) ||
11268 (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011269 hdd_set_genie_to_csr(pAdapter, &RSNAuthType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011270 hdd_set_csr_auth_type(pAdapter, RSNAuthType);
11271 }
11272#ifdef FEATURE_WLAN_WAPI
11273 if (pAdapter->wapi_info.nWapiMode) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011274 hdd_notice("Setting WAPI AUTH Type and Encryption Mode values");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011275 switch (pAdapter->wapi_info.wapiAuthMode) {
11276 case WAPI_AUTH_MODE_PSK:
11277 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011278 hdd_notice("WAPI AUTH TYPE: PSK: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011279 pAdapter->wapi_info.wapiAuthMode);
11280 pRoamProfile->AuthType.authType[0] =
11281 eCSR_AUTH_TYPE_WAPI_WAI_PSK;
11282 break;
11283 }
11284 case WAPI_AUTH_MODE_CERT:
11285 {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011286 hdd_notice("WAPI AUTH TYPE: CERT: %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011287 pAdapter->wapi_info.wapiAuthMode);
11288 pRoamProfile->AuthType.authType[0] =
11289 eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE;
11290 break;
11291 }
11292 } /* End of switch */
11293 if (pAdapter->wapi_info.wapiAuthMode ==
11294 WAPI_AUTH_MODE_PSK
11295 || pAdapter->wapi_info.wapiAuthMode ==
11296 WAPI_AUTH_MODE_CERT) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011297 hdd_notice("WAPI PAIRWISE/GROUP ENCRYPTION: WPI");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011298 pRoamProfile->AuthType.numEntries = 1;
11299 pRoamProfile->EncryptionType.numEntries = 1;
11300 pRoamProfile->EncryptionType.encryptionType[0] =
11301 eCSR_ENCRYPT_TYPE_WPI;
11302 pRoamProfile->mcEncryptionType.numEntries = 1;
11303 pRoamProfile->mcEncryptionType.
11304 encryptionType[0] = eCSR_ENCRYPT_TYPE_WPI;
11305 }
11306 }
Krunal Soni31949422016-07-29 17:17:53 -070011307#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011308#ifdef WLAN_FEATURE_GTK_OFFLOAD
11309 /* Initializing gtkOffloadReqParams */
Krunal Sonib4326f22016-03-10 13:05:51 -080011310 if ((QDF_STA_MODE == pAdapter->device_mode) ||
11311 (QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011312 memset(&pHddStaCtx->gtkOffloadReqParams, 0,
11313 sizeof(tSirGtkOffloadParams));
11314 pHddStaCtx->gtkOffloadReqParams.ulFlags =
11315 GTK_OFFLOAD_DISABLE;
11316 }
11317#endif
11318 pRoamProfile->csrPersona = pAdapter->device_mode;
11319
11320 if (operatingChannel) {
11321 pRoamProfile->ChannelInfo.ChannelList =
11322 &operatingChannel;
11323 pRoamProfile->ChannelInfo.numOfChannels = 1;
11324 } else {
11325 pRoamProfile->ChannelInfo.ChannelList = NULL;
11326 pRoamProfile->ChannelInfo.numOfChannels = 0;
11327 }
Krunal Sonib4326f22016-03-10 13:05:51 -080011328 if ((QDF_IBSS_MODE == pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011329 && operatingChannel) {
11330 /*
11331 * Need to post the IBSS power save parameters
11332 * to WMA. WMA will configure this parameters
11333 * to firmware if power save is enabled by the
11334 * firmware.
11335 */
11336 status = hdd_set_ibss_power_save_params(pAdapter);
11337
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011338 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011339 hdd_err("Set IBSS Power Save Params Failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011340 return -EINVAL;
11341 }
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011342 pRoamProfile->ch_params.ch_width =
11343 hdd_map_nl_chan_width(ch_width);
Nitesh Shah87335a52016-09-05 15:47:32 +053011344 /*
11345 * In IBSS mode while operating in 2.4 GHz,
11346 * the device supports only 20 MHz.
11347 */
11348 if (CDS_IS_CHANNEL_24GHZ(operatingChannel))
11349 pRoamProfile->ch_params.ch_width =
11350 CH_WIDTH_20MHZ;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070011351 hdd_select_cbmode(pAdapter, operatingChannel,
11352 &pRoamProfile->ch_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011353 }
Abhishek Singh99bce862016-06-20 15:10:51 +053011354 /*
11355 * if MFPEnabled is set but the peer AP is non-PMF i.e 80211w=2
11356 * or pmf=2 is an explicit configuration in the supplicant
11357 * configuration, drop the connection request.
11358 */
11359 if (pWextState->roamProfile.MFPEnabled &&
11360 !(pWextState->roamProfile.MFPRequired ||
11361 pWextState->roamProfile.MFPCapable)) {
11362 hdd_err("Drop connect req as supplicant has indicated PMF req for a non-PMF peer. MFPEnabled %d MFPRequired %d MFPCapable %d",
11363 pWextState->roamProfile.MFPEnabled,
11364 pWextState->roamProfile.MFPRequired,
11365 pWextState->roamProfile.MFPCapable);
11366 return -EINVAL;
11367 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011368
Krunal Soni3091bcc2016-06-23 12:28:21 -070011369 if (true == cds_is_connection_in_progress()) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011370 hdd_err("Connection refused: conn in progress");
11371 return -EINVAL;
11372 }
11373
Krunal Soni31949422016-07-29 17:17:53 -070011374 /*
11375 * After 8-way handshake supplicant should give the scan command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011376 * in that it update the additional IEs, But because of scan
Krunal Soni31949422016-07-29 17:17:53 -070011377 * enhancements, the supplicant is not issuing the scan command
11378 * now. So the unicast frames which are sent from the host are
11379 * not having the additional IEs. If it is P2P CLIENT and there
11380 * is no additional IE present in roamProfile, then use the
11381 * addtional IE form scan_info
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011382 */
11383
Krunal Sonib4326f22016-03-10 13:05:51 -080011384 if ((pAdapter->device_mode == QDF_P2P_CLIENT_MODE) &&
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011385 (!pRoamProfile->pAddIEScan)) {
11386 pRoamProfile->pAddIEScan =
11387 &pAdapter->scan_info.scanAddIE.addIEdata[0];
11388 pRoamProfile->nAddIEScanLength =
11389 pAdapter->scan_info.scanAddIE.length;
11390 }
11391 /*
11392 * When policy manager is enabled from ini file, we shouldn't
11393 * check for other concurrency rules.
11394 */
Krunal Soni3091bcc2016-06-23 12:28:21 -070011395 if (wma_is_hw_dbs_capable() == false) {
Tushnim Bhattacharyya4adb3682016-01-07 15:07:12 -080011396 cds_handle_conc_rule1(pAdapter, pRoamProfile);
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080011397 if (true != cds_handle_conc_rule2(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011398 pAdapter, pRoamProfile, &roamId))
11399 return 0;
11400 }
11401
Krunal Soni3091bcc2016-06-23 12:28:21 -070011402 if ((wma_is_hw_dbs_capable() == true) &&
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011403 (false == wlan_hdd_handle_sap_sta_dfs_conc(pAdapter,
11404 pRoamProfile))) {
11405 hdd_err("sap-sta conc will fail, can't allow sta");
11406 hdd_conn_set_connection_state(pAdapter,
11407 eConnectionState_NotConnected);
11408 return -ENOMEM;
11409 }
11410
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011411 sme_config = qdf_mem_malloc(sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011412 if (!sme_config) {
11413 hdd_err("unable to allocate sme_config");
Rajeev Kumar249ea8d2016-04-15 16:57:46 -070011414 hdd_conn_set_connection_state(pAdapter,
11415 eConnectionState_NotConnected);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011416 return -ENOMEM;
11417 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011418 qdf_mem_zero(sme_config, sizeof(*sme_config));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011419 sme_get_config_param(pHddCtx->hHal, sme_config);
11420 /* These values are not sessionized. So, any change in these SME
11421 * configs on an older or parallel interface will affect the
11422 * cb mode. So, restoring the default INI params before starting
11423 * interfaces such as sta, cli etc.,
11424 */
11425 sme_config->csrConfig.channelBondingMode5GHz =
11426 pHddCtx->config->nChannelBondingMode5GHz;
11427 sme_config->csrConfig.channelBondingMode24GHz =
11428 pHddCtx->config->nChannelBondingMode24GHz;
11429 sme_update_config(pHddCtx->hHal, sme_config);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053011430 qdf_mem_free(sme_config);
Agrawal Ashish6b015762016-05-05 11:22:18 +053011431 /*
11432 * Change conn_state to connecting before sme_roam_connect(),
11433 * because sme_roam_connect() has a direct path to call
11434 * hdd_sme_roam_callback(), which will change the conn_state
11435 * If direct path, conn_state will be accordingly changed to
11436 * NotConnected or Associated by either
11437 * hdd_association_completion_handler() or
11438 * hdd_dis_connect_handler() in sme_RoamCallback()if
11439 * sme_RomConnect is to be queued,
11440 * Connecting state will remain until it is completed.
11441 *
11442 * If connection state is not changed, connection state will
11443 * remain in eConnectionState_NotConnected state.
11444 * In hdd_association_completion_handler, "hddDisconInProgress"
11445 * is set to true if conn state is
11446 * eConnectionState_NotConnected.
11447 * If "hddDisconInProgress" is set to true then cfg80211 layer
11448 * is not informed of connect result indication which
11449 * is an issue.
11450 */
11451 if (QDF_STA_MODE == pAdapter->device_mode ||
Abhishek Singh23edd1c2016-05-05 11:56:06 +053011452 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)
Agrawal Ashish6b015762016-05-05 11:22:18 +053011453 hdd_conn_set_connection_state(pAdapter,
11454 eConnectionState_Connecting);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011455
Komal Seelama89be8d2016-09-29 11:09:26 +053011456 qdf_runtime_pm_prevent_suspend(pAdapter->connect_rpm_ctx.
11457 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011458 status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter),
11459 pAdapter->sessionId, pRoamProfile,
11460 &roamId);
11461
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053011462 if ((QDF_STATUS_SUCCESS != status) &&
Krunal Sonib4326f22016-03-10 13:05:51 -080011463 (QDF_STA_MODE == pAdapter->device_mode ||
11464 QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011465 hdd_err("sme_roam_connect (session %d) failed with "
11466 "status %d. -> NotConnected",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011467 pAdapter->sessionId, status);
11468 /* change back to NotAssociated */
11469 hdd_conn_set_connection_state(pAdapter,
11470 eConnectionState_NotConnected);
Komal Seelama89be8d2016-09-29 11:09:26 +053011471 qdf_runtime_pm_allow_suspend(pAdapter->connect_rpm_ctx.
11472 connect);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011473 }
11474
11475 pRoamProfile->ChannelInfo.ChannelList = NULL;
11476 pRoamProfile->ChannelInfo.numOfChannels = 0;
11477
Nitesh Shah044fd672016-10-13 18:53:25 +053011478 if (!QDF_IS_STATUS_SUCCESS(
11479 wma_get_current_hw_mode(&hw_mode))) {
11480 hdd_err("wma_get_current_hw_mode failed");
11481 return status;
11482 }
11483
11484 if ((QDF_STA_MODE == pAdapter->device_mode)
11485 && hw_mode.dbs_cap) {
11486 cds_get_channel_from_scan_result(pAdapter,
11487 pRoamProfile, &channel);
11488 if (channel)
11489 cds_checkn_update_hw_mode_single_mac_mode
11490 (channel);
11491 }
11492
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011493 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011494 hdd_err("No valid Roam profile");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011495 return -EINVAL;
11496 }
11497 EXIT();
11498 return status;
11499}
11500
11501/**
11502 * wlan_hdd_cfg80211_set_auth_type() - set auth type
11503 * @pAdapter: Pointer to adapter
11504 * @auth_type: Auth type
11505 *
11506 * This function is used to set the authentication type (OPEN/SHARED).
11507 *
11508 * Return: 0 for success, non-zero for failure
11509 */
11510static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter,
11511 enum nl80211_auth_type auth_type)
11512{
11513 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11514 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11515
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011516 /*set authentication type */
11517 switch (auth_type) {
11518 case NL80211_AUTHTYPE_AUTOMATIC:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011519 hdd_notice("set authentication type to AUTOSWITCH");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011520 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH;
11521 break;
11522
11523 case NL80211_AUTHTYPE_OPEN_SYSTEM:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011524 case NL80211_AUTHTYPE_FT:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011525 hdd_notice("set authentication type to OPEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011526 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
11527 break;
11528
11529 case NL80211_AUTHTYPE_SHARED_KEY:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011530 hdd_notice("set authentication type to SHARED");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011531 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY;
11532 break;
11533#ifdef FEATURE_WLAN_ESE
11534 case NL80211_AUTHTYPE_NETWORK_EAP:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011535 hdd_notice("set authentication type to CCKM WPA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011536 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;
11537 break;
11538#endif
11539
11540 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011541 hdd_err("Unsupported authentication type %d", auth_type);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011542 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN;
11543 return -EINVAL;
11544 }
11545
11546 pWextState->roamProfile.AuthType.authType[0] =
11547 pHddStaCtx->conn_info.authType;
11548 return 0;
11549}
11550
11551/**
11552 * wlan_hdd_set_akm_suite() - set key management type
11553 * @pAdapter: Pointer to adapter
11554 * @key_mgmt: Key management type
11555 *
11556 * This function is used to set the key mgmt type(PSK/8021x).
11557 *
11558 * Return: 0 for success, non-zero for failure
11559 */
11560static int wlan_hdd_set_akm_suite(hdd_adapter_t *pAdapter, u32 key_mgmt)
11561{
11562 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11563
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011564#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
11565#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
11566 /*set key mgmt type */
11567 switch (key_mgmt) {
11568 case WLAN_AKM_SUITE_PSK:
11569 case WLAN_AKM_SUITE_PSK_SHA256:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011570 case WLAN_AKM_SUITE_FT_PSK:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011571 hdd_notice("setting key mgmt type to PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011572 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_PSK;
11573 break;
11574
11575 case WLAN_AKM_SUITE_8021X_SHA256:
11576 case WLAN_AKM_SUITE_8021X:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011577 case WLAN_AKM_SUITE_FT_8021X:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011578 hdd_notice("setting key mgmt type to 8021x");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011579 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11580 break;
11581#ifdef FEATURE_WLAN_ESE
11582#define WLAN_AKM_SUITE_CCKM 0x00409600 /* Should be in ieee802_11_defs.h */
11583#define IW_AUTH_KEY_MGMT_CCKM 8 /* Should be in linux/wireless.h */
11584 case WLAN_AKM_SUITE_CCKM:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011585 hdd_notice("setting key mgmt type to CCKM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011586 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_CCKM;
11587 break;
11588#endif
11589#ifndef WLAN_AKM_SUITE_OSEN
11590#define WLAN_AKM_SUITE_OSEN 0x506f9a01 /* Should be in ieee802_11_defs.h */
11591#endif
11592 case WLAN_AKM_SUITE_OSEN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011593 hdd_notice("setting key mgmt type to OSEN");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011594 pWextState->authKeyMgmt |= IW_AUTH_KEY_MGMT_802_1X;
11595 break;
11596
11597 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011598 hdd_err("Unsupported key mgmt type %d", key_mgmt);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011599 return -EINVAL;
11600
11601 }
11602 return 0;
11603}
11604
11605/**
11606 * wlan_hdd_cfg80211_set_cipher() - set encryption type
11607 * @pAdapter: Pointer to adapter
11608 * @cipher: Cipher type
11609 * @ucast: Unicast flag
11610 *
11611 * This function is used to set the encryption type
11612 * (NONE/WEP40/WEP104/TKIP/CCMP).
11613 *
11614 * Return: 0 for success, non-zero for failure
11615 */
11616static int wlan_hdd_cfg80211_set_cipher(hdd_adapter_t *pAdapter,
11617 u32 cipher, bool ucast)
11618{
11619 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11620 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11621 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
11622
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011623 if (!cipher) {
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080011624 hdd_info("received cipher %d - considering none", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011625 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11626 } else {
11627
11628 /*set encryption method */
11629 switch (cipher) {
11630 case IW_AUTH_CIPHER_NONE:
11631 encryptionType = eCSR_ENCRYPT_TYPE_NONE;
11632 break;
11633
11634 case WLAN_CIPHER_SUITE_WEP40:
11635 encryptionType = eCSR_ENCRYPT_TYPE_WEP40;
11636 break;
11637
11638 case WLAN_CIPHER_SUITE_WEP104:
11639 encryptionType = eCSR_ENCRYPT_TYPE_WEP104;
11640 break;
11641
11642 case WLAN_CIPHER_SUITE_TKIP:
11643 encryptionType = eCSR_ENCRYPT_TYPE_TKIP;
11644 break;
11645
11646 case WLAN_CIPHER_SUITE_CCMP:
11647 encryptionType = eCSR_ENCRYPT_TYPE_AES;
11648 break;
11649#ifdef FEATURE_WLAN_WAPI
11650 case WLAN_CIPHER_SUITE_SMS4:
11651 encryptionType = eCSR_ENCRYPT_TYPE_WPI;
11652 break;
11653#endif
11654
11655#ifdef FEATURE_WLAN_ESE
11656 case WLAN_CIPHER_SUITE_KRK:
11657 encryptionType = eCSR_ENCRYPT_TYPE_KRK;
11658 break;
11659#ifdef WLAN_FEATURE_ROAM_OFFLOAD
11660 case WLAN_CIPHER_SUITE_BTK:
11661 encryptionType = eCSR_ENCRYPT_TYPE_BTK;
11662 break;
11663#endif
11664#endif
11665 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011666 hdd_err("Unsupported cipher type %d", cipher);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011667 return -EOPNOTSUPP;
11668 }
11669 }
11670
11671 if (ucast) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011672 hdd_notice("setting unicast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011673 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
11674 pWextState->roamProfile.EncryptionType.numEntries = 1;
11675 pWextState->roamProfile.EncryptionType.encryptionType[0] =
11676 encryptionType;
11677 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011678 hdd_notice("setting mcast cipher type to %d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011679 pHddStaCtx->conn_info.mcEncryptionType = encryptionType;
11680 pWextState->roamProfile.mcEncryptionType.numEntries = 1;
11681 pWextState->roamProfile.mcEncryptionType.encryptionType[0] =
11682 encryptionType;
11683 }
11684
11685 return 0;
11686}
11687
11688/**
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011689 * wlan_hdd_add_assoc_ie() - Add Assoc IE to roamProfile
11690 * @wext_state: Pointer to wext state
11691 * @gen_ie: Pointer to IE data
11692 * @len: length of IE data
11693 *
11694 * Return: 0 for success, non-zero for failure
11695 */
11696static int wlan_hdd_add_assoc_ie(hdd_wext_state_t *wext_state,
11697 const uint8_t *gen_ie, uint16_t len)
11698{
11699 uint16_t cur_add_ie_len =
11700 wext_state->assocAddIE.length;
11701
11702 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11703 (wext_state->assocAddIE.length + len)) {
11704 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
11705 QDF_ASSERT(0);
11706 return -ENOMEM;
11707 }
11708 memcpy(wext_state->assocAddIE.addIEdata +
11709 cur_add_ie_len, gen_ie, len);
11710 wext_state->assocAddIE.length += len;
11711
11712 wext_state->roamProfile.pAddIEAssoc =
11713 wext_state->assocAddIE.addIEdata;
11714 wext_state->roamProfile.nAddIEAssocLength =
11715 wext_state->assocAddIE.length;
11716 return 0;
11717}
11718
11719/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011720 * wlan_hdd_cfg80211_set_ie() - set IEs
11721 * @pAdapter: Pointer to adapter
11722 * @ie: Pointer ot ie
11723 * @ie: IE length
11724 *
11725 * Return: 0 for success, non-zero for failure
11726 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070011727static int wlan_hdd_cfg80211_set_ie(hdd_adapter_t *pAdapter, const uint8_t *ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011728 size_t ie_len)
11729{
11730 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
11731 const uint8_t *genie = ie;
11732 uint16_t remLen = ie_len;
11733#ifdef FEATURE_WLAN_WAPI
11734 uint32_t akmsuite[MAX_NUM_AKM_SUITES];
11735 u16 *tmp;
11736 uint16_t akmsuiteCount;
11737 int *akmlist;
11738#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011739 int status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011740
11741 /* clear previous assocAddIE */
11742 pWextState->assocAddIE.length = 0;
11743 pWextState->roamProfile.bWPSAssociation = false;
11744 pWextState->roamProfile.bOSENAssociation = false;
11745
11746 while (remLen >= 2) {
11747 uint16_t eLen = 0;
11748 uint8_t elementId;
11749 elementId = *genie++;
11750 eLen = *genie++;
11751 remLen -= 2;
11752
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011753 hdd_notice("IE[0x%X], LEN[%d]", elementId, eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011754
11755 switch (elementId) {
11756 case DOT11F_EID_WPA:
11757 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 -070011758 hdd_err("Invalid WPA IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011759 return -EINVAL;
11760 } else if (0 ==
11761 memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) {
11762 uint16_t curAddIELen =
11763 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011764 hdd_notice("Set WPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011765
11766 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11767 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011768 hdd_err("Cannot accommodate assocAddIE. Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011769 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011770 return -ENOMEM;
11771 }
11772 /* WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
11773 memcpy(pWextState->assocAddIE.addIEdata +
11774 curAddIELen, genie - 2, eLen + 2);
11775 pWextState->assocAddIE.length += eLen + 2;
11776
11777 pWextState->roamProfile.bWPSAssociation = true;
11778 pWextState->roamProfile.pAddIEAssoc =
11779 pWextState->assocAddIE.addIEdata;
11780 pWextState->roamProfile.nAddIEAssocLength =
11781 pWextState->assocAddIE.length;
11782 } else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011783 hdd_notice("Set WPA IE (len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011784 memset(pWextState->WPARSNIE, 0,
11785 MAX_WPA_RSN_IE_LEN);
11786 memcpy(pWextState->WPARSNIE, genie - 2,
11787 (eLen + 2));
11788 pWextState->roamProfile.pWPAReqIE =
11789 pWextState->WPARSNIE;
11790 pWextState->roamProfile.nWPAReqIELength = eLen + 2; /* ie_len; */
11791 } else if ((0 == memcmp(&genie[0], P2P_OUI_TYPE,
11792 P2P_OUI_TYPE_SIZE))) {
11793 uint16_t curAddIELen =
11794 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011795 hdd_notice("Set P2P IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011796
11797 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11798 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011799 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011800 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011801 return -ENOMEM;
11802 }
11803 /* P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE */
11804 memcpy(pWextState->assocAddIE.addIEdata +
11805 curAddIELen, genie - 2, eLen + 2);
11806 pWextState->assocAddIE.length += eLen + 2;
11807
11808 pWextState->roamProfile.pAddIEAssoc =
11809 pWextState->assocAddIE.addIEdata;
11810 pWextState->roamProfile.nAddIEAssocLength =
11811 pWextState->assocAddIE.length;
11812 }
11813#ifdef WLAN_FEATURE_WFD
11814 else if ((0 == memcmp(&genie[0], WFD_OUI_TYPE,
11815 WFD_OUI_TYPE_SIZE)) &&
11816 /* Consider WFD IE, only for P2P Client */
Krunal Sonib4326f22016-03-10 13:05:51 -080011817 (QDF_P2P_CLIENT_MODE ==
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011818 pAdapter->device_mode)) {
11819 uint16_t curAddIELen =
11820 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011821 hdd_notice("Set WFD IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011822
11823 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11824 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011825 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011826 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011827 return -ENOMEM;
11828 }
11829 /* WFD IE is saved to Additional IE ; it should
11830 * be accumulated to handle WPS IE + P2P IE +
11831 * WFD IE */
11832 memcpy(pWextState->assocAddIE.addIEdata +
11833 curAddIELen, genie - 2, eLen + 2);
11834 pWextState->assocAddIE.length += eLen + 2;
11835
11836 pWextState->roamProfile.pAddIEAssoc =
11837 pWextState->assocAddIE.addIEdata;
11838 pWextState->roamProfile.nAddIEAssocLength =
11839 pWextState->assocAddIE.length;
11840 }
11841#endif
11842 /* Appending HS 2.0 Indication Element in Assiciation Request */
11843 else if ((0 == memcmp(&genie[0], HS20_OUI_TYPE,
11844 HS20_OUI_TYPE_SIZE))) {
11845 uint16_t curAddIELen =
11846 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011847 hdd_notice("Set HS20 IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011848
11849 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11850 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011851 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011852 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011853 return -ENOMEM;
11854 }
11855 memcpy(pWextState->assocAddIE.addIEdata +
11856 curAddIELen, genie - 2, eLen + 2);
11857 pWextState->assocAddIE.length += eLen + 2;
11858
11859 pWextState->roamProfile.pAddIEAssoc =
11860 pWextState->assocAddIE.addIEdata;
11861 pWextState->roamProfile.nAddIEAssocLength =
11862 pWextState->assocAddIE.length;
11863 }
11864 /* Appending OSEN Information Element in Assiciation Request */
11865 else if ((0 == memcmp(&genie[0], OSEN_OUI_TYPE,
11866 OSEN_OUI_TYPE_SIZE))) {
11867 uint16_t curAddIELen =
11868 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011869 hdd_notice("Set OSEN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011870
11871 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11872 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011873 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011874 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011875 return -ENOMEM;
11876 }
11877 memcpy(pWextState->assocAddIE.addIEdata +
11878 curAddIELen, genie - 2, eLen + 2);
11879 pWextState->assocAddIE.length += eLen + 2;
11880
11881 pWextState->roamProfile.bOSENAssociation = true;
11882 pWextState->roamProfile.pAddIEAssoc =
11883 pWextState->assocAddIE.addIEdata;
11884 pWextState->roamProfile.nAddIEAssocLength =
11885 pWextState->assocAddIE.length;
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011886 } else if ((0 == memcmp(&genie[0], MBO_OUI_TYPE,
11887 MBO_OUI_TYPE_SIZE))){
11888 hdd_info("Set MBO IE(len %d)", eLen + 2);
11889 status = wlan_hdd_add_assoc_ie(pWextState,
11890 genie - 2, eLen + 2);
11891 if (status)
11892 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011893 } else {
11894 uint16_t add_ie_len =
11895 pWextState->assocAddIE.length;
11896
11897 hdd_info("Set OSEN IE(len %d)", eLen + 2);
11898
11899 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11900 (pWextState->assocAddIE.length + eLen)) {
11901 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011902 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011903 return -ENOMEM;
11904 }
11905
11906 memcpy(pWextState->assocAddIE.addIEdata +
11907 add_ie_len, genie - 2, eLen + 2);
11908 pWextState->assocAddIE.length += eLen + 2;
11909
11910 pWextState->roamProfile.pAddIEAssoc =
11911 pWextState->assocAddIE.addIEdata;
11912 pWextState->roamProfile.nAddIEAssocLength =
11913 pWextState->assocAddIE.length;
11914 }
11915 break;
11916 case DOT11F_EID_RSN:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011917 hdd_notice("Set RSN IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011918 memset(pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN);
11919 memcpy(pWextState->WPARSNIE, genie - 2,
11920 (eLen + 2));
11921 pWextState->roamProfile.pRSNReqIE =
11922 pWextState->WPARSNIE;
11923 pWextState->roamProfile.nRSNReqIELength = eLen + 2; /* ie_len; */
11924 break;
11925 /*
11926 * Appending Extended Capabilities with Interworking bit set
11927 * in Assoc Req.
11928 *
11929 * In assoc req this EXT Cap will only be taken into account if
11930 * interworkingService bit is set to 1. Currently
11931 * driver is only interested in interworkingService capability
11932 * from supplicant. If in future any other EXT Cap info is
11933 * required from supplicat, it needs to be handled while
11934 * sending Assoc Req in LIM.
11935 */
11936 case DOT11F_EID_EXTCAP:
11937 {
11938 uint16_t curAddIELen =
11939 pWextState->assocAddIE.length;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011940 hdd_notice("Set Extended CAPS IE(len %d)", eLen + 2);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011941
11942 if (SIR_MAC_MAX_ADD_IE_LENGTH <
11943 (pWextState->assocAddIE.length + eLen)) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011944 hdd_err("Cannot accommodate assocAddIE Need bigger buffer space");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011945 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011946 return -ENOMEM;
11947 }
11948 memcpy(pWextState->assocAddIE.addIEdata +
11949 curAddIELen, genie - 2, eLen + 2);
11950 pWextState->assocAddIE.length += eLen + 2;
11951
11952 pWextState->roamProfile.pAddIEAssoc =
11953 pWextState->assocAddIE.addIEdata;
11954 pWextState->roamProfile.nAddIEAssocLength =
11955 pWextState->assocAddIE.length;
11956 break;
11957 }
11958#ifdef FEATURE_WLAN_WAPI
11959 case WLAN_EID_WAPI:
11960 /* Setting WAPI Mode to ON=1 */
11961 pAdapter->wapi_info.nWapiMode = 1;
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011962 hdd_notice("WAPI MODE IS %u", pAdapter->wapi_info.nWapiMode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011963 tmp = (u16 *) ie;
11964 tmp = tmp + 2; /* Skip element Id and Len, Version */
11965 akmsuiteCount = WPA_GET_LE16(tmp);
11966 tmp = tmp + 1;
11967 akmlist = (int *)(tmp);
11968 if (akmsuiteCount <= MAX_NUM_AKM_SUITES) {
11969 memcpy(akmsuite, akmlist, (4 * akmsuiteCount));
11970 } else {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011971 hdd_err("Invalid akmSuite count");
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053011972 QDF_ASSERT(0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011973 return -EINVAL;
11974 }
11975
11976 if (WAPI_PSK_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011977 hdd_notice("WAPI AUTH MODE SET TO PSK");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011978 pAdapter->wapi_info.wapiAuthMode =
11979 WAPI_AUTH_MODE_PSK;
11980 }
11981 if (WAPI_CERT_AKM_SUITE == akmsuite[0]) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011982 hdd_notice("WAPI AUTH MODE SET TO CERTIFICATE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011983 pAdapter->wapi_info.wapiAuthMode =
11984 WAPI_AUTH_MODE_CERT;
11985 }
11986 break;
11987#endif
Selvaraj, Sridhara7fc7632016-09-04 13:13:38 +053011988 case DOT11F_EID_SUPPOPERATINGCLASSES:
11989 {
11990 hdd_info("Set Supported Operating Classes IE(len %d)", eLen + 2);
11991 status = wlan_hdd_add_assoc_ie(pWextState,
11992 genie - 2, eLen + 2);
11993 if (status)
11994 return status;
11995 break;
11996 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011997 default:
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070011998 hdd_err("Set UNKNOWN IE %X", elementId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080011999 /* when Unknown IE is received we should break and continue
12000 * to the next IE in the buffer instead we were returning
12001 * so changing this to break */
12002 break;
12003 }
12004 genie += eLen;
12005 remLen -= eLen;
12006 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012007 return 0;
12008}
12009
12010/**
12011 * hdd_is_wpaie_present() - check for WPA ie
12012 * @ie: Pointer to ie
12013 * @ie_len: Ie length
12014 *
12015 * Parse the received IE to find the WPA IE
12016 *
12017 * Return: true if wpa ie is found else false
12018 */
12019static bool hdd_is_wpaie_present(const uint8_t *ie, uint8_t ie_len)
12020{
12021 uint8_t eLen = 0;
12022 uint16_t remLen = ie_len;
12023 uint8_t elementId = 0;
12024
12025 while (remLen >= 2) {
12026 elementId = *ie++;
12027 eLen = *ie++;
12028 remLen -= 2;
12029 if (eLen > remLen) {
Jeff Johnsonff5b9aa2016-06-29 15:10:30 -070012030 hdd_err("IE length is wrong %d", eLen);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012031 return false;
12032 }
12033 if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) {
12034 /* OUI - 0x00 0X50 0XF2
12035 * WPA Information Element - 0x01
12036 * WPA version - 0x01
12037 */
12038 if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5))
12039 return true;
12040 }
12041 ie += eLen;
12042 remLen -= eLen;
12043 }
12044 return false;
12045}
12046
12047/**
12048 * wlan_hdd_cfg80211_set_privacy() - set security parameters during connection
12049 * @pAdapter: Pointer to adapter
12050 * @req: Pointer to security parameters
12051 *
12052 * Return: 0 for success, non-zero for failure
12053 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012054static int wlan_hdd_cfg80211_set_privacy(hdd_adapter_t *pAdapter,
12055 struct cfg80211_connect_params *req)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012056{
12057 int status = 0;
12058 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12059 ENTER();
12060
12061 /*set wpa version */
12062 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
12063
12064 if (req->crypto.wpa_versions) {
12065 if (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) {
12066 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA;
12067 } else if (NL80211_WPA_VERSION_2 == req->crypto.wpa_versions) {
12068 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12069 }
12070 }
12071
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012072 hdd_notice("set wpa version to %d", pWextState->wpaVersion);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012073
12074 /*set authentication type */
12075 status = wlan_hdd_cfg80211_set_auth_type(pAdapter, req->auth_type);
12076
12077 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012078 hdd_err("failed to set authentication type ");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012079 return status;
12080 }
12081
12082 /*set key mgmt type */
12083 if (req->crypto.n_akm_suites) {
12084 status =
12085 wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]);
12086 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012087 hdd_err("failed to set akm suite");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012088 return status;
12089 }
12090 }
12091
12092 /*set pairwise cipher type */
12093 if (req->crypto.n_ciphers_pairwise) {
12094 status = wlan_hdd_cfg80211_set_cipher(pAdapter,
12095 req->crypto.
12096 ciphers_pairwise[0],
12097 true);
12098 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012099 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012100 return status;
12101 }
12102 } else {
12103 /*Reset previous cipher suite to none */
12104 status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true);
12105 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012106 hdd_err("failed to set unicast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012107 return status;
12108 }
12109 }
12110
12111 /*set group cipher type */
12112 status =
12113 wlan_hdd_cfg80211_set_cipher(pAdapter, req->crypto.cipher_group,
12114 false);
12115
12116 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012117 hdd_err("failed to set mcast cipher type");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012118 return status;
12119 }
12120#ifdef WLAN_FEATURE_11W
12121 pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED);
12122#endif
12123
12124 /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile */
12125 if (req->ie_len) {
12126 status =
12127 wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len);
12128 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012129 hdd_err("failed to parse the WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012130 return status;
12131 }
12132 }
12133
12134 /*incase of WEP set default key information */
12135 if (req->key && req->key_len) {
12136 if ((WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0])
12137 || (WLAN_CIPHER_SUITE_WEP104 ==
12138 req->crypto.ciphers_pairwise[0])
12139 ) {
12140 if (IW_AUTH_KEY_MGMT_802_1X
12141 ==
12142 (pWextState->
12143 authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012144 hdd_err("Dynamic WEP not supported");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012145 return -EOPNOTSUPP;
12146 } else {
12147 u8 key_len = req->key_len;
12148 u8 key_idx = req->key_idx;
12149
12150 if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >=
12151 key_len)
12152 && (CSR_MAX_NUM_KEY > key_idx)
12153 ) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012154 hdd_notice("setting default wep key, key_idx = %hu key_len %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012155 key_idx, key_len);
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012156 qdf_mem_copy(&pWextState->roamProfile.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012157 Keys.
12158 KeyMaterial[key_idx][0],
12159 req->key, key_len);
12160 pWextState->roamProfile.Keys.
12161 KeyLength[key_idx] = (u8) key_len;
12162 pWextState->roamProfile.Keys.
12163 defaultIndex = (u8) key_idx;
12164 }
12165 }
12166 }
12167 }
12168
12169 return status;
12170}
12171
12172/**
12173 * wlan_hdd_try_disconnect() - try disconnnect from previous connection
12174 * @pAdapter: Pointer to adapter
12175 *
12176 * This function is used to disconnect from previous connection
12177 *
12178 * Return: 0 for success, non-zero for failure
12179 */
12180static int wlan_hdd_try_disconnect(hdd_adapter_t *pAdapter)
12181{
12182 unsigned long rc;
12183 hdd_station_ctx_t *pHddStaCtx;
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012184 int status, result = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012185
12186 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12187
Jeff Johnson9edf9572016-10-03 15:24:49 -070012188 if ((QDF_IBSS_MODE == pAdapter->device_mode) ||
Abhishek Singh03f992e2016-01-07 18:07:06 +053012189 (eConnectionState_Associated == pHddStaCtx->conn_info.connState) ||
12190 (eConnectionState_Connecting == pHddStaCtx->conn_info.connState) ||
12191 (eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012192 hdd_conn_set_connection_state(pAdapter,
12193 eConnectionState_Disconnecting);
12194 /* Issue disconnect to CSR */
12195 INIT_COMPLETION(pAdapter->disconnect_comp_var);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012196
12197 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12198 pAdapter->sessionId,
12199 eCSR_DISCONNECT_REASON_UNSPECIFIED);
12200 /*
12201 * Wait here instead of returning directly, this will block the
12202 * next connect command and allow processing of the scan for
12203 * ssid and the previous connect command in CSR. Else we might
12204 * hit some race conditions leading to SME and HDD out of sync.
12205 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012206 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012207 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
12208 } else if (0 != status) {
12209 hdd_err("csrRoamDisconnect failure, returned %d",
12210 (int)status);
12211 pHddStaCtx->staDebugState = status;
12212 result = -EINVAL;
12213 goto disconnected;
12214 }
12215
12216 rc = wait_for_completion_timeout(
12217 &pAdapter->disconnect_comp_var,
12218 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012219 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012220 hdd_err("Sme disconnect event timed out session Id %d staDebugState %d",
12221 pAdapter->sessionId, pHddStaCtx->staDebugState);
12222 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012223 }
12224 } else if (eConnectionState_Disconnecting ==
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012225 pHddStaCtx->conn_info.connState) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012226 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012227 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012228 if (!rc) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012229 hdd_err("Disconnect event timed out session Id %d staDebugState %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012230 pAdapter->sessionId, pHddStaCtx->staDebugState);
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012231 result = -ETIMEDOUT;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012232 }
12233 }
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012234disconnected:
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012235 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12236 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012237}
12238
12239/**
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012240 * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
12241 * @adapter: Pointer to the HDD adapter
12242 * @req: Pointer to the structure cfg_connect_params receieved from user space
Naveen Rawat07332902016-07-27 09:13:17 -070012243 * @status: out variable for status of reassoc request
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012244 *
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012245 * This function will start reassociation if prev_bssid is set and bssid/
12246 * bssid_hint, channel/channel_hint parameters are present in connect request.
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012247 *
Naveen Rawat07332902016-07-27 09:13:17 -070012248 * Return: true if connect was for ReAssociation, false otherwise
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012249 */
Selvaraj, Sridhara11edcb2016-09-07 18:49:14 +053012250#if defined(CFG80211_CONNECT_PREV_BSSID) || \
12251 (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
Naveen Rawat07332902016-07-27 09:13:17 -070012252static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12253 struct cfg80211_connect_params *req,
12254 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012255{
Naveen Rawat07332902016-07-27 09:13:17 -070012256 bool reassoc = false;
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012257 const uint8_t *bssid = NULL;
12258 uint16_t channel = 0;
12259
12260 if (req->bssid)
12261 bssid = req->bssid;
12262 else if (req->bssid_hint)
12263 bssid = req->bssid_hint;
12264
12265 if (req->channel)
12266 channel = req->channel->hw_value;
12267 else if (req->channel_hint)
12268 channel = req->channel_hint->hw_value;
12269
12270 if (bssid && channel && req->prev_bssid) {
Naveen Rawat07332902016-07-27 09:13:17 -070012271 reassoc = true;
12272 hdd_info(FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
Selvaraj, Sridhar353be2f2016-09-27 15:01:41 +053012273 channel, MAC_ADDR_ARRAY(bssid));
12274 *status = hdd_reassoc(adapter, bssid, channel,
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012275 CONNECT_CMD_USERSPACE);
Naveen Rawat07332902016-07-27 09:13:17 -070012276 hdd_debug("hdd_reassoc: status: %d", *status);
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012277 }
Naveen Rawat07332902016-07-27 09:13:17 -070012278 return reassoc;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012279}
12280#else
Naveen Rawat07332902016-07-27 09:13:17 -070012281static bool wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
12282 struct cfg80211_connect_params *req,
12283 int *status)
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012284{
Naveen Rawat07332902016-07-27 09:13:17 -070012285 return false;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012286}
12287#endif
12288
12289/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012290 * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
12291 * @wiphy: Pointer to wiphy
12292 * @dev: Pointer to network device
12293 * @req: Pointer to cfg80211 connect request
12294 *
12295 * This function is used to start the association process
12296 *
12297 * Return: 0 for success, non-zero for failure
12298 */
12299static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12300 struct net_device *ndev,
12301 struct cfg80211_connect_params *req)
12302{
12303 int status;
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012304 u16 channel;
12305#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
12306 const u8 *bssid_hint = req->bssid_hint;
12307#else
12308 const u8 *bssid_hint = NULL;
12309#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012310 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(ndev);
12311 hdd_context_t *pHddCtx;
12312
12313 ENTER();
12314
Anurag Chouhan6d760662016-02-20 16:05:43 +053012315 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012316 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012317 return -EINVAL;
12318 }
12319
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012320 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012321 TRACE_CODE_HDD_CFG80211_CONNECT,
12322 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012323 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012324 hdd_device_mode_to_string(pAdapter->device_mode),
12325 pAdapter->device_mode);
12326
Krunal Sonib4326f22016-03-10 13:05:51 -080012327 if (pAdapter->device_mode != QDF_STA_MODE &&
12328 pAdapter->device_mode != QDF_P2P_CLIENT_MODE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012329 hdd_err("Device_mode %s(%d) is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012330 hdd_device_mode_to_string(pAdapter->device_mode),
12331 pAdapter->device_mode);
12332 return -EINVAL;
12333 }
12334
12335 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12336 if (!pHddCtx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012337 hdd_err("HDD context is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012338 return -EINVAL;
12339 }
12340
12341 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012342 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012343 return status;
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012344
Naveen Rawat07332902016-07-27 09:13:17 -070012345 if (true == wlan_hdd_reassoc_bssid_hint(pAdapter, req, &status))
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012346 return status;
12347
Agrawal Ashishf156e942016-08-04 14:54:47 +053012348 wlan_hdd_disable_roaming(pAdapter);
12349
12350 /* Try disconnecting if already in connected state */
12351 status = wlan_hdd_try_disconnect(pAdapter);
12352 if (0 > status) {
12353 hdd_err("Failed to disconnect the existing connection");
12354 return -EALREADY;
12355 }
12356
12357 /* Check for max concurrent connections after doing disconnect if any */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012358 if (req->channel) {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012359 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012360 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012361 pAdapter->device_mode),
12362 req->channel->hw_value, HW_MODE_20_MHZ)) {
12363 hdd_err("This concurrency combination is not allowed");
12364 return -ECONNREFUSED;
12365 }
12366 } else {
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012367 if (!cds_allow_concurrency(
Krunal Sonib4326f22016-03-10 13:05:51 -080012368 cds_convert_device_mode_to_qdf_type(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012369 pAdapter->device_mode), 0, HW_MODE_20_MHZ)) {
12370 hdd_err("This concurrency combination is not allowed");
12371 return -ECONNREFUSED;
12372 }
12373 }
Varun Reddy Yeturu3e91dad2016-07-18 15:58:47 -070012374
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012375 /*initialise security parameters */
12376 status = wlan_hdd_cfg80211_set_privacy(pAdapter, req);
12377
12378 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012379 hdd_err("failed to set security params");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012380 return status;
12381 }
12382
Sreelakshmi Konamki6bd8a2e2015-11-03 16:30:32 +053012383 if (req->channel)
12384 channel = req->channel->hw_value;
12385 else
12386 channel = 0;
12387 status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid,
12388 req->ssid_len, req->bssid,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012389 bssid_hint, channel, 0);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012390 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012391 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012392 return status;
12393 }
12394 EXIT();
12395 return status;
12396}
12397
12398/**
12399 * wlan_hdd_cfg80211_connect() - cfg80211 connect api
12400 * @wiphy: Pointer to wiphy
12401 * @dev: Pointer to network device
12402 * @req: Pointer to cfg80211 connect request
12403 *
12404 * Return: 0 for success, non-zero for failure
12405 */
12406static int wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
12407 struct net_device *ndev,
12408 struct cfg80211_connect_params *req)
12409{
12410 int ret;
12411 cds_ssr_protect(__func__);
12412 ret = __wlan_hdd_cfg80211_connect(wiphy, ndev, req);
12413 cds_ssr_unprotect(__func__);
12414
12415 return ret;
12416}
12417
12418/**
12419 * wlan_hdd_disconnect() - hdd disconnect api
12420 * @pAdapter: Pointer to adapter
12421 * @reason: Disconnect reason code
12422 *
12423 * This function is used to issue a disconnect request to SME
12424 *
12425 * Return: 0 for success, non-zero for failure
12426 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070012427static int wlan_hdd_disconnect(hdd_adapter_t *pAdapter, u16 reason)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012428{
12429 int status, result = 0;
12430 unsigned long rc;
12431 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12432 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12433
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012434 ENTER();
12435
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012436 status = wlan_hdd_validate_context(pHddCtx);
12437
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012438 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012439 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012440
12441 /*stop tx queues */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012442 hdd_notice("Disabling queues");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012443 wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE_N_CARRIER,
12444 WLAN_CONTROL_PATH);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012445 hdd_notice("Set HDD connState to eConnectionState_Disconnecting");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012446 pHddStaCtx->conn_info.connState = eConnectionState_Disconnecting;
12447 INIT_COMPLETION(pAdapter->disconnect_comp_var);
12448
12449 /*issue disconnect */
12450
12451 status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
12452 pAdapter->sessionId, reason);
Abhishek Singhacfdc922015-12-30 17:31:21 +053012453 /*
12454 * Wait here instead of returning directly, this will block the next
12455 * connect command and allow processing of the scan for ssid and
12456 * the previous connect command in CSR. Else we might hit some
12457 * race conditions leading to SME and HDD out of sync.
12458 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012459 if (QDF_STATUS_CMD_NOT_QUEUED == status) {
Abhishek Singhbe1849b2016-01-19 14:12:00 +053012460 hdd_info("Already disconnected or connect was in sme/roam pending list and removed by disconnect");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012461 } else if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012462 hdd_err("csr_roam_disconnect failure, returned %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012463 (int)status);
12464 pHddStaCtx->staDebugState = status;
12465 result = -EINVAL;
12466 goto disconnected;
12467 }
12468 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
12469 msecs_to_jiffies
12470 (WLAN_WAIT_TIME_DISCONNECT));
12471
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012472 if (!rc && (QDF_STATUS_CMD_NOT_QUEUED != status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012473 hdd_err("Failed to disconnect, timed out");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012474 result = -ETIMEDOUT;
12475 }
12476disconnected:
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012477 hdd_conn_set_connection_state(pAdapter, eConnectionState_NotConnected);
12478#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
12479 /* Sending disconnect event to userspace for kernel version < 3.11
12480 * is handled by __cfg80211_disconnect call to __cfg80211_disconnected
12481 */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012482 hdd_notice("Send disconnected event to userspace");
Mahesh A Saptasagarc35e8bf2016-06-17 20:03:46 +053012483 wlan_hdd_cfg80211_indicate_disconnect(pAdapter->dev, true,
12484 WLAN_REASON_UNSPECIFIED);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012485#endif
12486
12487 return result;
12488}
12489
12490/**
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012491 * hdd_ieee80211_reason_code_to_str() - return string conversion of reason code
12492 * @reason: ieee80211 reason code.
12493 *
12494 * This utility function helps log string conversion of reason code.
12495 *
12496 * Return: string conversion of reason code, if match found;
12497 * "Unknown" otherwise.
12498 */
12499static const char *hdd_ieee80211_reason_code_to_str(uint16_t reason)
12500{
12501 switch (reason) {
12502 CASE_RETURN_STRING(WLAN_REASON_UNSPECIFIED);
12503 CASE_RETURN_STRING(WLAN_REASON_PREV_AUTH_NOT_VALID);
12504 CASE_RETURN_STRING(WLAN_REASON_DEAUTH_LEAVING);
12505 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
12506 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_AP_BUSY);
12507 CASE_RETURN_STRING(WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
12508 CASE_RETURN_STRING(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
12509 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_STA_HAS_LEFT);
12510 CASE_RETURN_STRING(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
12511 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_POWER);
12512 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_BAD_SUPP_CHAN);
12513 CASE_RETURN_STRING(WLAN_REASON_INVALID_IE);
12514 CASE_RETURN_STRING(WLAN_REASON_MIC_FAILURE);
12515 CASE_RETURN_STRING(WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT);
12516 CASE_RETURN_STRING(WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT);
12517 CASE_RETURN_STRING(WLAN_REASON_IE_DIFFERENT);
12518 CASE_RETURN_STRING(WLAN_REASON_INVALID_GROUP_CIPHER);
12519 CASE_RETURN_STRING(WLAN_REASON_INVALID_PAIRWISE_CIPHER);
12520 CASE_RETURN_STRING(WLAN_REASON_INVALID_AKMP);
12521 CASE_RETURN_STRING(WLAN_REASON_UNSUPP_RSN_VERSION);
12522 CASE_RETURN_STRING(WLAN_REASON_INVALID_RSN_IE_CAP);
12523 CASE_RETURN_STRING(WLAN_REASON_IEEE8021X_FAILED);
12524 CASE_RETURN_STRING(WLAN_REASON_CIPHER_SUITE_REJECTED);
12525 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_UNSPECIFIED_QOS);
12526 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_NO_BANDWIDTH);
12527 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_LOW_ACK);
12528 CASE_RETURN_STRING(WLAN_REASON_DISASSOC_QAP_EXCEED_TXOP);
12529 CASE_RETURN_STRING(WLAN_REASON_QSTA_LEAVE_QBSS);
12530 CASE_RETURN_STRING(WLAN_REASON_QSTA_NOT_USE);
12531 CASE_RETURN_STRING(WLAN_REASON_QSTA_REQUIRE_SETUP);
12532 CASE_RETURN_STRING(WLAN_REASON_QSTA_TIMEOUT);
12533 CASE_RETURN_STRING(WLAN_REASON_QSTA_CIPHER_NOT_SUPP);
12534 CASE_RETURN_STRING(WLAN_REASON_MESH_PEER_CANCELED);
12535 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_PEERS);
12536 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIG);
12537 CASE_RETURN_STRING(WLAN_REASON_MESH_CLOSE);
12538 CASE_RETURN_STRING(WLAN_REASON_MESH_MAX_RETRIES);
12539 CASE_RETURN_STRING(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
12540 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_GTK);
12541 CASE_RETURN_STRING(WLAN_REASON_MESH_INCONSISTENT_PARAM);
12542 CASE_RETURN_STRING(WLAN_REASON_MESH_INVALID_SECURITY);
12543 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_ERROR);
12544 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_NOFORWARD);
12545 CASE_RETURN_STRING(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);
12546 CASE_RETURN_STRING(WLAN_REASON_MAC_EXISTS_IN_MBSS);
12547 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN_REGULATORY);
12548 CASE_RETURN_STRING(WLAN_REASON_MESH_CHAN);
12549 default:
12550 return "Unknown";
12551 }
12552}
12553
12554/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012555 * __wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12556 * @wiphy: Pointer to wiphy
12557 * @dev: Pointer to network device
12558 * @reason: Disconnect reason code
12559 *
12560 * This function is used to issue a disconnect request to SME
12561 *
12562 * Return: 0 for success, non-zero for failure
12563 */
12564static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12565 struct net_device *dev, u16 reason)
12566{
12567 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12568 int status;
12569 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12570 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
12571#ifdef FEATURE_WLAN_TDLS
12572 uint8_t staIdx;
12573#endif
12574
12575 ENTER();
12576
Anurag Chouhan6d760662016-02-20 16:05:43 +053012577 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012578 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012579 return -EINVAL;
12580 }
12581
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012582 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012583 TRACE_CODE_HDD_CFG80211_DISCONNECT,
12584 pAdapter->sessionId, reason));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012585 hdd_notice("Device_mode %s(%d) reason code(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012586 hdd_device_mode_to_string(pAdapter->device_mode),
12587 pAdapter->device_mode, reason);
12588
12589 status = wlan_hdd_validate_context(pHddCtx);
12590
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012591 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012592 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012593
12594 /* Issue disconnect request to SME, if station is in connected state */
12595 if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated) ||
12596 (pHddStaCtx->conn_info.connState == eConnectionState_Connecting)) {
12597 eCsrRoamDisconnectReason reasonCode =
12598 eCSR_DISCONNECT_REASON_UNSPECIFIED;
12599 hdd_scaninfo_t *pScanInfo;
12600
12601 switch (reason) {
12602 case WLAN_REASON_MIC_FAILURE:
12603 reasonCode = eCSR_DISCONNECT_REASON_MIC_ERROR;
12604 break;
12605
12606 case WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY:
12607 case WLAN_REASON_DISASSOC_AP_BUSY:
12608 case WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
12609 reasonCode = eCSR_DISCONNECT_REASON_DISASSOC;
12610 break;
12611
12612 case WLAN_REASON_PREV_AUTH_NOT_VALID:
12613 case WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
12614 reasonCode = eCSR_DISCONNECT_REASON_DEAUTH;
12615 break;
12616
12617 case WLAN_REASON_DEAUTH_LEAVING:
12618 reasonCode =
12619 pHddCtx->config->
12620 gEnableDeauthToDisassocMap ?
12621 eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
12622 eCSR_DISCONNECT_REASON_DEAUTH;
12623 break;
12624 case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
12625 reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
12626 break;
12627 default:
12628 reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
12629 break;
12630 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012631 hdd_notice("convert to internal reason %d to reasonCode %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012632 reason, reasonCode);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012633 pScanInfo = &pAdapter->scan_info;
12634 if (pScanInfo->mScanPending) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012635 hdd_notice("Disconnect is in progress, Aborting Scan");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012636 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
12637 eCSR_SCAN_ABORT_DEFAULT);
12638 }
Edhar, Mahesh Kumar732f6982016-07-01 11:23:06 +053012639 wlan_hdd_cleanup_remain_on_channel_ctx(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012640#ifdef FEATURE_WLAN_TDLS
12641 /* First clean up the tdls peers if any */
12642 for (staIdx = 0; staIdx < pHddCtx->max_num_tdls_sta; staIdx++) {
12643 if ((pHddCtx->tdlsConnInfo[staIdx].sessionId ==
12644 pAdapter->sessionId)
12645 && (pHddCtx->tdlsConnInfo[staIdx].staId)) {
12646 uint8_t *mac;
12647 mac =
12648 pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012649 hdd_notice("call sme_delete_tdls_peer_sta staId %d sessionId %d "
12650 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012651 pHddCtx->tdlsConnInfo[staIdx].staId,
12652 pAdapter->sessionId,
12653 MAC_ADDR_ARRAY(mac));
12654 sme_delete_tdls_peer_sta(WLAN_HDD_GET_HAL_CTX
12655 (pAdapter),
12656 pAdapter->sessionId, mac);
12657 }
12658 }
12659#endif
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012660 hdd_notice("Disconnecting with reasoncode:%u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012661 reasonCode);
Srinivas Girigowdaf2599dd2015-11-16 18:20:46 -080012662 hdd_info("Disconnect request from user space with reason: %s",
12663 hdd_ieee80211_reason_code_to_str(reason));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012664 status = wlan_hdd_disconnect(pAdapter, reasonCode);
12665 if (0 != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012666 hdd_err("failure, returned %d", status);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012667 return -EINVAL;
12668 }
12669 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012670 hdd_err("unexpected cfg disconnect called while in state (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012671 pHddStaCtx->conn_info.connState);
12672 }
12673
12674 return status;
12675}
12676
12677/**
12678 * wlan_hdd_cfg80211_disconnect() - cfg80211 disconnect api
12679 * @wiphy: Pointer to wiphy
12680 * @dev: Pointer to network device
12681 * @reason: Disconnect reason code
12682 *
12683 * Return: 0 for success, non-zero for failure
12684 */
12685static int wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
12686 struct net_device *dev, u16 reason)
12687{
12688 int ret;
12689 cds_ssr_protect(__func__);
12690 ret = __wlan_hdd_cfg80211_disconnect(wiphy, dev, reason);
12691 cds_ssr_unprotect(__func__);
12692
12693 return ret;
12694}
12695
12696/**
12697 * wlan_hdd_cfg80211_set_privacy_ibss() - set ibss privacy
12698 * @pAdapter: Pointer to adapter
12699 * @param: Pointer to IBSS parameters
12700 *
12701 * This function is used to initialize the security settings in IBSS mode
12702 *
12703 * Return: 0 for success, non-zero for failure
12704 */
12705static int wlan_hdd_cfg80211_set_privacy_ibss(hdd_adapter_t *pAdapter,
12706 struct cfg80211_ibss_params
12707 *params)
12708{
12709 int status = 0;
12710 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12711 eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE;
12712 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12713
12714 ENTER();
12715
12716 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED;
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012717 qdf_mem_zero(&pHddStaCtx->ibss_enc_key, sizeof(tCsrRoamSetKey));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012718 pHddStaCtx->ibss_enc_key_installed = 0;
12719
12720 if (params->ie_len && (NULL != params->ie)) {
12721 if (wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12722 params->ie_len, WLAN_EID_RSN)) {
12723 pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2;
12724 encryptionType = eCSR_ENCRYPT_TYPE_AES;
12725 } else if (hdd_is_wpaie_present(params->ie, params->ie_len)) {
12726 tDot11fIEWPA dot11WPAIE;
12727 tHalHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
12728 u8 *ie;
12729
12730 memset(&dot11WPAIE, 0, sizeof(dot11WPAIE));
12731 ie = wlan_hdd_cfg80211_get_ie_ptr(params->ie,
12732 params->ie_len,
12733 DOT11F_EID_WPA);
12734 if (NULL != ie) {
12735 pWextState->wpaVersion =
12736 IW_AUTH_WPA_VERSION_WPA;
12737 /* Unpack the WPA IE */
12738 /* Skip past the EID byte and length byte - and four byte WiFi OUI */
12739 dot11f_unpack_ie_wpa((tpAniSirGlobal) halHandle,
12740 &ie[2 + 4],
12741 ie[1] - 4, &dot11WPAIE);
12742 /*Extract the multicast cipher, the encType for unicast
12743 cipher for wpa-none is none */
12744 encryptionType =
12745 hdd_translate_wpa_to_csr_encryption_type
12746 (dot11WPAIE.multicast_cipher);
12747 }
12748 }
12749
12750 status =
12751 wlan_hdd_cfg80211_set_ie(pAdapter, params->ie,
12752 params->ie_len);
12753
12754 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012755 hdd_err("failed to parse WPA/RSN IE");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012756 return status;
12757 }
12758 }
12759
12760 pWextState->roamProfile.AuthType.authType[0] =
12761 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
12762
12763 if (params->privacy) {
12764 /* Security enabled IBSS, At this time there is no information
12765 * available about the security paramters, so initialise the
12766 * encryption type to eCSR_ENCRYPT_TYPE_WEP40_STATICKEY.
12767 * The correct security parameters will be updated later in
12768 * wlan_hdd_cfg80211_add_key Hal expects encryption type to be
12769 * set inorder enable privacy bit in beacons
12770 */
12771
12772 encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY;
12773 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012774 hdd_info("encryptionType=%d", encryptionType);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012775 pHddStaCtx->conn_info.ucEncryptionType = encryptionType;
12776 pWextState->roamProfile.EncryptionType.numEntries = 1;
12777 pWextState->roamProfile.EncryptionType.encryptionType[0] =
12778 encryptionType;
12779 return status;
12780}
12781
12782/**
12783 * __wlan_hdd_cfg80211_join_ibss() - join ibss
12784 * @wiphy: Pointer to wiphy
12785 * @dev: Pointer to network device
12786 * @param: Pointer to IBSS join parameters
12787 *
12788 * This function is used to create/join an IBSS network
12789 *
12790 * Return: 0 for success, non-zero for failure
12791 */
12792static int __wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
12793 struct net_device *dev,
12794 struct cfg80211_ibss_params *params)
12795{
12796 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12797 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
12798 tCsrRoamProfile *pRoamProfile;
12799 int status;
12800 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
12801 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
Anurag Chouhan6d760662016-02-20 16:05:43 +053012802 struct qdf_mac_addr bssid;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012803 u8 channelNum = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012804
12805 ENTER();
12806
Anurag Chouhan6d760662016-02-20 16:05:43 +053012807 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012808 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012809 return -EINVAL;
12810 }
12811
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053012812 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012813 TRACE_CODE_HDD_CFG80211_JOIN_IBSS,
12814 pAdapter->sessionId, pAdapter->device_mode));
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012815 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012816 hdd_device_mode_to_string(pAdapter->device_mode),
12817 pAdapter->device_mode);
12818
12819 status = wlan_hdd_validate_context(pHddCtx);
12820
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012821 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012822 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012823
12824 if (NULL !=
Anurag Chouhance0dc992016-02-16 18:18:03 +053012825 params->chandef.chan) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012826 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
12827 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
12828 tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
12829 int indx;
12830
12831 /* Get channel number */
12832 channelNum = ieee80211_frequency_to_channel(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012833 params->
12834 chandef.
12835 chan->
12836 center_freq);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012837
12838 if (0 != sme_cfg_get_str(hHal, WNI_CFG_VALID_CHANNEL_LIST,
12839 validChan, &numChans)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012840 hdd_err("No valid channel list");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012841 return -EOPNOTSUPP;
12842 }
12843
12844 for (indx = 0; indx < numChans; indx++) {
12845 if (channelNum == validChan[indx]) {
12846 break;
12847 }
12848 }
12849 if (indx >= numChans) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012850 hdd_err("Not valid Channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012851 return -EINVAL;
12852 }
12853 }
12854
Tushnim Bhattacharyyaca50b322015-12-28 17:14:36 -080012855 if (!cds_allow_concurrency(CDS_IBSS_MODE, channelNum,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012856 HW_MODE_20_MHZ)) {
12857 hdd_err("This concurrency combination is not allowed");
12858 return -ECONNREFUSED;
12859 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012860
Krunal Soni3091bcc2016-06-23 12:28:21 -070012861 status = qdf_reset_connection_update();
12862 if (!QDF_IS_STATUS_SUCCESS(status))
12863 hdd_err("ERR: clear event failed");
12864
12865 status = cds_current_connections_update(pAdapter->sessionId,
12866 channelNum,
12867 SIR_UPDATE_REASON_JOIN_IBSS);
12868 if (QDF_STATUS_E_FAILURE == status) {
12869 hdd_err("ERROR: connections update failed!!");
12870 return -EINVAL;
12871 }
12872
12873 if (QDF_STATUS_SUCCESS == status) {
12874 status = qdf_wait_for_connection_update();
12875 if (!QDF_IS_STATUS_SUCCESS(status)) {
12876 hdd_err("ERROR: qdf wait for event failed!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012877 return -EINVAL;
12878 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012879 }
12880
12881 /*Try disconnecting if already in connected state */
12882 status = wlan_hdd_try_disconnect(pAdapter);
12883 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012884 hdd_err("Failed to disconnect the existing IBSS connection");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012885 return -EALREADY;
12886 }
12887
12888 pRoamProfile = &pWextState->roamProfile;
12889
12890 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012891 hdd_err("Interface type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012892 return -EINVAL;
12893 }
12894
12895 /* enable selected protection checks in IBSS mode */
12896 pRoamProfile->cfg_protection = IBSS_CFG_PROTECTION_ENABLE_MASK;
12897
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012898 if (QDF_STATUS_E_FAILURE == sme_cfg_set_int(pHddCtx->hHal,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012899 WNI_CFG_IBSS_ATIM_WIN_SIZE,
12900 pHddCtx->config->
12901 ibssATIMWinSize)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012902 hdd_err("Could not pass on WNI_CFG_IBSS_ATIM_WIN_SIZE to CCM");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012903 }
12904
12905 /* BSSID is provided by upper layers hence no need to AUTO generate */
12906 if (NULL != params->bssid) {
12907 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012908 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012909 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012910 return -EIO;
12911 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053012912 qdf_mem_copy(bssid.bytes, params->bssid, QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012913 } else if (pHddCtx->config->isCoalesingInIBSSAllowed == 0) {
12914 if (sme_cfg_set_int(pHddCtx->hHal, WNI_CFG_IBSS_AUTO_BSSID, 0)
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053012915 == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012916 hdd_err("ccmCfgStInt failed for WNI_CFG_IBSS_AUTO_BSSID");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012917 return -EIO;
12918 }
Anurag Chouhanc5548422016-02-24 18:33:27 +053012919 qdf_copy_macaddr(&bssid, &pHddCtx->config->IbssBssid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012920 }
12921 if ((params->beacon_interval > CFG_BEACON_INTERVAL_MIN)
12922 && (params->beacon_interval <= CFG_BEACON_INTERVAL_MAX))
12923 pRoamProfile->beaconInterval = params->beacon_interval;
12924 else {
12925 pRoamProfile->beaconInterval = CFG_BEACON_INTERVAL_DEFAULT;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012926 hdd_info("input beacon interval %d TU is invalid, use default %d TU",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012927 params->beacon_interval, pRoamProfile->beaconInterval);
12928 }
12929
12930 /* Set Channel */
12931 if (channelNum) {
12932 /* Set the Operational Channel */
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012933 hdd_info("set channel %d", channelNum);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012934 pRoamProfile->ChannelInfo.numOfChannels = 1;
12935 pHddStaCtx->conn_info.operationChannel = channelNum;
12936 pRoamProfile->ChannelInfo.ChannelList =
12937 &pHddStaCtx->conn_info.operationChannel;
12938 }
12939
12940 /* Initialize security parameters */
12941 status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params);
12942 if (status < 0) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012943 hdd_err("failed to set security parameters");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012944 return status;
12945 }
12946
12947 /* Issue connect start */
12948 status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid,
12949 params->ssid_len,
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012950 bssid.bytes, NULL,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012951 pHddStaCtx->conn_info.
Naveen Rawatc77e6e72016-08-05 15:19:03 -070012952 operationChannel,
12953 params->chandef.width);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012954
12955 if (0 > status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070012956 hdd_err("connect failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012957 return status;
12958 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053012959 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080012960 return 0;
12961}
12962
12963/**
12964 * wlan_hdd_cfg80211_join_ibss() - join ibss
12965 * @wiphy: Pointer to wiphy
12966 * @dev: Pointer to network device
12967 * @param: Pointer to IBSS join parameters
12968 *
12969 * This function is used to create/join an IBSS network
12970 *
12971 * Return: 0 for success, non-zero for failure
12972 */
12973static int wlan_hdd_cfg80211_join_ibss(struct wiphy *wiphy,
12974 struct net_device *dev,
12975 struct cfg80211_ibss_params *params)
12976{
12977 int ret = 0;
12978
12979 cds_ssr_protect(__func__);
12980 ret = __wlan_hdd_cfg80211_join_ibss(wiphy, dev, params);
12981 cds_ssr_unprotect(__func__);
12982
12983 return ret;
12984}
12985
12986/**
12987 * __wlan_hdd_cfg80211_leave_ibss() - leave ibss
12988 * @wiphy: Pointer to wiphy
12989 * @dev: Pointer to network device
12990 *
12991 * This function is used to leave an IBSS network
12992 *
12993 * Return: 0 for success, non-zero for failure
12994 */
12995static int __wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
12996 struct net_device *dev)
12997{
12998 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
12999 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
13000 tCsrRoamProfile *pRoamProfile;
13001 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13002 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013003 QDF_STATUS hal_status;
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013004 unsigned long rc;
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013005 tSirUpdateIE updateIE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013006
13007 ENTER();
13008
Anurag Chouhan6d760662016-02-20 16:05:43 +053013009 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013010 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013011 return -EINVAL;
13012 }
13013
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013014 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013015 TRACE_CODE_HDD_CFG80211_LEAVE_IBSS,
13016 pAdapter->sessionId,
13017 eCSR_DISCONNECT_REASON_IBSS_LEAVE));
13018 status = wlan_hdd_validate_context(pHddCtx);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013019 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013020 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013021
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013022 hdd_notice("Device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013023 hdd_device_mode_to_string(pAdapter->device_mode),
13024 pAdapter->device_mode);
13025 if (NULL == pWextState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013026 hdd_err("Data Storage Corruption");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013027 return -EIO;
13028 }
13029
13030 pRoamProfile = &pWextState->roamProfile;
13031
13032 /* Issue disconnect only if interface type is set to IBSS */
13033 if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013034 hdd_err("BSS Type is not set to IBSS");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013035 return -EINVAL;
13036 }
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013037 /* Clearing add IE of beacon */
13038 qdf_mem_copy(updateIE.bssid.bytes, pAdapter->macAddressCurrent.bytes,
13039 sizeof(tSirMacAddr));
13040 updateIE.smeSessionId = pAdapter->sessionId;
13041 updateIE.ieBufferlength = 0;
13042 updateIE.pAdditionIEBuffer = NULL;
13043 updateIE.append = true;
13044 updateIE.notify = true;
13045 if (sme_update_add_ie(WLAN_HDD_GET_HAL_CTX(pAdapter),
13046 &updateIE,
13047 eUPDATE_IE_PROBE_BCN) == QDF_STATUS_E_FAILURE) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013048 hdd_err("Could not pass on PROBE_RSP_BCN data to PE");
Rajeev Kumar8e3e2832015-11-06 16:02:54 -080013049 }
13050
13051 /* Reset WNI_CFG_PROBE_RSP Flags */
13052 wlan_hdd_reset_prob_rspies(pAdapter);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013053
13054 /* Issue Disconnect request */
13055 INIT_COMPLETION(pAdapter->disconnect_comp_var);
13056 hal_status = sme_roam_disconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
13057 pAdapter->sessionId,
13058 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013059 if (!QDF_IS_STATUS_SUCCESS(hal_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013060 hdd_err("sme_roam_disconnect failed hal_status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013061 hal_status);
13062 return -EAGAIN;
13063 }
Chandrasekaran, Manishekar12a818a2015-12-18 11:44:56 +053013064
13065 /* wait for mc thread to cleanup and then return to upper stack
13066 * so by the time upper layer calls the change interface, we are
13067 * all set to proceed further
13068 */
13069 rc = wait_for_completion_timeout(&pAdapter->disconnect_comp_var,
13070 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
13071 if (!rc) {
13072 hdd_err("Failed to disconnect, timed out");
13073 return -ETIMEDOUT;
13074 }
13075
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013076 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013077 return 0;
13078}
13079
13080/**
13081 * wlan_hdd_cfg80211_leave_ibss() - leave ibss
13082 * @wiphy: Pointer to wiphy
13083 * @dev: Pointer to network device
13084 *
13085 * This function is used to leave an IBSS network
13086 *
13087 * Return: 0 for success, non-zero for failure
13088 */
13089static int wlan_hdd_cfg80211_leave_ibss(struct wiphy *wiphy,
13090 struct net_device *dev)
13091{
13092 int ret = 0;
13093
13094 cds_ssr_protect(__func__);
13095 ret = __wlan_hdd_cfg80211_leave_ibss(wiphy, dev);
13096 cds_ssr_unprotect(__func__);
13097
13098 return ret;
13099}
13100
13101/**
13102 * __wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13103 * @wiphy: Pointer to wiphy
13104 * @changed: Parameters changed
13105 *
13106 * This function is used to set the phy parameters. RTS Threshold/FRAG
13107 * Threshold/Retry Count etc.
13108 *
13109 * Return: 0 for success, non-zero for failure
13110 */
13111static int __wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy,
13112 u32 changed)
13113{
13114 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13115 tHalHandle hHal = pHddCtx->hHal;
13116 int status;
13117
13118 ENTER();
13119
Anurag Chouhan6d760662016-02-20 16:05:43 +053013120 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013121 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013122 return -EINVAL;
13123 }
13124
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013125 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013126 TRACE_CODE_HDD_CFG80211_SET_WIPHY_PARAMS,
13127 NO_SESSION, wiphy->rts_threshold));
13128 status = wlan_hdd_validate_context(pHddCtx);
13129
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013130 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013131 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013132
13133 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
13134 u32 rts_threshold = (wiphy->rts_threshold == -1) ?
13135 WNI_CFG_RTS_THRESHOLD_STAMAX : wiphy->rts_threshold;
13136
13137 if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) ||
13138 (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013139 hdd_err("Invalid RTS Threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013140 rts_threshold);
13141 return -EINVAL;
13142 }
13143
13144 if (0 != sme_cfg_set_int(hHal, WNI_CFG_RTS_THRESHOLD,
13145 rts_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013146 hdd_err("sme_cfg_set_int failed for rts_threshold value %u",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013147 rts_threshold);
13148 return -EIO;
13149 }
13150
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013151 hdd_info("set rts threshold %u", rts_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013152 }
13153
13154 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
13155 u16 frag_threshold = (wiphy->frag_threshold == -1) ?
13156 WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX :
13157 wiphy->frag_threshold;
13158
13159 if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold) ||
13160 (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013161 hdd_err("Invalid frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013162 frag_threshold);
13163 return -EINVAL;
13164 }
13165
13166 if (0 != sme_cfg_set_int(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD,
13167 frag_threshold)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013168 hdd_err("sme_cfg_set_int failed for frag_threshold value %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013169 frag_threshold);
13170 return -EIO;
13171 }
13172
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013173 hdd_info("set frag threshold %hu", frag_threshold);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013174 }
13175
13176 if ((changed & WIPHY_PARAM_RETRY_SHORT)
13177 || (changed & WIPHY_PARAM_RETRY_LONG)) {
13178 u8 retry_value = (changed & WIPHY_PARAM_RETRY_SHORT) ?
13179 wiphy->retry_short : wiphy->retry_long;
13180
13181 if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) ||
13182 (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013183 hdd_err("Invalid Retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013184 return -EINVAL;
13185 }
13186
13187 if (changed & WIPHY_PARAM_RETRY_SHORT) {
13188 if (0 != sme_cfg_set_int(hHal,
13189 WNI_CFG_LONG_RETRY_LIMIT,
13190 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013191 hdd_err("sme_cfg_set_int failed for long retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013192 retry_value);
13193 return -EIO;
13194 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013195 hdd_info("set long retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013196 } else if (changed & WIPHY_PARAM_RETRY_SHORT) {
13197 if (0 != sme_cfg_set_int(hHal,
13198 WNI_CFG_SHORT_RETRY_LIMIT,
13199 retry_value)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013200 hdd_err("sme_cfg_set_int failed for short retry count %hu",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013201 retry_value);
13202 return -EIO;
13203 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013204 hdd_info("set short retry count %hu", retry_value);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013205 }
13206 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013207 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013208 return 0;
13209}
13210
13211/**
13212 * wlan_hdd_cfg80211_set_wiphy_params() - set wiphy parameters
13213 * @wiphy: Pointer to wiphy
13214 * @changed: Parameters changed
13215 *
13216 * Return: 0 for success, non-zero for failure
13217 */
13218static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
13219{
13220 int ret;
13221
13222 cds_ssr_protect(__func__);
13223 ret = __wlan_hdd_cfg80211_set_wiphy_params(wiphy, changed);
13224 cds_ssr_unprotect(__func__);
13225
13226 return ret;
13227}
13228
13229/**
13230 * __wlan_hdd_set_default_mgmt_key() - dummy implementation of set default mgmt
13231 * key
13232 * @wiphy: Pointer to wiphy
13233 * @dev: Pointer to network device
13234 * @key_index: Key index
13235 *
13236 * Return: 0
13237 */
13238static int __wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13239 struct net_device *netdev,
13240 u8 key_index)
13241{
13242 ENTER();
13243 return 0;
13244}
13245
13246/**
13247 * wlan_hdd_set_default_mgmt_key() - SSR wrapper for
13248 * wlan_hdd_set_default_mgmt_key
13249 * @wiphy: pointer to wiphy
13250 * @netdev: pointer to net_device structure
13251 * @key_index: key index
13252 *
13253 * Return: 0 on success, error number on failure
13254 */
13255static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy,
13256 struct net_device *netdev,
13257 u8 key_index)
13258{
13259 int ret;
13260
13261 cds_ssr_protect(__func__);
13262 ret = __wlan_hdd_set_default_mgmt_key(wiphy, netdev, key_index);
13263 cds_ssr_unprotect(__func__);
13264
13265 return ret;
13266}
13267
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013268/**
13269 * __wlan_hdd_set_txq_params() - dummy implementation of set tx queue params
13270 * @wiphy: Pointer to wiphy
13271 * @dev: Pointer to network device
13272 * @params: Pointer to tx queue parameters
13273 *
13274 * Return: 0
13275 */
13276static int __wlan_hdd_set_txq_params(struct wiphy *wiphy,
13277 struct net_device *dev,
13278 struct ieee80211_txq_params *params)
13279{
13280 ENTER();
13281 return 0;
13282}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013283
13284/**
13285 * wlan_hdd_set_txq_params() - SSR wrapper for wlan_hdd_set_txq_params
13286 * @wiphy: pointer to wiphy
13287 * @netdev: pointer to net_device structure
13288 * @params: pointer to ieee80211_txq_params
13289 *
13290 * Return: 0 on success, error number on failure
13291 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013292static int wlan_hdd_set_txq_params(struct wiphy *wiphy,
13293 struct net_device *dev,
13294 struct ieee80211_txq_params *params)
13295{
13296 int ret;
13297
13298 cds_ssr_protect(__func__);
13299 ret = __wlan_hdd_set_txq_params(wiphy, dev, params);
13300 cds_ssr_unprotect(__func__);
13301
13302 return ret;
13303}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013304
13305/**
13306 * __wlan_hdd_cfg80211_del_station() - delete station v2
13307 * @wiphy: Pointer to wiphy
13308 * @param: Pointer to delete station parameter
13309 *
13310 * Return: 0 for success, non-zero for failure
13311 */
13312static
13313int __wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13314 struct net_device *dev,
13315 struct tagCsrDelStaParams *pDelStaParams)
13316{
13317 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13318 hdd_context_t *pHddCtx;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013319 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013320 hdd_hostapd_state_t *hapd_state;
13321 int status;
13322 uint8_t staId;
13323 uint8_t *mac;
13324
13325 ENTER();
13326
Anurag Chouhan6d760662016-02-20 16:05:43 +053013327 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013328 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013329 return -EINVAL;
13330 }
13331
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013332 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013333 TRACE_CODE_HDD_CFG80211_DEL_STA,
13334 pAdapter->sessionId, pAdapter->device_mode));
13335
13336 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13337 status = wlan_hdd_validate_context(pHddCtx);
13338
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013339 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013340 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013341
13342 mac = (uint8_t *) pDelStaParams->peerMacAddr.bytes;
13343
Krunal Sonib4326f22016-03-10 13:05:51 -080013344 if ((QDF_SAP_MODE == pAdapter->device_mode) ||
13345 (QDF_P2P_GO_MODE == pAdapter->device_mode)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013346
13347 hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
13348 if (!hapd_state) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013349 hdd_err("Hostapd State is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013350 return 0;
13351 }
13352
Anurag Chouhanc5548422016-02-24 18:33:27 +053013353 if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013354 uint16_t i;
13355 for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
13356 if ((pAdapter->aStaInfo[i].isUsed) &&
13357 (!pAdapter->aStaInfo[i].
13358 isDeauthInProgress)) {
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013359 qdf_mem_copy(
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013360 mac,
13361 pAdapter->aStaInfo[i].
13362 macAddrSTA.bytes,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013363 QDF_MAC_ADDR_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013364 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13365 hdd_ipa_wlan_evt(pAdapter,
13366 pAdapter->
13367 aStaInfo[i].
13368 ucSTAId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013369 HDD_IPA_CLIENT_DISCONNECT,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013370 mac);
13371 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013372 hdd_notice("Delete STA with MAC::"
13373 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013374 MAC_ADDR_ARRAY(mac));
13375
13376 if (pHddCtx->dev_dfs_cac_status ==
13377 DFS_CAC_IN_PROGRESS)
13378 goto fn_end;
13379
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013380 qdf_event_reset(&hapd_state->qdf_event);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013381 hdd_softap_sta_disassoc(pAdapter,
Deepthi Gowrib3bfefd2016-09-13 15:14:34 +053013382 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013383 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013384 hdd_softap_sta_deauth(pAdapter,
13385 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013386 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013387 pAdapter->aStaInfo[i].
13388 isDeauthInProgress = true;
Anurag Chouhance0dc992016-02-16 18:18:03 +053013389 qdf_status =
13390 qdf_wait_single_event(
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013391 &hapd_state->qdf_event,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013392 1000);
Anurag Chouhance0dc992016-02-16 18:18:03 +053013393 if (!QDF_IS_STATUS_SUCCESS(
13394 qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013395 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013396 }
13397 }
13398 }
13399 } else {
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013400 qdf_status =
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013401 hdd_softap_get_sta_id(pAdapter,
Anurag Chouhan6d760662016-02-20 16:05:43 +053013402 (struct qdf_mac_addr *) mac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013403 &staId);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013404 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013405 hdd_notice("Skip DEL STA as this is not used::"
13406 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013407 MAC_ADDR_ARRAY(mac));
13408 return -ENOENT;
13409 }
13410
13411 if (hdd_ipa_uc_is_enabled(pHddCtx)) {
13412 hdd_ipa_wlan_evt(pAdapter, staId,
Mohit Khannafa99aea2016-05-12 21:43:13 -070013413 HDD_IPA_CLIENT_DISCONNECT, mac);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013414 }
13415
13416 if (pAdapter->aStaInfo[staId].isDeauthInProgress ==
13417 true) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013418 hdd_notice("Skip DEL STA as deauth is in progress::"
13419 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013420 MAC_ADDR_ARRAY(mac));
13421 return -ENOENT;
13422 }
13423
13424 pAdapter->aStaInfo[staId].isDeauthInProgress = true;
13425
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013426 hdd_notice("Delete STA with MAC::" MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013427 MAC_ADDR_ARRAY(mac));
13428
13429 /* Case: SAP in ACS selected DFS ch and client connected
13430 * Now Radar detected. Then if random channel is another
13431 * DFS ch then new CAC is initiated and no TX allowed.
13432 * So do not send any mgmt frames as it will timeout
13433 * during CAC.
13434 */
13435
13436 if (pHddCtx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
13437 goto fn_end;
13438
Anurag Chouhanf04e84f2016-03-03 10:12:12 +053013439 qdf_event_reset(&hapd_state->qdf_event);
Kondabattini, Ganesh3f2d02c2016-09-13 12:23:47 +053013440 sme_send_disassoc_req_frame(WLAN_HDD_GET_HAL_CTX
13441 (pAdapter), pAdapter->sessionId,
13442 (uint8_t *)&pDelStaParams->peerMacAddr,
13443 pDelStaParams->reason_code, 0);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013444 qdf_status = hdd_softap_sta_deauth(pAdapter,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013445 pDelStaParams);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013446 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013447 pAdapter->aStaInfo[staId].isDeauthInProgress =
13448 false;
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013449 hdd_notice("STA removal failed for ::"
13450 MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013451 MAC_ADDR_ARRAY(mac));
13452 return -ENOENT;
13453 } else {
Anurag Chouhance0dc992016-02-16 18:18:03 +053013454 qdf_status = 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(qdf_status))
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013458 hdd_err("Deauth wait time expired");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013459 }
13460 }
13461 }
13462
13463fn_end:
13464 EXIT();
13465 return 0;
13466}
13467
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013468#if defined(USE_CFG80211_DEL_STA_V2)
13469/**
13470 * wlan_hdd_del_station() - delete station wrapper
13471 * @adapter: pointer to the hdd adapter
13472 *
13473 * Return: None
13474 */
13475void wlan_hdd_del_station(hdd_adapter_t *adapter)
13476{
13477 struct station_del_parameters del_sta;
13478 del_sta.mac = NULL;
13479 del_sta.subtype = SIR_MAC_MGMT_DEAUTH >> 4;
13480 del_sta.reason_code = eCsrForcedDeauthSta;
13481
13482 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev,
13483 &del_sta);
13484}
13485#else
13486void wlan_hdd_del_station(hdd_adapter_t *adapter)
13487{
13488 wlan_hdd_cfg80211_del_station(adapter->wdev.wiphy, adapter->dev, NULL);
13489}
13490#endif
13491
13492#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013493/**
13494 * wlan_hdd_cfg80211_del_station() - delete station v2
13495 * @wiphy: Pointer to wiphy
13496 * @param: Pointer to delete station parameter
13497 *
13498 * Return: 0 for success, non-zero for failure
13499 */
13500int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13501 struct net_device *dev,
13502 struct station_del_parameters *param)
13503#else
13504/**
13505 * wlan_hdd_cfg80211_del_station() - delete station
13506 * @wiphy: Pointer to wiphy
13507 * @mac: Pointer to station mac address
13508 *
13509 * Return: 0 for success, non-zero for failure
13510 */
13511#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13512int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13513 struct net_device *dev,
13514 const uint8_t *mac)
13515#else
13516int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy,
13517 struct net_device *dev,
13518 uint8_t *mac)
13519#endif
13520#endif
13521{
13522 int ret;
13523 struct tagCsrDelStaParams delStaParams;
13524
13525 cds_ssr_protect(__func__);
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013526#if defined(USE_CFG80211_DEL_STA_V2)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013527 if (NULL == param) {
Ryan Hsu8ecb0fa2016-01-18 15:40:55 -080013528 hdd_err("Invalid argument passed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013529 return -EINVAL;
13530 }
13531 wlansap_populate_del_sta_params(param->mac, param->reason_code,
13532 param->subtype, &delStaParams);
13533#else
13534 wlansap_populate_del_sta_params(mac, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
13535 (SIR_MAC_MGMT_DEAUTH >> 4),
13536 &delStaParams);
13537#endif
13538 ret = __wlan_hdd_cfg80211_del_station(wiphy, dev, &delStaParams);
13539 cds_ssr_unprotect(__func__);
13540
13541 return ret;
13542}
13543
13544/**
13545 * __wlan_hdd_cfg80211_add_station() - add station
13546 * @wiphy: Pointer to wiphy
13547 * @mac: Pointer to station mac address
13548 * @pmksa: Pointer to add station parameter
13549 *
13550 * Return: 0 for success, non-zero for failure
13551 */
13552static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13553 struct net_device *dev,
13554 const uint8_t *mac,
13555 struct station_parameters *params)
13556{
13557 int status = -EPERM;
13558#ifdef FEATURE_WLAN_TDLS
13559 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13560 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13561 u32 mask, set;
13562
13563 ENTER();
13564
Anurag Chouhan6d760662016-02-20 16:05:43 +053013565 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013566 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013567 return -EINVAL;
13568 }
13569
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013570 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013571 TRACE_CODE_HDD_CFG80211_ADD_STA,
13572 pAdapter->sessionId, params->listen_interval));
13573
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013574 if (0 != wlan_hdd_validate_context(pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013575 return -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013576
13577 mask = params->sta_flags_mask;
13578
13579 set = params->sta_flags_set;
13580
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013581 hdd_notice("mask 0x%x set 0x%x " MAC_ADDRESS_STR, mask, set,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013582 MAC_ADDR_ARRAY(mac));
13583
13584 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13585 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
13586 status =
13587 wlan_hdd_tdls_add_station(wiphy, dev, mac, 0, NULL);
13588 }
13589 }
13590#endif
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013591 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013592 return status;
13593}
13594
13595/**
13596 * wlan_hdd_cfg80211_add_station() - add station
13597 * @wiphy: Pointer to wiphy
13598 * @mac: Pointer to station mac address
13599 * @pmksa: Pointer to add station parameter
13600 *
13601 * Return: 0 for success, non-zero for failure
13602 */
13603#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
13604static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13605 struct net_device *dev,
13606 const uint8_t *mac,
13607 struct station_parameters *params)
13608#else
13609static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
13610 struct net_device *dev, uint8_t *mac,
13611 struct station_parameters *params)
13612#endif
13613{
13614 int ret;
13615
13616 cds_ssr_protect(__func__);
13617 ret = __wlan_hdd_cfg80211_add_station(wiphy, dev, mac, params);
13618 cds_ssr_unprotect(__func__);
13619
13620 return ret;
13621}
13622
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013623/**
13624 * __wlan_hdd_cfg80211_set_pmksa() - set pmksa
13625 * @wiphy: Pointer to wiphy
13626 * @dev: Pointer to network device
13627 * @pmksa: Pointer to set pmksa parameter
13628 *
13629 * Return: 0 for success, non-zero for failure
13630 */
13631static int __wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13632 struct net_device *dev,
13633 struct cfg80211_pmksa *pmksa)
13634{
13635 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13636 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13637 tHalHandle halHandle;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013638 QDF_STATUS result = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013639 int status;
13640 tPmkidCacheInfo pmk_id;
13641
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013642 ENTER();
13643
Anurag Chouhan6d760662016-02-20 16:05:43 +053013644 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013645 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013646 return -EINVAL;
13647 }
13648
13649 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013650 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013651 return -EINVAL;
13652 }
13653
13654 if (!pmksa->bssid || !pmksa->pmkid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013655 hdd_err("pmksa->bssid(%p) or pmksa->pmkid(%p) is NULL",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013656 pmksa->bssid, pmksa->pmkid);
13657 return -EINVAL;
13658 }
13659
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013660 hdd_warn("set PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013661 MAC_ADDR_ARRAY(pmksa->bssid));
13662
13663 status = wlan_hdd_validate_context(pHddCtx);
13664
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013665 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013666 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013667
13668 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13669
Anurag Chouhan600c3a02016-03-01 10:33:54 +053013670 qdf_mem_copy(pmk_id.BSSID.bytes, pmksa->bssid, QDF_MAC_ADDR_SIZE);
13671 qdf_mem_copy(pmk_id.PMKID, pmksa->pmkid, CSR_RSN_PMKID_SIZE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013672
13673 /* Add to the PMKSA ID Cache in CSR */
13674 result = sme_roam_set_pmkid_cache(halHandle, pAdapter->sessionId,
13675 &pmk_id, 1, false);
13676
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013677 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013678 TRACE_CODE_HDD_CFG80211_SET_PMKSA,
13679 pAdapter->sessionId, result));
13680
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013681 EXIT();
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013682 return QDF_IS_STATUS_SUCCESS(result) ? 0 : -EINVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013683}
13684
13685/**
13686 * wlan_hdd_cfg80211_set_pmksa() - set pmksa
13687 * @wiphy: Pointer to wiphy
13688 * @dev: Pointer to network device
13689 * @pmksa: Pointer to set pmksa parameter
13690 *
13691 * Return: 0 for success, non-zero for failure
13692 */
13693static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy,
13694 struct net_device *dev,
13695 struct cfg80211_pmksa *pmksa)
13696{
13697 int ret;
13698
13699 cds_ssr_protect(__func__);
13700 ret = __wlan_hdd_cfg80211_set_pmksa(wiphy, dev, pmksa);
13701 cds_ssr_unprotect(__func__);
13702
13703 return ret;
13704}
13705
13706/**
13707 * __wlan_hdd_cfg80211_del_pmksa() - delete pmksa
13708 * @wiphy: Pointer to wiphy
13709 * @dev: Pointer to network device
13710 * @pmksa: Pointer to pmksa parameter
13711 *
13712 * Return: 0 for success, non-zero for failure
13713 */
13714static int __wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
13715 struct net_device *dev,
13716 struct cfg80211_pmksa *pmksa)
13717{
13718 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13719 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13720 tHalHandle halHandle;
13721 int status = 0;
13722
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013723 ENTER();
13724
Anurag Chouhan6d760662016-02-20 16:05:43 +053013725 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013726 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013727 return -EINVAL;
13728 }
13729
13730 if (!pmksa) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013731 hdd_err("pmksa is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013732 return -EINVAL;
13733 }
13734
13735 if (!pmksa->bssid) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013736 hdd_err("pmksa->bssid is NULL");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013737 return -EINVAL;
13738 }
13739
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013740 hdd_debug("Deleting PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013741 MAC_ADDR_ARRAY(pmksa->bssid));
13742
13743 status = wlan_hdd_validate_context(pHddCtx);
13744
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013745 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013746 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013747
13748 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13749
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013750 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053013751 TRACE_CODE_HDD_CFG80211_DEL_PMKSA,
13752 pAdapter->sessionId, 0));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013753 /* Delete the PMKID CSR cache */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013754 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013755 sme_roam_del_pmkid_from_cache(halHandle,
13756 pAdapter->sessionId, pmksa->bssid,
13757 false)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013758 hdd_err("Failed to delete PMKSA for " MAC_ADDRESS_STR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013759 MAC_ADDR_ARRAY(pmksa->bssid));
13760 status = -EINVAL;
13761 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013762 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013763 return status;
13764}
13765
13766/**
13767 * wlan_hdd_cfg80211_del_pmksa() - delete pmksa
13768 * @wiphy: Pointer to wiphy
13769 * @dev: Pointer to network device
13770 * @pmksa: Pointer to pmksa parameter
13771 *
13772 * Return: 0 for success, non-zero for failure
13773 */
13774static int wlan_hdd_cfg80211_del_pmksa(struct wiphy *wiphy,
13775 struct net_device *dev,
13776 struct cfg80211_pmksa *pmksa)
13777{
13778 int ret;
13779
13780 cds_ssr_protect(__func__);
13781 ret = __wlan_hdd_cfg80211_del_pmksa(wiphy, dev, pmksa);
13782 cds_ssr_unprotect(__func__);
13783
13784 return ret;
13785
13786}
13787
13788/**
13789 * __wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
13790 * @wiphy: Pointer to wiphy
13791 * @dev: Pointer to network device
13792 *
13793 * Return: 0 for success, non-zero for failure
13794 */
13795static int __wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
13796 struct net_device *dev)
13797{
13798 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13799 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13800 tHalHandle halHandle;
13801 int status = 0;
13802
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013803 ENTER();
13804
Anurag Chouhan6d760662016-02-20 16:05:43 +053013805 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013806 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013807 return -EINVAL;
13808 }
13809
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013810 hdd_warn("Flushing PMKSA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013811
13812 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
13813 status = wlan_hdd_validate_context(pHddCtx);
13814
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013815 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013816 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013817
13818 /* Retrieve halHandle */
13819 halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter);
13820
13821 /* Flush the PMKID cache in CSR */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013822 if (QDF_STATUS_SUCCESS !=
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013823 sme_roam_del_pmkid_from_cache(halHandle, pAdapter->sessionId, NULL,
13824 true)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013825 hdd_err("Cannot flush PMKIDCache");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013826 status = -EINVAL;
13827 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013828 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013829 return status;
13830}
13831
13832/**
13833 * wlan_hdd_cfg80211_flush_pmksa() - flush pmksa
13834 * @wiphy: Pointer to wiphy
13835 * @dev: Pointer to network device
13836 *
13837 * Return: 0 for success, non-zero for failure
13838 */
13839static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy,
13840 struct net_device *dev)
13841{
13842 int ret;
13843
13844 cds_ssr_protect(__func__);
13845 ret = __wlan_hdd_cfg80211_flush_pmksa(wiphy, dev);
13846 cds_ssr_unprotect(__func__);
13847
13848 return ret;
13849}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013850
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080013851#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013852/**
13853 * __wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
13854 * @wiphy: Pointer to wiphy
13855 * @dev: Pointer to network device
13856 * @ftie: Pointer to fast transition ie parameter
13857 *
13858 * Return: 0 for success, non-zero for failure
13859 */
13860static int
13861__wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
13862 struct net_device *dev,
13863 struct cfg80211_update_ft_ies_params *ftie)
13864{
13865 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
13866 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13867 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13868 int status;
13869
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013870 ENTER();
13871
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013872 status = wlan_hdd_validate_context(hdd_ctx);
13873 if (status)
13874 return status;
13875
Anurag Chouhan6d760662016-02-20 16:05:43 +053013876 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013877 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013878 return -EINVAL;
13879 }
13880
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053013881 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013882 TRACE_CODE_HDD_CFG80211_UPDATE_FT_IES,
13883 pAdapter->sessionId, pHddStaCtx->conn_info.connState));
13884 /* Added for debug on reception of Re-assoc Req. */
13885 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013886 hdd_err("Called with Ie of length = %zu when not associated",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013887 ftie->ie_len);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013888 hdd_err("Should be Re-assoc Req IEs");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013889 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013890 hdd_notice("%s called with Ie of length = %zu", __func__,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013891 ftie->ie_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013892
13893 /* Pass the received FT IEs to SME */
13894 sme_set_ft_ies(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId,
13895 (const u8 *)ftie->ie, ftie->ie_len);
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053013896 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013897 return 0;
13898}
13899
13900/**
13901 * wlan_hdd_cfg80211_update_ft_ies() - update fast transition ies
13902 * @wiphy: Pointer to wiphy
13903 * @dev: Pointer to network device
13904 * @ftie: Pointer to fast transition ie parameter
13905 *
13906 * Return: 0 for success, non-zero for failure
13907 */
13908static int
13909wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy,
13910 struct net_device *dev,
13911 struct cfg80211_update_ft_ies_params *ftie)
13912{
13913 int ret;
13914
13915 cds_ssr_protect(__func__);
13916 ret = __wlan_hdd_cfg80211_update_ft_ies(wiphy, dev, ftie);
13917 cds_ssr_unprotect(__func__);
13918
13919 return ret;
13920}
13921#endif
13922
13923#ifdef WLAN_FEATURE_GTK_OFFLOAD
13924/**
13925 * wlan_hdd_cfg80211_update_replay_counter_callback() - replay counter callback
13926 * @callbackContext: Callback context
13927 * @pGtkOffloadGetInfoRsp: Pointer to gtk offload response parameter
13928 *
13929 * Callback rountine called upon receiving response for get offload info
13930 *
13931 * Return: none
13932 */
13933void wlan_hdd_cfg80211_update_replay_counter_callback(void *callbackContext,
13934 tpSirGtkOffloadGetInfoRspParams
13935 pGtkOffloadGetInfoRsp)
13936{
13937 hdd_adapter_t *pAdapter = (hdd_adapter_t *) callbackContext;
13938 uint8_t tempReplayCounter[8];
13939 hdd_station_ctx_t *pHddStaCtx;
13940
13941 ENTER();
13942
13943 if (NULL == pAdapter) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013944 hdd_err("HDD adapter is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013945 return;
13946 }
13947
13948 if (NULL == pGtkOffloadGetInfoRsp) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013949 hdd_err("pGtkOffloadGetInfoRsp is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013950 return;
13951 }
13952
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053013953 if (QDF_STATUS_SUCCESS != pGtkOffloadGetInfoRsp->ulStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070013954 hdd_err("wlan Failed to get replay counter value");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013955 return;
13956 }
13957
13958 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
13959 /* Update replay counter */
13960 pHddStaCtx->gtkOffloadReqParams.ullKeyReplayCounter =
13961 pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
13962
13963 {
13964 /* changing from little to big endian since supplicant
13965 * works on big endian format
13966 */
13967 int i;
13968 uint8_t *p =
13969 (uint8_t *) &pGtkOffloadGetInfoRsp->ullKeyReplayCounter;
13970
13971 for (i = 0; i < 8; i++) {
13972 tempReplayCounter[7 - i] = (uint8_t) p[i];
13973 }
13974 }
13975
13976 /* Update replay counter to NL */
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080013977 cfg80211_gtk_rekey_notify(pAdapter->dev,
13978 pGtkOffloadGetInfoRsp->bssid.bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013979 tempReplayCounter, GFP_KERNEL);
13980}
13981
13982/**
13983 * __wlan_hdd_cfg80211_set_rekey_data() - set rekey data
13984 * @wiphy: Pointer to wiphy
13985 * @dev: Pointer to network device
13986 * @data: Pointer to rekey data
13987 *
13988 * This function is used to offload GTK rekeying job to the firmware.
13989 *
13990 * Return: 0 for success, non-zero for failure
13991 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070013992static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080013993int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
13994 struct net_device *dev,
13995 struct cfg80211_gtk_rekey_data *data)
13996{
13997 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
13998 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
13999 hdd_station_ctx_t *pHddStaCtx;
14000 tHalHandle hHal;
14001 int result;
14002 tSirGtkOffloadParams hddGtkOffloadReqParams;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014003 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014004
14005 ENTER();
14006
Anurag Chouhan6d760662016-02-20 16:05:43 +053014007 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014008 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014009 return -EINVAL;
14010 }
14011
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014012 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014013 TRACE_CODE_HDD_CFG80211_SET_REKEY_DATA,
14014 pAdapter->sessionId, pAdapter->device_mode));
14015
14016 result = wlan_hdd_validate_context(pHddCtx);
14017
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014018 if (0 != result)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014019 return result;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014020
14021 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
14022 hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
14023 if (NULL == hHal) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014024 hdd_err("HAL context is Null!!!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014025 return -EAGAIN;
14026 }
14027
14028 pHddStaCtx->gtkOffloadReqParams.ulFlags = GTK_OFFLOAD_ENABLE;
14029 memcpy(pHddStaCtx->gtkOffloadReqParams.aKCK, data->kck,
14030 NL80211_KCK_LEN);
14031 memcpy(pHddStaCtx->gtkOffloadReqParams.aKEK, data->kek,
14032 NL80211_KEK_LEN);
Anurag Chouhanc5548422016-02-24 18:33:27 +053014033 qdf_copy_macaddr(&pHddStaCtx->gtkOffloadReqParams.bssid,
Srinivas Girigowda2213b1d2015-11-20 17:10:11 -080014034 &pHddStaCtx->conn_info.bssId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014035 {
14036 /* changing from big to little endian since driver
14037 * works on little endian format
14038 */
14039 uint8_t *p =
14040 (uint8_t *) &pHddStaCtx->gtkOffloadReqParams.
14041 ullKeyReplayCounter;
14042 int i;
14043
14044 for (i = 0; i < 8; i++) {
14045 p[7 - i] = data->replay_ctr[i];
14046 }
14047 }
14048
14049 if (true == pHddCtx->hdd_wlan_suspended) {
14050 /* if wlan is suspended, enable GTK offload directly from here */
14051 memcpy(&hddGtkOffloadReqParams,
14052 &pHddStaCtx->gtkOffloadReqParams,
14053 sizeof(tSirGtkOffloadParams));
14054 status =
14055 sme_set_gtk_offload(hHal, &hddGtkOffloadReqParams,
14056 pAdapter->sessionId);
14057
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014058 if (QDF_STATUS_SUCCESS != status) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014059 hdd_err("sme_set_gtk_offload failed, status(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014060 status);
14061 return -EINVAL;
14062 }
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014063 hdd_notice("sme_set_gtk_offload successful");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014064 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014065 hdd_notice("wlan not suspended GTKOffload request is stored");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014066 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014067 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014068 return result;
14069}
14070
14071/**
14072 * wlan_hdd_cfg80211_set_rekey_data() - set rekey data
14073 * @wiphy: Pointer to wiphy
14074 * @dev: Pointer to network device
14075 * @data: Pointer to rekey data
14076 *
14077 * This function is used to offload GTK rekeying job to the firmware.
14078 *
14079 * Return: 0 for success, non-zero for failure
14080 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014081static
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014082int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
14083 struct net_device *dev,
14084 struct cfg80211_gtk_rekey_data *data)
14085{
14086 int ret;
14087
14088 cds_ssr_protect(__func__);
14089 ret = __wlan_hdd_cfg80211_set_rekey_data(wiphy, dev, data);
14090 cds_ssr_unprotect(__func__);
14091
14092 return ret;
14093}
14094#endif /*WLAN_FEATURE_GTK_OFFLOAD */
14095
14096/**
14097 * __wlan_hdd_cfg80211_set_mac_acl() - set access control policy
14098 * @wiphy: Pointer to wiphy
14099 * @dev: Pointer to network device
14100 * @param: Pointer to access control parameter
14101 *
14102 * Return: 0 for success, non-zero for failure
14103 */
14104static int __wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14105 struct net_device *dev,
14106 const struct cfg80211_acl_data *params)
14107{
14108 int i;
14109 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14110 hdd_hostapd_state_t *pHostapdState;
14111 tsap_Config_t *pConfig;
14112 v_CONTEXT_t p_cds_context = NULL;
14113 hdd_context_t *pHddCtx;
14114 int status;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014115 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014116
14117 ENTER();
14118
Anurag Chouhan6d760662016-02-20 16:05:43 +053014119 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014120 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014121 return -EINVAL;
14122 }
14123
14124 if (NULL == params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014125 hdd_err("params is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014126 return -EINVAL;
14127 }
14128
14129 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14130 status = wlan_hdd_validate_context(pHddCtx);
14131
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014132 if (0 != status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014133 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014134
14135 p_cds_context = pHddCtx->pcds_context;
14136 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
14137
14138 if (NULL == pHostapdState) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014139 hdd_err("pHostapdState is Null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014140 return -EINVAL;
14141 }
14142
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014143 hdd_err("acl policy: = %d no acl entries = %d", params->acl_policy,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014144 params->n_acl_entries);
14145
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014146 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014147 TRACE_CODE_HDD_CFG80211_SET_MAC_ACL,
14148 pAdapter->sessionId, pAdapter->device_mode));
Krunal Sonib4326f22016-03-10 13:05:51 -080014149 if (QDF_SAP_MODE == pAdapter->device_mode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014150 pConfig = &pAdapter->sessionCtx.ap.sapConfig;
14151
14152 /* default value */
14153 pConfig->num_accept_mac = 0;
14154 pConfig->num_deny_mac = 0;
14155
14156 /**
14157 * access control policy
14158 * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
14159 * listed in hostapd.deny file.
14160 * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are
14161 * listed in hostapd.accept file.
14162 */
14163 if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) {
14164 pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED;
14165 } else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED ==
14166 params->acl_policy) {
14167 pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED;
14168 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014169 hdd_err("Acl Policy : %d is not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014170 params->acl_policy);
14171 return -ENOTSUPP;
14172 }
14173
14174 if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) {
14175 pConfig->num_accept_mac = params->n_acl_entries;
14176 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014177 hdd_notice("** Add ACL MAC entry %i in WhiletList :"
14178 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014179 MAC_ADDR_ARRAY(
14180 params->mac_addrs[i].addr));
14181
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014182 qdf_mem_copy(&pConfig->accept_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014183 params->mac_addrs[i].addr,
14184 sizeof(qcmacaddr));
14185 }
14186 } else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) {
14187 pConfig->num_deny_mac = params->n_acl_entries;
14188 for (i = 0; i < params->n_acl_entries; i++) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014189 hdd_notice("** Add ACL MAC entry %i in BlackList :"
14190 MAC_ADDRESS_STR, i,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014191 MAC_ADDR_ARRAY(
14192 params->mac_addrs[i].addr));
14193
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014194 qdf_mem_copy(&pConfig->deny_mac[i],
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014195 params->mac_addrs[i].addr,
14196 sizeof(qcmacaddr));
14197 }
14198 }
Dustin Brown6ba30a12016-09-13 13:59:43 -070014199 qdf_status = wlansap_set_mac_acl(
14200 WLAN_HDD_GET_SAP_CTX_PTR(pAdapter), pConfig);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014201 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014202 hdd_err("SAP Set Mac Acl fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014203 return -EINVAL;
14204 }
14205 } else {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014206 hdd_notice("Invalid device_mode %s(%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014207 hdd_device_mode_to_string(pAdapter->device_mode),
14208 pAdapter->device_mode);
14209 return -EINVAL;
14210 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014211 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014212 return 0;
14213}
14214
14215/**
14216 * wlan_hdd_cfg80211_set_mac_acl() - SSR wrapper for
14217 * __wlan_hdd_cfg80211_set_mac_acl
14218 * @wiphy: pointer to wiphy structure
14219 * @dev: pointer to net_device
14220 * @params: pointer to cfg80211_acl_data
14221 *
14222 * Return; 0 on success, error number otherwise
14223 */
14224static int
14225wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy,
14226 struct net_device *dev,
14227 const struct cfg80211_acl_data *params)
14228{
14229 int ret;
14230
14231 cds_ssr_protect(__func__);
14232 ret = __wlan_hdd_cfg80211_set_mac_acl(wiphy, dev, params);
14233 cds_ssr_unprotect(__func__);
14234
14235 return ret;
14236}
14237
14238#ifdef WLAN_NL80211_TESTMODE
14239#ifdef FEATURE_WLAN_LPHB
14240/**
14241 * wlan_hdd_cfg80211_lphb_ind_handler() - handle low power heart beat indication
14242 * @pHddCtx: Pointer to hdd context
14243 * @lphbInd: Pointer to low power heart beat indication parameter
14244 *
14245 * Return: none
14246 */
Jeff Johnson8b8a04b2016-10-05 15:49:43 -070014247static void wlan_hdd_cfg80211_lphb_ind_handler(void *pHddCtx,
14248 tSirLPHBInd *lphbInd)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014249{
14250 struct sk_buff *skb;
14251
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014252 hdd_err("LPHB indication arrived");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014253
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014254 if (0 != wlan_hdd_validate_context((hdd_context_t *) pHddCtx))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014255 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014256
14257 if (NULL == lphbInd) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014258 hdd_err("invalid argument lphbInd");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014259 return;
14260 }
14261
14262 skb = cfg80211_testmode_alloc_event_skb(((hdd_context_t *) pHddCtx)->
14263 wiphy, sizeof(tSirLPHBInd),
14264 GFP_ATOMIC);
14265 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014266 hdd_err("LPHB timeout, NL buffer alloc fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014267 return;
14268 }
14269
14270 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_HB)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014271 hdd_err("WLAN_HDD_TM_ATTR_CMD put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014272 goto nla_put_failure;
14273 }
14274 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_TYPE, lphbInd->protocolType)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014275 hdd_err("WLAN_HDD_TM_ATTR_TYPE put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014276 goto nla_put_failure;
14277 }
14278 if (nla_put(skb, WLAN_HDD_TM_ATTR_DATA, sizeof(tSirLPHBInd), lphbInd)) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014279 hdd_err("WLAN_HDD_TM_ATTR_DATA put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014280 goto nla_put_failure;
14281 }
14282 cfg80211_testmode_event(skb, GFP_ATOMIC);
14283 return;
14284
14285nla_put_failure:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014286 hdd_err("NLA Put fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014287 kfree_skb(skb);
14288
14289 return;
14290}
14291#endif /* FEATURE_WLAN_LPHB */
14292
14293/**
14294 * __wlan_hdd_cfg80211_testmode() - test mode
14295 * @wiphy: Pointer to wiphy
14296 * @data: Data pointer
14297 * @len: Data length
14298 *
14299 * Return: 0 for success, non-zero for failure
14300 */
14301static int __wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14302 void *data, int len)
14303{
14304 struct nlattr *tb[WLAN_HDD_TM_ATTR_MAX + 1];
14305 int err;
14306 hdd_context_t *pHddCtx = wiphy_priv(wiphy);
14307
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014308 ENTER();
14309
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014310 err = wlan_hdd_validate_context(pHddCtx);
14311 if (err)
14312 return err;
14313
14314 err = nla_parse(tb, WLAN_HDD_TM_ATTR_MAX, data,
14315 len, wlan_hdd_tm_policy);
14316 if (err) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014317 hdd_err("Testmode INV ATTR");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014318 return err;
14319 }
14320
14321 if (!tb[WLAN_HDD_TM_ATTR_CMD]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014322 hdd_err("Testmode INV CMD");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014323 return -EINVAL;
14324 }
14325
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +053014326 MTRACE(qdf_trace(QDF_MODULE_ID_HDD,
Sreelakshmi Konamki6744cff2015-09-07 12:10:39 +053014327 TRACE_CODE_HDD_CFG80211_TESTMODE,
14328 NO_SESSION, nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014329 switch (nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD])) {
14330#ifdef FEATURE_WLAN_LPHB
14331 /* Low Power Heartbeat configuration request */
14332 case WLAN_HDD_TM_CMD_WLAN_HB:
14333 {
14334 int buf_len;
14335 void *buf;
14336 tSirLPHBReq *hb_params = NULL;
14337 tSirLPHBReq *hb_params_temp = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014338 QDF_STATUS smeStatus;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014339
14340 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014341 hdd_err("Testmode INV DATA");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014342 return -EINVAL;
14343 }
14344
14345 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14346 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14347
14348 hb_params_temp = (tSirLPHBReq *) buf;
14349 if ((hb_params_temp->cmd == LPHB_SET_TCP_PARAMS_INDID)
14350 && (hb_params_temp->params.lphbTcpParamReq.
14351 timePeriodSec == 0))
14352 return -EINVAL;
14353
14354 hb_params =
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014355 (tSirLPHBReq *) qdf_mem_malloc(sizeof(tSirLPHBReq));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014356 if (NULL == hb_params) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014357 hdd_err("Request Buffer Alloc Fail");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014358 return -ENOMEM;
14359 }
14360
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014361 qdf_mem_copy(hb_params, buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014362 smeStatus =
14363 sme_lphb_config_req((tHalHandle) (pHddCtx->hHal),
14364 hb_params,
14365 wlan_hdd_cfg80211_lphb_ind_handler);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014366 if (QDF_STATUS_SUCCESS != smeStatus) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014367 hdd_err("LPHB Config Fail, disable");
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014368 qdf_mem_free(hb_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014369 }
14370 return 0;
14371 }
14372#endif /* FEATURE_WLAN_LPHB */
14373
14374#if defined(QCA_WIFI_FTM)
14375 case WLAN_HDD_TM_CMD_WLAN_FTM:
14376 {
14377 int buf_len;
14378 void *buf;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014379 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014380 if (!tb[WLAN_HDD_TM_ATTR_DATA]) {
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014381 hdd_err("WLAN_HDD_TM_ATTR_DATA attribute is invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014382 return -EINVAL;
14383 }
14384
14385 buf = nla_data(tb[WLAN_HDD_TM_ATTR_DATA]);
14386 buf_len = nla_len(tb[WLAN_HDD_TM_ATTR_DATA]);
14387
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014388 hdd_info("****FTM Tx cmd len = %d*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014389
14390 status = wlan_hdd_ftm_testmode_cmd(buf, buf_len);
14391
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014392 if (status != QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014393 err = -EBUSY;
14394 break;
14395 }
14396#endif
14397
14398 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014399 hdd_err("command %d not supported",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014400 nla_get_u32(tb[WLAN_HDD_TM_ATTR_CMD]));
14401 return -EOPNOTSUPP;
14402 }
Hanumantha Reddy Pothula2db50ed2015-11-23 10:48:33 +053014403 EXIT();
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014404 return err;
14405}
14406
14407/**
14408 * wlan_hdd_cfg80211_testmode() - test mode
14409 * @wiphy: Pointer to wiphy
14410 * @dev: Pointer to network device
14411 * @data: Data pointer
14412 * @len: Data length
14413 *
14414 * Return: 0 for success, non-zero for failure
14415 */
14416static int wlan_hdd_cfg80211_testmode(struct wiphy *wiphy,
14417#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
14418 struct wireless_dev *wdev,
14419#endif
14420 void *data, int len)
14421{
14422 int ret;
14423
14424 cds_ssr_protect(__func__);
14425 ret = __wlan_hdd_cfg80211_testmode(wiphy, data, len);
14426 cds_ssr_unprotect(__func__);
14427
14428 return ret;
14429}
14430
14431#if defined(QCA_WIFI_FTM)
14432/**
14433 * wlan_hdd_testmode_rx_event() - test mode rx event handler
14434 * @buf: Pointer to buffer
14435 * @buf_len: Buffer length
14436 *
14437 * Return: none
14438 */
14439void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len)
14440{
14441 struct sk_buff *skb;
14442 hdd_context_t *hdd_ctx;
14443
14444 if (!buf || !buf_len) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014445 hdd_err("buf or buf_len invalid, buf = %p buf_len = %zu", buf, buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014446 return;
14447 }
14448
Anurag Chouhan6d760662016-02-20 16:05:43 +053014449 hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014450 if (!hdd_ctx) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014451 hdd_err("hdd context invalid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014452 return;
14453 }
14454
14455 skb = cfg80211_testmode_alloc_event_skb(hdd_ctx->wiphy,
14456 buf_len, GFP_KERNEL);
14457 if (!skb) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014458 hdd_err("failed to allocate testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014459 return;
14460 }
14461
14462 if (nla_put_u32(skb, WLAN_HDD_TM_ATTR_CMD, WLAN_HDD_TM_CMD_WLAN_FTM) ||
14463 nla_put(skb, WLAN_HDD_TM_ATTR_DATA, buf_len, buf))
14464 goto nla_put_failure;
14465
Ryan Hsucfef0ae2016-04-28 10:20:46 -070014466 hdd_info("****FTM Rx cmd len = %zu*****", buf_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014467
14468 cfg80211_testmode_event(skb, GFP_KERNEL);
14469 return;
14470
14471nla_put_failure:
14472 kfree_skb(skb);
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014473 hdd_err("nla_put failed on testmode rx skb!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014474}
14475#endif
14476#endif /* CONFIG_NL80211_TESTMODE */
14477
14478#ifdef QCA_HT_2040_COEX
14479/**
14480 * __wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14481 * @wiphy: Pointer to wiphy
14482 * @dev: Pointer to network device
14483 * @chandef: Pointer to channel definition parameter
14484 *
14485 * Return: 0 for success, non-zero for failure
14486 */
14487static int
14488__wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14489 struct net_device *dev,
14490 struct cfg80211_chan_def *chandef)
14491{
14492 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
14493 hdd_context_t *pHddCtx;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014494 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014495 tSmeConfigParams sme_config;
Anurag Chouhan00ed5272016-10-17 17:22:55 +053014496 bool cbModeChange = false;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014497
Anurag Chouhan6d760662016-02-20 16:05:43 +053014498 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014499 hdd_err("Command not allowed in FTM mode");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014500 return -EINVAL;
14501 }
14502
14503 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
14504 status = wlan_hdd_validate_context(pHddCtx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +053014505 if (status)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014506 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014507
Anurag Chouhan600c3a02016-03-01 10:33:54 +053014508 qdf_mem_zero(&sme_config, sizeof(tSmeConfigParams));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014509 sme_get_config_param(pHddCtx->hHal, &sme_config);
14510 switch (chandef->width) {
14511 case NL80211_CHAN_WIDTH_20:
14512 if (sme_config.csrConfig.channelBondingMode24GHz !=
14513 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14514 sme_config.csrConfig.channelBondingMode24GHz =
14515 eCSR_INI_SINGLE_CHANNEL_CENTERED;
14516 sme_update_config(pHddCtx->hHal, &sme_config);
14517 cbModeChange = true;
14518 }
14519 break;
14520
14521 case NL80211_CHAN_WIDTH_40:
14522 if (sme_config.csrConfig.channelBondingMode24GHz ==
14523 eCSR_INI_SINGLE_CHANNEL_CENTERED) {
14524 if (NL80211_CHAN_HT40MINUS ==
14525 cfg80211_get_chandef_type(chandef))
14526 sme_config.csrConfig.channelBondingMode24GHz =
14527 eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
14528 else
14529 sme_config.csrConfig.channelBondingMode24GHz =
14530 eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
14531 sme_update_config(pHddCtx->hHal, &sme_config);
14532 cbModeChange = true;
14533 }
14534 break;
14535
14536 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014537 hdd_err("Error!!! Invalid HT20/40 mode !");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014538 return -EINVAL;
14539 }
14540
14541 if (!cbModeChange)
14542 return 0;
14543
Krunal Sonib4326f22016-03-10 13:05:51 -080014544 if (QDF_SAP_MODE != pAdapter->device_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014545 return 0;
14546
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014547 hdd_notice("Channel bonding changed to %d",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014548 sme_config.csrConfig.channelBondingMode24GHz);
14549
14550 /* Change SAP ht2040 mode */
14551 status = hdd_set_sap_ht2040_mode(pAdapter,
14552 cfg80211_get_chandef_type(chandef));
Anurag Chouhanfb54ab02016-02-18 18:00:46 +053014553 if (status != QDF_STATUS_SUCCESS) {
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014554 hdd_err("Error!!! Cannot set SAP HT20/40 mode!");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014555 return -EINVAL;
14556 }
14557
14558 return 0;
14559}
14560
14561/**
14562 * wlan_hdd_cfg80211_set_ap_channel_width() - set ap channel bandwidth
14563 * @wiphy: Pointer to wiphy
14564 * @dev: Pointer to network device
14565 * @chandef: Pointer to channel definition parameter
14566 *
14567 * Return: 0 for success, non-zero for failure
14568 */
14569static int
14570wlan_hdd_cfg80211_set_ap_channel_width(struct wiphy *wiphy,
14571 struct net_device *dev,
14572 struct cfg80211_chan_def *chandef)
14573{
14574 int ret;
14575
14576 cds_ssr_protect(__func__);
14577 ret = __wlan_hdd_cfg80211_set_ap_channel_width(wiphy, dev, chandef);
14578 cds_ssr_unprotect(__func__);
14579
14580 return ret;
14581}
14582#endif
14583
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014584#ifdef CHANNEL_SWITCH_SUPPORTED
14585/**
14586 * __wlan_hdd_cfg80211_channel_switch()- function to switch
14587 * channel in SAP/GO
14588 * @wiphy: wiphy pointer
14589 * @dev: dev pointer.
14590 * @csa_params: Change channel params
14591 *
14592 * This function is called to switch channel in SAP/GO
14593 *
14594 * Return: 0 if success else return non zero
14595 */
14596static int __wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14597 struct net_device *dev,
14598 struct cfg80211_csa_settings *csa_params)
14599{
14600 hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
14601 hdd_context_t *hdd_ctx;
14602 uint8_t channel;
14603 uint16_t freq;
14604 int ret;
Kiran Kumar Lokere13644672016-02-29 15:40:10 -080014605 enum phy_ch_width ch_width;
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014606
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014607 hdd_notice("Set Freq %d",
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014608 csa_params->chandef.chan->center_freq);
14609
14610 hdd_ctx = WLAN_HDD_GET_CTX(adapter);
14611 ret = wlan_hdd_validate_context(hdd_ctx);
14612
14613 if (0 != ret)
14614 return ret;
14615
Krunal Sonib4326f22016-03-10 13:05:51 -080014616 if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
14617 (QDF_SAP_MODE != adapter->device_mode))
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014618 return -ENOTSUPP;
14619
14620 freq = csa_params->chandef.chan->center_freq;
14621 channel = cds_freq_to_chan(freq);
14622
Chandrasekaran, Manishekara74bb022016-01-12 18:37:43 +053014623 ch_width = hdd_map_nl_chan_width(csa_params->chandef.width);
14624
14625 ret = hdd_softap_set_channel_change(dev, channel, ch_width);
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014626 return ret;
14627}
14628
14629/**
14630 * wlan_hdd_cfg80211_channel_switch()- function to switch
14631 * channel in SAP/GO
14632 * @wiphy: wiphy pointer
14633 * @dev: dev pointer.
14634 * @csa_params: Change channel params
14635 *
14636 * This function is called to switch channel in SAP/GO
14637 *
14638 * Return: 0 if success else return non zero
14639 */
14640static int wlan_hdd_cfg80211_channel_switch(struct wiphy *wiphy,
14641 struct net_device *dev,
14642 struct cfg80211_csa_settings *csa_params)
14643{
14644 int ret;
14645
14646 cds_ssr_protect(__func__);
14647 ret = __wlan_hdd_cfg80211_channel_switch(wiphy, dev, csa_params);
14648 cds_ssr_unprotect(__func__);
14649 return ret;
14650}
14651#endif
14652
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014653/**
14654 * wlan_hdd_convert_nl_iftype_to_hdd_type() - provides the type
14655 * translation from NL to policy manager type
14656 * @type: Generic connection mode type defined in NL
14657 *
14658 *
14659 * This function provides the type translation
14660 *
14661 * Return: cds_con_mode enum
14662 */
14663enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type(
14664 enum nl80211_iftype type)
14665{
14666 enum cds_con_mode mode = CDS_MAX_NUM_OF_MODE;
14667 switch (type) {
14668 case NL80211_IFTYPE_STATION:
14669 mode = CDS_STA_MODE;
14670 break;
14671 case NL80211_IFTYPE_P2P_CLIENT:
14672 mode = CDS_P2P_CLIENT_MODE;
14673 break;
14674 case NL80211_IFTYPE_P2P_GO:
14675 mode = CDS_P2P_GO_MODE;
14676 break;
14677 case NL80211_IFTYPE_AP:
14678 mode = CDS_SAP_MODE;
14679 break;
14680 case NL80211_IFTYPE_ADHOC:
14681 mode = CDS_IBSS_MODE;
14682 break;
14683 default:
Jeff Johnson3d8ac552016-06-29 15:21:37 -070014684 hdd_err("Unsupported interface type (%d)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014685 type);
14686 }
14687 return mode;
14688}
14689
14690/**
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014691 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
14692 * @wiphy: Handle to struct wiphy to get handle to module context.
14693 * @chandef: Contains information about the capture channel to be set.
14694 *
14695 * This interface is called if and only if monitor mode interface alone is
14696 * active.
14697 *
14698 * Return: 0 success or error code on failure.
14699 */
14700static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
14701 struct cfg80211_chan_def *chandef)
14702{
14703 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
14704 hdd_adapter_t *adapter;
14705 hdd_station_ctx_t *sta_ctx;
14706 struct hdd_mon_set_ch_info *ch_info;
14707 QDF_STATUS status;
14708 tHalHandle hal_hdl;
14709 struct qdf_mac_addr bssid;
14710 tCsrRoamProfile roam_profile;
14711 struct ch_params_s ch_params;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070014712 uint8_t sec_ch = 0;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014713 int ret;
14714 uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq);
14715
14716 ENTER();
14717
14718 ret = wlan_hdd_validate_context(hdd_ctx);
14719 if (ret)
14720 return ret;
14721
14722 hal_hdl = hdd_ctx->hHal;
14723
14724 adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
14725 if (!adapter)
14726 return -EIO;
14727
14728 hdd_info("%s: set monitor mode Channel %d and freq %d",
14729 adapter->dev->name, chan_num, chandef->chan->center_freq);
14730
14731 sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
14732 ch_info = &sta_ctx->ch_info;
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014733 roam_profile.ChannelInfo.ChannelList = &ch_info->channel;
14734 roam_profile.ChannelInfo.numOfChannels = 1;
14735 roam_profile.phyMode = ch_info->phy_mode;
14736 roam_profile.ch_params.ch_width = chandef->width;
Naveen Rawatc77e6e72016-08-05 15:19:03 -070014737 hdd_select_cbmode(adapter, chan_num, &roam_profile.ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014738
14739 qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes,
14740 QDF_MAC_ADDR_SIZE);
14741
14742 ch_params.ch_width = chandef->width;
Sandeep Puligilla1cc23f62016-04-27 16:52:49 -070014743 /*
14744 * CDS api expects secondary channel for calculating
14745 * the channel params
14746 */
14747 if ((ch_params.ch_width == CH_WIDTH_40MHZ) &&
14748 (CDS_IS_CHANNEL_24GHZ(chan_num))) {
14749 if (chan_num >= 1 && chan_num <= 5)
14750 sec_ch = chan_num + 4;
14751 else if (chan_num >= 6 && chan_num <= 13)
14752 sec_ch = chan_num - 4;
14753 }
14754 cds_set_channel_params(chan_num, sec_ch, &ch_params);
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014755 status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params,
14756 &roam_profile);
14757 if (status) {
14758 hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode",
14759 status);
14760 ret = qdf_status_to_os_return(status);
14761 return ret;
14762 }
14763 EXIT();
14764 return 0;
14765}
14766
14767/**
14768 * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel
14769 * @wiphy: Handle to struct wiphy to get handle to module context.
14770 * @chandef: Contains information about the capture channel to be set.
14771 *
14772 * This interface is called if and only if monitor mode interface alone is
14773 * active.
14774 *
14775 * Return: 0 success or error code on failure.
14776 */
14777static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy,
14778 struct cfg80211_chan_def *chandef)
14779{
14780 int ret;
14781
14782 cds_ssr_protect(__func__);
14783 ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef);
14784 cds_ssr_unprotect(__func__);
14785 return ret;
14786}
14787
14788/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014789 * struct cfg80211_ops - cfg80211_ops
14790 *
14791 * @add_virtual_intf: Add virtual interface
14792 * @del_virtual_intf: Delete virtual interface
14793 * @change_virtual_intf: Change virtual interface
14794 * @change_station: Change station
14795 * @add_beacon: Add beacon in sap mode
14796 * @del_beacon: Delete beacon in sap mode
14797 * @set_beacon: Set beacon in sap mode
14798 * @start_ap: Start ap
14799 * @change_beacon: Change beacon
14800 * @stop_ap: Stop ap
14801 * @change_bss: Change bss
14802 * @add_key: Add key
14803 * @get_key: Get key
14804 * @del_key: Delete key
14805 * @set_default_key: Set default key
14806 * @set_channel: Set channel
14807 * @scan: Scan
14808 * @connect: Connect
14809 * @disconnect: Disconnect
14810 * @join_ibss = Join ibss
14811 * @leave_ibss = Leave ibss
14812 * @set_wiphy_params = Set wiphy params
14813 * @set_tx_power = Set tx power
14814 * @get_tx_power = get tx power
14815 * @remain_on_channel = Remain on channel
14816 * @cancel_remain_on_channel = Cancel remain on channel
14817 * @mgmt_tx = Tx management frame
14818 * @mgmt_tx_cancel_wait = Cancel management tx wait
14819 * @set_default_mgmt_key = Set default management key
14820 * @set_txq_params = Set tx queue parameters
14821 * @get_station = Get station
14822 * @set_power_mgmt = Set power management
14823 * @del_station = Delete station
14824 * @add_station = Add station
14825 * @set_pmksa = Set pmksa
14826 * @del_pmksa = Delete pmksa
14827 * @flush_pmksa = Flush pmksa
14828 * @update_ft_ies = Update FT IEs
14829 * @tdls_mgmt = Tdls management
14830 * @tdls_oper = Tdls operation
14831 * @set_rekey_data = Set rekey data
14832 * @sched_scan_start = Scheduled scan start
14833 * @sched_scan_stop = Scheduled scan stop
14834 * @resume = Resume wlan
14835 * @suspend = Suspend wlan
14836 * @set_mac_acl = Set mac acl
14837 * @testmode_cmd = Test mode command
14838 * @set_ap_chanwidth = Set AP channel bandwidth
14839 * @dump_survey = Dump survey
14840 * @key_mgmt_set_pmk = Set pmk key management
14841 */
14842static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
14843 .add_virtual_intf = wlan_hdd_add_virtual_intf,
14844 .del_virtual_intf = wlan_hdd_del_virtual_intf,
14845 .change_virtual_intf = wlan_hdd_cfg80211_change_iface,
14846 .change_station = wlan_hdd_change_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014847 .start_ap = wlan_hdd_cfg80211_start_ap,
14848 .change_beacon = wlan_hdd_cfg80211_change_beacon,
14849 .stop_ap = wlan_hdd_cfg80211_stop_ap,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014850 .change_bss = wlan_hdd_cfg80211_change_bss,
14851 .add_key = wlan_hdd_cfg80211_add_key,
14852 .get_key = wlan_hdd_cfg80211_get_key,
14853 .del_key = wlan_hdd_cfg80211_del_key,
14854 .set_default_key = wlan_hdd_cfg80211_set_default_key,
14855 .scan = wlan_hdd_cfg80211_scan,
14856 .connect = wlan_hdd_cfg80211_connect,
14857 .disconnect = wlan_hdd_cfg80211_disconnect,
14858 .join_ibss = wlan_hdd_cfg80211_join_ibss,
14859 .leave_ibss = wlan_hdd_cfg80211_leave_ibss,
14860 .set_wiphy_params = wlan_hdd_cfg80211_set_wiphy_params,
14861 .set_tx_power = wlan_hdd_cfg80211_set_txpower,
14862 .get_tx_power = wlan_hdd_cfg80211_get_txpower,
14863 .remain_on_channel = wlan_hdd_cfg80211_remain_on_channel,
14864 .cancel_remain_on_channel = wlan_hdd_cfg80211_cancel_remain_on_channel,
14865 .mgmt_tx = wlan_hdd_mgmt_tx,
14866 .mgmt_tx_cancel_wait = wlan_hdd_cfg80211_mgmt_tx_cancel_wait,
14867 .set_default_mgmt_key = wlan_hdd_set_default_mgmt_key,
14868 .set_txq_params = wlan_hdd_set_txq_params,
Himanshu Agarwal37e42412016-07-21 14:35:09 +053014869 .dump_station = wlan_hdd_cfg80211_dump_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014870 .get_station = wlan_hdd_cfg80211_get_station,
14871 .set_power_mgmt = wlan_hdd_cfg80211_set_power_mgmt,
14872 .del_station = wlan_hdd_cfg80211_del_station,
14873 .add_station = wlan_hdd_cfg80211_add_station,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014874 .set_pmksa = wlan_hdd_cfg80211_set_pmksa,
14875 .del_pmksa = wlan_hdd_cfg80211_del_pmksa,
14876 .flush_pmksa = wlan_hdd_cfg80211_flush_pmksa,
Deepak Dhamdhere9f09e752016-01-09 23:17:25 -080014877#if defined(KERNEL_SUPPORT_11R_CFG80211)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014878 .update_ft_ies = wlan_hdd_cfg80211_update_ft_ies,
14879#endif
14880#ifdef FEATURE_WLAN_TDLS
14881 .tdls_mgmt = wlan_hdd_cfg80211_tdls_mgmt,
14882 .tdls_oper = wlan_hdd_cfg80211_tdls_oper,
14883#endif
14884#ifdef WLAN_FEATURE_GTK_OFFLOAD
14885 .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data,
14886#endif /* WLAN_FEATURE_GTK_OFFLOAD */
14887#ifdef FEATURE_WLAN_SCAN_PNO
14888 .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start,
14889 .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop,
14890#endif /*FEATURE_WLAN_SCAN_PNO */
14891 .resume = wlan_hdd_cfg80211_resume_wlan,
14892 .suspend = wlan_hdd_cfg80211_suspend_wlan,
14893 .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl,
14894#ifdef WLAN_NL80211_TESTMODE
14895 .testmode_cmd = wlan_hdd_cfg80211_testmode,
14896#endif
14897#ifdef QCA_HT_2040_COEX
14898 .set_ap_chanwidth = wlan_hdd_cfg80211_set_ap_channel_width,
14899#endif
14900 .dump_survey = wlan_hdd_cfg80211_dump_survey,
Abhishek Singh1bdb1572015-10-16 16:24:19 +053014901#ifdef CHANNEL_SWITCH_SUPPORTED
14902 .channel_switch = wlan_hdd_cfg80211_channel_switch,
14903#endif
Manjunathappa Prakash59f861d2016-04-21 10:33:31 -070014904 .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch,
Vidyullatha, Kanchanapally528789e2016-05-11 20:38:37 +053014905#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
14906 defined(CFG80211_ABORT_SCAN)
14907 .abort_scan = wlan_hdd_cfg80211_abort_scan,
14908#endif
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080014909};